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.
Signed-off-by: Steve Rae <s...@broadcom.com> --- Changes in v2: add validation of the GPT before writing to flash (suggested by: Lukasz Majewski <l.majew...@samsung.com>) README | 7 +++++++ common/fb_mmc.c | 26 +++++++++++++++++++++++--- disk/part_efi.c | 37 +++++++++++++++++++++++++++++++++++++ include/part.h | 10 ++++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/README b/README index 4ca04d0..5f50cdd 100644 --- a/README +++ b/README @@ -1773,6 +1773,13 @@ 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. 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..a646a7b 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,9 +67,9 @@ 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; + lbaint_t blksz; /* initialize the response buffer */ response_str = response; @@ -76,8 +81,23 @@ 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 GUID Partition Table (including MBR)\n", + __func__); + /* start at Protective MBR */ + info.start = (GPT_PRIMARY_PARTITION_TABLE_LBA - 1); + blksz = dev_desc->blksz; + info.blksz = blksz; + /* assume that the Partition Entry Array starts in LBA 2 */ + info.size = (2 + (GPT_ENTRY_NUMBERS * GPT_ENTRY_SIZE) / blksz); + + if (is_valid_gpt_primary(download_buffer, dev_desc->blksz)) { + printf("%s: invalid GPT - refusing to write to flash\n", + __func__); + fastboot_fail("invalid GPT partition"); + 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 efed58f..86cb160 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -455,6 +455,43 @@ err: free(gpt_h); return ret; } + +int is_valid_gpt_primary(void *buf, unsigned long blksz) +{ + int rc = 0; + gpt_header *gpt_h; + gpt_entry *gpt_e; + gpt_header gpt_hdr; + uint32_t calc_crc32; + + /* GPT Header starts at "LBA[1]" in the buffer */ + gpt_h = buf + blksz; + if (gpt_h->signature != cpu_to_le64(GPT_HEADER_SIGNATURE)) { + printf("%s: 'signature' is invalid\n", __func__); + rc += 1; + } + + memcpy(&gpt_hdr, gpt_h, sizeof(gpt_header)); + gpt_hdr.header_crc32 = 0; + calc_crc32 = efi_crc32((const unsigned char *)&gpt_hdr, + le32_to_cpu(gpt_h->header_size)); + if (gpt_h->header_crc32 != cpu_to_le32(calc_crc32)) { + printf("%s: 'header_crc32' is invalid\n", __func__); + rc += 1; + } + + /* GPT Entries start at "LBA[2]" in the buffer */ + gpt_e = buf + (2 * blksz); + calc_crc32 = efi_crc32((const unsigned char *)gpt_e, + le32_to_cpu(gpt_h->num_partition_entries) * + le32_to_cpu(gpt_h->sizeof_partition_entry)); + if (gpt_h->partition_entry_array_crc32 != cpu_to_le32(calc_crc32)) { + printf("%s: 'partition_entry_array_crc32' is invalid\n", + __func__); + rc += 1; + } + return rc; +} #endif /* diff --git a/include/part.h b/include/part.h index a496a4a..9cfa4c9 100644 --- a/include/part.h +++ b/include/part.h @@ -244,6 +244,16 @@ 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_primary() - Ensure that the Primary GPT information is valid + * + * @param buf - buffer which contains the Primary GPT info + * @param blksz - block size (in bytes) + * + * @return - '0' on success, otherwise error + */ +int is_valid_gpt_primary(void *buf, unsigned long blksz); #endif #endif /* _PART_H */ -- 1.8.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot