Commit bf8940d35b91ef87e0e4e691c5d8cc356fcae035

Authored by Maxime Ripard
Committed by Tom Rini
1 parent 1f8690aa95

fastboot: Implement NAND backend

So far the fastboot code was only supporting MMC-backed devices for its
flashing operations (flash and erase).

Add a storage backend for NAND-backed devices.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Showing 4 changed files with 223 additions and 1 deletions Side-by-side Diff

... ... @@ -276,9 +276,14 @@
276 276 obj-y += stdio.o
277 277  
278 278 # This option is not just y/n - it can have a numeric value
279   -ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
  279 +ifdef CONFIG_FASTBOOT_FLASH
280 280 obj-y += aboot.o
  281 +ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
281 282 obj-y += fb_mmc.o
  283 +endif
  284 +ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
  285 +obj-y += fb_nand.o
  286 +endif
282 287 endif
283 288  
284 289 obj-$(CONFIG_CMD_BLOB) += cmd_blob.o
  1 +/*
  2 + * Copyright 2014 Broadcom Corporation.
  3 + * Copyright 2015 Free Electrons.
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +#include <config.h>
  9 +#include <common.h>
  10 +
  11 +#include <aboot.h>
  12 +#include <fastboot.h>
  13 +#include <sparse_format.h>
  14 +
  15 +#include <linux/mtd/mtd.h>
  16 +#include <jffs2/jffs2.h>
  17 +#include <nand.h>
  18 +
  19 +static char *response_str;
  20 +
  21 +struct fb_nand_sparse {
  22 + nand_info_t *nand;
  23 + struct part_info *part;
  24 +};
  25 +
  26 +static int fb_nand_lookup(const char *partname, char *response,
  27 + nand_info_t **nand,
  28 + struct part_info **part)
  29 +{
  30 + struct mtd_device *dev;
  31 + int ret;
  32 + u8 pnum;
  33 +
  34 + ret = mtdparts_init();
  35 + if (ret) {
  36 + error("Cannot initialize MTD partitions\n");
  37 + fastboot_fail(response_str, "cannot init mtdparts");
  38 + return ret;
  39 + }
  40 +
  41 + ret = find_dev_and_part(partname, &dev, &pnum, part);
  42 + if (ret) {
  43 + error("cannot find partition: '%s'", partname);
  44 + fastboot_fail(response_str, "cannot find partition");
  45 + return ret;
  46 + }
  47 +
  48 + if (dev->id->type != MTD_DEV_TYPE_NAND) {
  49 + error("partition '%s' is not stored on a NAND device",
  50 + partname);
  51 + fastboot_fail(response_str, "not a NAND device");
  52 + return -EINVAL;
  53 + }
  54 +
  55 + *nand = &nand_info[dev->id->num];
  56 +
  57 + return 0;
  58 +}
  59 +
  60 +static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
  61 +{
  62 + nand_erase_options_t opts;
  63 + int ret;
  64 +
  65 + memset(&opts, 0, sizeof(opts));
  66 + opts.offset = part->offset;
  67 + opts.length = part->size;
  68 + opts.quiet = 1;
  69 +
  70 + printf("Erasing blocks 0x%llx to 0x%llx\n",
  71 + part->offset, part->offset + part->size);
  72 +
  73 + ret = nand_erase_opts(nand, &opts);
  74 + if (ret)
  75 + return ret;
  76 +
  77 + printf("........ erased 0x%llx bytes from '%s'\n",
  78 + part->size, part->name);
  79 +
  80 + return 0;
  81 +}
  82 +
  83 +static int _fb_nand_write(nand_info_t *nand, struct part_info *part,
  84 + void *buffer, unsigned int offset,
  85 + unsigned int length, size_t *written)
  86 +{
  87 + int flags = WITH_WR_VERIFY;
  88 +
  89 +#ifdef CONFIG_FASTBOOT_FLASH_NAND_TRIMFFS
  90 + flags |= WITH_DROP_FFS;
  91 +#endif
  92 +
  93 + return nand_write_skip_bad(nand, offset, &length, written,
  94 + part->size - (offset - part->offset),
  95 + buffer, flags);
  96 +}
  97 +
  98 +static int fb_nand_sparse_write(struct sparse_storage *storage,
  99 + void *priv,
  100 + unsigned int offset,
  101 + unsigned int size,
  102 + char *data)
  103 +{
  104 + struct fb_nand_sparse *sparse = priv;
  105 + size_t written;
  106 + int ret;
  107 +
  108 + ret = _fb_nand_write(sparse->nand, sparse->part, data,
  109 + offset * storage->block_sz,
  110 + size * storage->block_sz, &written);
  111 + if (ret < 0) {
  112 + printf("Failed to write sparse chunk\n");
  113 + return ret;
  114 + }
  115 +
  116 + return written / storage->block_sz;
  117 +}
  118 +
  119 +void fb_nand_flash_write(const char *partname, unsigned int session_id,
  120 + void *download_buffer, unsigned int download_bytes,
  121 + char *response)
  122 +{
  123 + struct part_info *part;
  124 + nand_info_t *nand = NULL;
  125 + int ret;
  126 +
  127 + /* initialize the response buffer */
  128 + response_str = response;
  129 +
  130 + ret = fb_nand_lookup(partname, response, &nand, &part);
  131 + if (ret) {
  132 + error("invalid NAND device");
  133 + fastboot_fail(response_str, "invalid NAND device");
  134 + return;
  135 + }
  136 +
  137 + if (is_sparse_image(download_buffer)) {
  138 + struct fb_nand_sparse sparse_priv;
  139 + sparse_storage_t sparse;
  140 +
  141 + sparse_priv.nand = nand;
  142 + sparse_priv.part = part;
  143 +
  144 + sparse.block_sz = nand->writesize;
  145 + sparse.start = part->offset / sparse.block_sz;
  146 + sparse.size = part->size / sparse.block_sz;
  147 + sparse.name = part->name;
  148 + sparse.write = fb_nand_sparse_write;
  149 +
  150 + ret = store_sparse_image(&sparse, &sparse_priv, session_id,
  151 + download_buffer);
  152 + } else {
  153 + printf("Flashing raw image at offset 0x%llx\n",
  154 + part->offset);
  155 +
  156 + ret = _fb_nand_write(nand, part, download_buffer, part->offset,
  157 + download_bytes, NULL);
  158 +
  159 + printf("........ wrote %u bytes to '%s'\n",
  160 + download_bytes, part->name);
  161 + }
  162 +
  163 + if (ret) {
  164 + fastboot_fail(response_str, "error writing the image");
  165 + return;
  166 + }
  167 +
  168 + fastboot_okay(response_str, "");
  169 +}
  170 +
  171 +void fb_nand_erase(const char *partname, char *response)
  172 +{
  173 + struct part_info *part;
  174 + nand_info_t *nand = NULL;
  175 + int ret;
  176 +
  177 + /* initialize the response buffer */
  178 + response_str = response;
  179 +
  180 + ret = fb_nand_lookup(partname, response, &nand, &part);
  181 + if (ret) {
  182 + error("invalid NAND device");
  183 + fastboot_fail(response_str, "invalid NAND device");
  184 + return;
  185 + }
  186 +
  187 + ret = _fb_nand_erase(nand, part);
  188 + if (ret) {
  189 + error("failed erasing from device %s", nand->name);
  190 + fastboot_fail(response_str, "failed erasing from device");
  191 + return;
  192 + }
  193 +
  194 + fastboot_okay(response_str, "");
  195 +}
drivers/usb/gadget/f_fastboot.c
... ... @@ -24,6 +24,9 @@
24 24 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
25 25 #include <fb_mmc.h>
26 26 #endif
  27 +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
  28 +#include <fb_nand.h>
  29 +#endif
27 30  
28 31 #define FASTBOOT_VERSION "0.4"
29 32  
... ... @@ -569,6 +572,11 @@
569 572 (void *)CONFIG_FASTBOOT_BUF_ADDR,
570 573 download_bytes, response);
571 574 #endif
  575 +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
  576 + fb_nand_flash_write(cmd, fastboot_flash_session_id,
  577 + (void *)CONFIG_FASTBOOT_BUF_ADDR,
  578 + download_bytes, response);
  579 +#endif
572 580 fastboot_flash_session_id++;
573 581 fastboot_tx_write_str(response);
574 582 }
... ... @@ -613,6 +621,9 @@
613 621  
614 622 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
615 623 fb_mmc_erase(cmd, response);
  624 +#endif
  625 +#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
  626 + fb_nand_erase(cmd, response);
616 627 #endif
617 628 fastboot_tx_write_str(response);
618 629 }
  1 +/*
  2 + * Copyright 2014 Broadcom Corporation.
  3 + * Copyright 2015 Free Electrons.
  4 + *
  5 + * SPDX-License-Identifier: GPL-2.0+
  6 + */
  7 +
  8 +void fb_nand_flash_write(const char *cmd, unsigned int session_id,
  9 + void *download_buffer, unsigned int download_bytes,
  10 + char *response);
  11 +void fb_nand_erase(const char *cmd, char *response);