[U-Boot] [PATCH v2] fastboot: handle flash write to GPT partition
Steve Rae
srae at broadcom.com
Tue Dec 9 01:34:11 CET 2014
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 <srae at broadcom.com>
---
Changes in v2:
add validation of the GPT before writing to flash
(suggested by: Lukasz Majewski <l.majewski at 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
More information about the U-Boot
mailing list