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.
> 
> 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;
> +             }

IMHO some extra code to update secondary (backup) GPT is needed here.

A good example may be at part_efi.c - print_part_efi() function [1].

> +     } 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)

The name is a bit misleading - I rather though about something like
is_valid_gpt_buf() and write it in a similar way to is_valid_gpt()
which would allow using it for both primary and secondary GPTs (like in
[1]).

> +{
> +     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 */



-- 
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

Reply via email to