Hi Steve, > Implement a feature to allow fastboot to write the downloaded image > to the space reserved for the Protective MBR and the Primary GUID > Partition Table. > Additionally, prepare and write the Backup GUID Partition Table. > > Signed-off-by: Steve Rae <s...@broadcom.com> > --- > > Changes in v4: > fix bug with partition_entry_lba in Backup GPT > use common static functions > > Changes in v3: > - prefer leXX_to_cpu() over cpu_to_leXX() > - enhance calculation of pointer to GPT Entries > - prepare and write the Backup GPT > (requested by: Lukasz Majewski <l.majew...@samsung.com>) > > Changes in v2: > add validation of the GPT before writing to flash > (suggested by: Lukasz Majewski <l.majew...@samsung.com>) > > README | 9 ++++++ > common/fb_mmc.c | 26 ++++++++++++++-- > disk/part_efi.c | 93 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > include/part.h | 20 +++++++++++++ 4 files changed, 145 > insertions(+), 3 deletions(-) > > diff --git a/README b/README > index 4ca04d0..42ece99 100644 > --- a/README > +++ b/README > @@ -1773,6 +1773,15 @@ The following options need to be configured: > regarding the non-volatile storage device. Define > this to the eMMC device that fastboot should use to store the image. > > + CONFIG_FASTBOOT_GPT_NAME > + The fastboot "flash" command supports writing the > downloaded > + image to the Protective MBR and the Primary GUID > Partition > + Table. (Additionally, this downloaded image is > post-processed > + to generate and write the Backup GUID Partition > Table.) > + This occurs when the specified "partition name" on > the > + "fastboot flash" command line matches this value. > + Default is GPT_ENTRY_NAME (currently "gpt") if > undefined. + > - Journaling Flash filesystem support: > CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, > CONFIG_JFFS2_NAND_SIZE, CONFIG_JFFS2_NAND_DEV > diff --git a/common/fb_mmc.c b/common/fb_mmc.c > index fb06d8a..6ea3938 100644 > --- a/common/fb_mmc.c > +++ b/common/fb_mmc.c > @@ -4,12 +4,17 @@ > * SPDX-License-Identifier: GPL-2.0+ > */ > > +#include <config.h> > #include <common.h> > #include <fb_mmc.h> > #include <part.h> > #include <aboot.h> > #include <sparse_format.h> > > +#ifndef CONFIG_FASTBOOT_GPT_NAME > +#define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME > +#endif > + > /* The 64 defined bytes plus the '\0' */ > #define RESPONSE_LEN (64 + 1) > > @@ -62,7 +67,6 @@ static void write_raw_image(block_dev_desc_t > *dev_desc, disk_partition_t *info, void fb_mmc_flash_write(const char > *cmd, void *download_buffer, unsigned int download_bytes, char > *response) { > - int ret; > block_dev_desc_t *dev_desc; > disk_partition_t info; > > @@ -76,8 +80,24 @@ void fb_mmc_flash_write(const char *cmd, void > *download_buffer, return; > } > > - ret = get_partition_info_efi_by_name(dev_desc, cmd, &info); > - if (ret) { > + if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) { > + printf("%s: updating MBR, Primary and Backup > GPT(s)\n", > + __func__); > + if (is_valid_gpt_buf(dev_desc, download_buffer)) { > + printf("%s: invalid GPT - refusing to write > to flash\n", > + __func__); > + fastboot_fail("invalid GPT partition"); > + return; > + } > + if (write_mbr_and_gpt_partitions(dev_desc, > download_buffer)) { > + printf("%s: writing GPT partitions > failed\n", __func__); > + fastboot_fail("writing GPT partitions > failed"); > + return; > + } > + printf("........ success\n"); > + fastboot_okay(""); > + return; > + } else if (get_partition_info_efi_by_name(dev_desc, cmd, > &info)) { error("cannot find partition: '%s'\n", cmd); > fastboot_fail("cannot find partition"); > return; > diff --git a/disk/part_efi.c b/disk/part_efi.c > index 2c77f29..338010e 100644 > --- a/disk/part_efi.c > +++ b/disk/part_efi.c > @@ -161,6 +161,8 @@ static void prepare_backup_gpt_header(gpt_header > *gpt_h) val = le64_to_cpu(gpt_h->my_lba); > gpt_h->my_lba = gpt_h->alternate_lba; > gpt_h->alternate_lba = cpu_to_le64(val); > + gpt_h->partition_entry_lba = > + > cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1); > gpt_h->header_crc32 = 0; > calc_crc32 = efi_crc32((const unsigned char *)gpt_h, > @@ -545,6 +547,97 @@ err: > free(gpt_h); > return ret; > } > + > +int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf) > +{ > + gpt_header *gpt_h; > + gpt_entry *gpt_e; > + > + /* determine start of GPT Header in the buffer */ > + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * > + dev_desc->blksz); > + if (validate_gpt_header(gpt_h, > GPT_PRIMARY_PARTITION_TABLE_LBA, > + dev_desc->lba)) > + return -1; > + > + /* determine start of GPT Entries in the buffer */ > + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) * > + dev_desc->blksz); > + if (validate_gpt_entries(gpt_h, gpt_e)) > + return -1; > + > + return 0; > +} > + > +int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void > *buf) +{ > + gpt_header *gpt_h; > + gpt_entry *gpt_e; > + int gpt_e_blk_cnt; > + lbaint_t lba; > + int cnt; > + > + if (is_valid_gpt_buf(dev_desc, buf)) > + return -1; > + > + /* determine start of GPT Header in the buffer */ > + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * > + dev_desc->blksz); > + > + /* determine start of GPT Entries in the buffer */ > + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) * > + dev_desc->blksz); > + gpt_e_blk_cnt = > BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) * > + > le32_to_cpu(gpt_h->sizeof_partition_entry)), > + dev_desc); > + > + /* write MBR */ > + lba = 0; /* MBR is always at 0 */ > + cnt = 1; /* MBR (1 block) */ > + if (dev_desc->block_write(dev_desc->dev, lba, cnt, buf) != > cnt) { > + printf("%s: failed writing '%s' (%d blks at 0x" LBAF > ")\n", > + __func__, "MBR", cnt, lba); > + return 1; > + } > + > + /* write Primary GPT */ > + lba = GPT_PRIMARY_PARTITION_TABLE_LBA; > + cnt = 1; /* GPT Header (1 block) */ > + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != > cnt) { > + printf("%s: failed writing '%s' (%d blks at 0x" LBAF > ")\n", > + __func__, "Primary GPT Header", cnt, lba); > + return 1; > + } > + > + lba = le64_to_cpu(gpt_h->partition_entry_lba); > + cnt = gpt_e_blk_cnt; > + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != > cnt) { > + printf("%s: failed writing '%s' (%d blks at 0x" LBAF > ")\n", > + __func__, "Primary GPT Entries", cnt, lba); > + return 1; > + } > + > + prepare_backup_gpt_header(gpt_h); > + > + /* write Backup GPT */ > + lba = le64_to_cpu(gpt_h->partition_entry_lba); > + cnt = gpt_e_blk_cnt; > + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != > cnt) { > + printf("%s: failed writing '%s' (%d blks at 0x" LBAF > ")\n", > + __func__, "Backup GPT Entries", cnt, lba); > + return 1; > + } > + > + lba = le64_to_cpu(gpt_h->my_lba); > + cnt = 1; /* GPT Header (1 block) */ > + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != > cnt) { > + printf("%s: failed writing '%s' (%d blks at 0x" LBAF > ")\n", > + __func__, "Backup GPT Header", cnt, lba); > + return 1; > + } > + > + return 0; > +} > #endif > > /* > diff --git a/include/part.h b/include/part.h > index a496a4a..8ea9b30 100644 > --- a/include/part.h > +++ b/include/part.h > @@ -244,6 +244,26 @@ int gpt_fill_header(block_dev_desc_t *dev_desc, > gpt_header *gpt_h, */ > int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid, > disk_partition_t *partitions, const int parts_count); > + > +/** > + * is_valid_gpt_buf() - Ensure that the Primary GPT information is > valid > + * > + * @param dev_desc - block device descriptor > + * @param buf - buffer which contains the MBR and Primary GPT info > + * > + * @return - '0' on success, otherwise error > + */ > +int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf); > + > +/** > + * write_mbr_and_gpt_partitions() - write MBR, Primary GPT and > Backup GPT > + * > + * @param dev_desc - block device descriptor > + * @param buf - buffer which contains the MBR and Primary GPT info > + * > + * @return - '0' on success, otherwise error > + */ > +int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void > *buf); #endif > > #endif /* _PART_H */
Acked-by: Lukasz Majewski <l.majew...@samsung.com> Tested-by: Lukasz Majewski <l.majew...@samsung.com> Test HW: Exynos4412 - trats2 To Marek: This patch cleanly applies to master (SHA1:b9206e61f3d87535ac4f4b0b858e674fd1edfeaf) not u-boot-usb. Therefore I cannot apply it to u-boot-usb based -dfu tree. We can either wait up the moment when -dfu get in sync with mainline or apply this patch to mainline directly. -- Best regards, Lukasz Majewski Samsung R&D Institute Poland (SRPOL) | Linux Platform Group _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot