fastboot: Support defining raw partitions without a partition table
authorFilip Brozovic <fbrozovic@gmail.com>
Mon, 29 Jun 2020 11:14:37 +0000 (13:14 +0200)
committerMarek Vasut <marex@denx.de>
Tue, 1 Sep 2020 12:47:43 +0000 (14:47 +0200)
Add support for defining raw fastboot partitions in eMMC by specifying
the offset and size in an environment variable. Optionally, the eMMC
hardware partition number may also be specified.

This makes it possible to e.g. update only part of the eMMC boot
partition, instead of having to write the entire partition.

Signed-off-by: Filip Brozovic <fbrozovic@gmail.com>
doc/android/fastboot.rst
drivers/fastboot/fb_mmc.c

index de3f6c37d7d52c7749be8fe8d625dd867239a675..2877c3cbaaae175fdcf266bd8d051f9670618340 100644 (file)
@@ -85,6 +85,25 @@ for example::
 
     fastboot_partition_alias_boot=LNX
 
+Raw partition descriptors
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In cases where no partition table is present, a raw partition descriptor can be
+defined, specifying the offset, size, and optionally the MMC hardware partition
+number for a given partition name.
+
+This is useful when using fastboot to flash files (e.g. SPL or U-Boot) to a
+specific offset in the eMMC boot partition, without having to update the entire
+boot partition.
+
+To define a raw partition descriptor, add an environment variable similar to::
+
+    fastboot_raw_partition_<raw partition name>=<offset> <size> [mmcpart <num>]
+
+for example::
+
+    fastboot_raw_partition_boot=0x100 0x1f00 mmcpart 1
+
 Variable overrides
 ^^^^^^^^^^^^^^^^^^
 
index b2f8932e1c7a67ca1843b4428a74fc1d33f99e29..ae8e8e512f2ecd8dacc26cee210f1fd1aaaa3973 100644 (file)
@@ -50,6 +50,48 @@ static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
        return ret;
 }
 
+static int raw_part_get_info_by_name(struct blk_desc *dev_desc,
+               const char *name, struct disk_partition *info, int *mmcpart)
+{
+       /* strlen("fastboot_raw_partition_") + PART_NAME_LEN + 1 */
+       char env_desc_name[23 + PART_NAME_LEN + 1];
+       char *raw_part_desc;
+       const char *argv[2];
+       const char **parg = argv;
+
+       /* check for raw partition descriptor */
+       strcpy(env_desc_name, "fastboot_raw_partition_");
+       strncat(env_desc_name, name, PART_NAME_LEN);
+       raw_part_desc = strdup(env_get(env_desc_name));
+       if (raw_part_desc == NULL)
+               return -ENODEV;
+
+       /*
+        * parse partition descriptor
+        *
+        * <lba_start> <lba_size> [mmcpart <num>]
+        */
+       for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
+               *parg = strsep(&raw_part_desc, " ");
+               if (*parg == NULL) {
+                       pr_err("Invalid number of arguments.\n");
+                       return -ENODEV;
+               }
+       }
+
+       info->start = simple_strtoul(argv[0], NULL, 0);
+       info->size = simple_strtoul(argv[1], NULL, 0);
+       info->blksz = dev_desc->blksz;
+       strncpy((char *)info->name, name, PART_NAME_LEN);
+
+       if (raw_part_desc) {
+               if (strcmp(strsep(&raw_part_desc, " "), "mmcpart") == 0)
+                       *mmcpart = simple_strtoul(raw_part_desc, NULL, 0);
+       }
+
+       return 0;
+}
+
 /**
  * fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE
  *
@@ -376,7 +418,8 @@ int fastboot_mmc_get_part_info(const char *part_name,
                               struct blk_desc **dev_desc,
                               struct disk_partition *part_info, char *response)
 {
-       int r;
+       int r = 0;
+       int mmcpart;
 
        *dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
        if (!*dev_desc) {
@@ -388,10 +431,12 @@ int fastboot_mmc_get_part_info(const char *part_name,
                return -ENOENT;
        }
 
-       r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
-       if (r < 0) {
-               fastboot_fail("partition not found", response);
-               return r;
+       if (raw_part_get_info_by_name(*dev_desc, part_name, part_info, &mmcpart) < 0) {
+               r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
+               if (r < 0) {
+                       fastboot_fail("partition not found", response);
+                       return r;
+               }
        }
 
        return r;
@@ -410,6 +455,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
 {
        struct blk_desc *dev_desc;
        struct disk_partition info;
+       int mmcpart = 0;
 
        dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
        if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
@@ -482,7 +528,13 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
        }
 #endif
 
-       if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
+       if (raw_part_get_info_by_name(dev_desc, cmd, &info, &mmcpart) == 0) {
+               if (blk_dselect_hwpart(dev_desc, mmcpart)) {
+                       pr_err("Failed to select hwpart\n");
+                       fastboot_fail("Failed to select hwpart", response);
+                       return;
+               }
+       } else if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
                pr_err("cannot find partition: '%s'\n", cmd);
                fastboot_fail("cannot find partition", response);
                return;
@@ -524,11 +576,11 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
  */
 void fastboot_mmc_erase(const char *cmd, char *response)
 {
-       int ret;
        struct blk_desc *dev_desc;
        struct disk_partition info;
        lbaint_t blks, blks_start, blks_size, grp_size;
        struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+       int mmcpart = 0;
 
        if (mmc == NULL) {
                pr_err("invalid mmc device\n");
@@ -562,8 +614,13 @@ void fastboot_mmc_erase(const char *cmd, char *response)
        }
 #endif
 
-       ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
-       if (ret < 0) {
+       if (raw_part_get_info_by_name(dev_desc, cmd, &info, &mmcpart) == 0) {
+               if (blk_dselect_hwpart(dev_desc, mmcpart)) {
+                       pr_err("Failed to select hwpart\n");
+                       fastboot_fail("Failed to select hwpart", response);
+                       return;
+               }
+       } else if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
                pr_err("cannot find partition: '%s'\n", cmd);
                fastboot_fail("cannot find partition", response);
                return;