[U-Boot] [PATCH v4 2/2] fastboot: handle flash write to GPT partitions

Lukasz Majewski l.majewski at samsung.com
Tue Dec 16 15:17:12 CET 2014


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 <srae at 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.majewski at samsung.com>)
> 
> Changes in v2:
> add validation of the GPT before writing to flash
> (suggested by: Lukasz Majewski <l.majewski at 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.majewski at samsung.com>
Tested-by: Lukasz Majewski <l.majewski at 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


More information about the U-Boot mailing list