Skip to contentSkip to conversation

fastboot: handle flash write to GPT partition

PATCH Superseded Steve Rae 2 participants 4 messages Dec 9, 2014 – Dec 11, 2014

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Steve Rae

author
#0 lore raw

PATCH v2 1/1 fastboot: handle flash write to GPT partition

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.

---

Changes in v2:
add validation of the GPT before writing to flash (suggested by: Lukasz Majewski <[email protected]>)

 README          |  7 +++++++
 common/fb_mmc.c | 26 +++++++++++++++++++++++---
 disk/part_efi.c | 37 +++++++++++++++++++++++++++++++++++++
 include/part.h  | 10 ++++++++++
 4 files changed, 77 insertions(+), 3 deletions(-)
README +7 -0
index 4ca04d0..5f50cdd 100644
@@ -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
common/fb_mmc.c +23 -3
index fb06d8a..a646a7b 100644
@@ -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;
disk/part_efi.c +37 -0
index efed58f..86cb160 100644
@@ -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
 
 /*
include/part.h +10 -0
index a496a4a..9cfa4c9 100644
@@ -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 */
Signature · 1 line
1.8.5
#1 lore raw

PATCH v2 1/1 fastboot: handle flash write to GPT partition

Hi Steve,

Quoted 93 lines

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.

---

Changes in v2:
add validation of the GPT before writing to flash (suggested by: Lukasz Majewski <[email protected]>)

 README          |  7 +++++++
 common/fb_mmc.c | 26 +++++++++++++++++++++++---
 disk/part_efi.c | 37 +++++++++++++++++++++++++++++++++++++
 include/part.h  | 10 ++++++++++
 4 files changed, 77 insertions(+), 3 deletions(-)
README +0 -0
index 4ca04d0..5f50cdd 100644
@@ -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.

README +2 -0
+		CONFIG_FASTBOOT_GPT_NAME
+		The fastboot "flash" command supports writing the

downloaded

README +1 -0
+		image to the Protective MBR and the Primary GUID

Partition

README +1 -0
+		Table. This occurs when the specified "partition

name" on the

README +2 -0
+		"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

common/fb_mmc.c +14 -3
index fb06d8a..a646a7b 100644
@@ -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 */

common/fb_mmc.c +1 -0
+		info.size = (2 + (GPT_ENTRY_NUMBERS *

GPT_ENTRY_SIZE) / blksz); +

common/fb_mmc.c +1 -0
+		if (is_valid_gpt_primary(download_buffer,

dev_desc->blksz)) {

common/fb_mmc.c +1 -0
+			printf("%s: invalid GPT - refusing to write

to flash\n",

common/fb_mmc.c void fb_mmc_flash_write(const char *cmd, void *download_buffer, · line 99

Quoted 4 lines
common/fb_mmc.c +4 -0
+			       __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].

Quoted 9 lines
common/fb_mmc.c +1 -0
+	} else if (get_partition_info_efi_by_name(dev_desc, cmd,

&info)) { error("cannot find partition: '%s'\n", cmd);

common/fb_mmc.c +0 -0
 		fastboot_fail("cannot find partition");
 		return;
disk/part_efi.c +0 -0
index efed58f..86cb160 100644

disk/part_efi.c err: · line 459

Quoted 5 lines
disk/part_efi.c +2 -0
@@ -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]).

Quoted 64 lines
disk/part_efi.c +27 -0
+{
+	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));

disk/part_efi.c +1 -0
+	if (gpt_h->partition_entry_array_crc32 !=

cpu_to_le32(calc_crc32)) {

disk/part_efi.c +1 -0
+		printf("%s: 'partition_entry_array_crc32' is

invalid\n",

disk/part_efi.c +5 -0
+		       __func__);
+		rc += 1;
+	}
+	return rc;
+}
 #endif
 
 /*
include/part.h +0 -0
index a496a4a..9cfa4c9 100644
@@ -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,

include/part.h +3 -0
 		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 */

Signature · 5 lines
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
author
#2 lore raw

PATCH v2 1/1 fastboot: handle flash write to GPT partition

Hi Lukasz,

Quoted 102 lines · Lukasz Majewski

Hi Steve,

Quoted 93 lines

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.

---

Changes in v2:
add validation of the GPT before writing to flash (suggested by: Lukasz Majewski <[email protected]>)

  README          |  7 +++++++
  common/fb_mmc.c | 26 +++++++++++++++++++++++---
  disk/part_efi.c | 37 +++++++++++++++++++++++++++++++++++++
  include/part.h  | 10 ++++++++++
  4 files changed, 77 insertions(+), 3 deletions(-)
README +0 -0
index 4ca04d0..5f50cdd 100644
@@ -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.

README +2 -0
+		CONFIG_FASTBOOT_GPT_NAME
+		The fastboot "flash" command supports writing the

downloaded

README +1 -0
+		image to the Protective MBR and the Primary GUID

Partition

README +1 -0
+		Table. This occurs when the specified "partition

name" on the

README +2 -0
+		"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

common/fb_mmc.c +14 -3
index fb06d8a..a646a7b 100644
@@ -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 */

common/fb_mmc.c +1 -0
+		info.size = (2 + (GPT_ENTRY_NUMBERS *

GPT_ENTRY_SIZE) / blksz); +

common/fb_mmc.c +1 -0
+		if (is_valid_gpt_primary(download_buffer,

dev_desc->blksz)) {

common/fb_mmc.c +1 -0
+			printf("%s: invalid GPT - refusing to write

to flash\n",

common/fb_mmc.c void fb_mmc_flash_write(const char *cmd, void *download_buffer, · line 99

Quoted 4 lines
common/fb_mmc.c +4 -0
+			       __func__);
+			fastboot_fail("invalid GPT partition");
+			return;
+		}

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

Quoted 2 lines

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

OK -- added "prepare and write Backup GPT" in v3

Quoted 11 lines
Quoted 11 lines
common/fb_mmc.c +1 -0
+	} 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;

disk/part_efi.c +0 -0
index efed58f..86cb160 100644
@@ -455,6 +455,43 @@ err:
  	free(gpt_h);
  	return ret;
Quoted 8 lines

disk/part_efi.c err: · line 459

Quoted 3 lines
disk/part_efi.c +2 -0
  }
+
+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]).

OK - I changed the name, however, it still can only handle a buffer which contains:
- 512 bytes of MBR, followed by
- 512 bytes of GPT Header, followed by
the GPT Entries at the specified offset (typically 2 * 512 bytes) Thus, it cannot be used for the Backup GPT anyway....

Quoted 68 lines
Quoted 65 lines
disk/part_efi.c +27 -0
+{
+	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));

disk/part_efi.c +1 -0
+	if (gpt_h->partition_entry_array_crc32 !=

cpu_to_le32(calc_crc32)) {

disk/part_efi.c +1 -0
+		printf("%s: 'partition_entry_array_crc32' is

invalid\n",

disk/part_efi.c +5 -0
+		       __func__);
+		rc += 1;
+	}
+	return rc;
+}
  #endif
 
  /*
include/part.h +0 -0
index a496a4a..9cfa4c9 100644
@@ -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);

include/part.h +3 -0
+
+/**
+ * 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 */
#3 lore raw

PATCH v2 1/1 fastboot: handle flash write to GPT partition

Hi Steve,

Quoted 134 lines

Hi Lukasz,

Quoted 106 lines · Lukasz Majewski

Hi Steve,

Quoted 96 lines

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.

---

Changes in v2:
add validation of the GPT before writing to flash (suggested by: Lukasz Majewski <[email protected]>)

  README          |  7 +++++++
  common/fb_mmc.c | 26 +++++++++++++++++++++++---
  disk/part_efi.c | 37 +++++++++++++++++++++++++++++++++++++
  include/part.h  | 10 ++++++++++
  4 files changed, 77 insertions(+), 3 deletions(-)
README +0 -0
index 4ca04d0..5f50cdd 100644
@@ -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.

README +2 -0
+		CONFIG_FASTBOOT_GPT_NAME
+		The fastboot "flash" command supports writing the

downloaded

README +1 -0
+		image to the Protective MBR and the Primary GUID

Partition

README +1 -0
+		Table. This occurs when the specified "partition

name" on the

README +2 -0
+		"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

common/fb_mmc.c +5 -0
index fb06d8a..a646a7b 100644
@@ -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) {

common/fb_mmc.c +9 -3
-	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 */

common/fb_mmc.c +1 -0
+		info.size = (2 + (GPT_ENTRY_NUMBERS *

GPT_ENTRY_SIZE) / blksz); +

common/fb_mmc.c +1 -0
+		if (is_valid_gpt_primary(download_buffer,

dev_desc->blksz)) {

common/fb_mmc.c +1 -0
+			printf("%s: invalid GPT - refusing to

write to flash\n",

common/fb_mmc.c void fb_mmc_flash_write(const char *cmd, void *download_buffer, · line 99

Quoted 4 lines
common/fb_mmc.c +4 -0
+			       __func__);
+			fastboot_fail("invalid GPT partition");
+			return;
+		}

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

Quoted 2 lines

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

OK -- added "prepare and write Backup GPT" in v3

Quoted 11 lines
Quoted 11 lines
common/fb_mmc.c +1 -0
+	} 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;

disk/part_efi.c +0 -0
index efed58f..86cb160 100644
@@ -455,6 +455,43 @@ err:
  	free(gpt_h);
  	return ret;
Quoted 8 lines

disk/part_efi.c err: · line 459

Quoted 3 lines
disk/part_efi.c +2 -0
  }
+
+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]).

Quoted 6 lines

OK - I changed the name, however, it still can only handle a buffer which contains:
- 512 bytes of MBR, followed by
- 512 bytes of GPT Header, followed by
the GPT Entries at the specified offset (typically 2 * 512 bytes) Thus, it cannot be used for the Backup GPT anyway....

I think that it should be possible to reuse the code:

1. There is "is_pmbr_valid()" function @ part_efi.c - so you don't need to check pmbr validity in the is_valid_gpt_buf function.

2. If 1. is done, then one function can be used to check CRC's for primary and secondary GPT headers and entries (as is done in the print_part_efi()).

Quoted 71 lines
Quoted 71 lines
Quoted 68 lines
disk/part_efi.c +27 -0
+{
+	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));

disk/part_efi.c +1 -0
+	if (gpt_h->partition_entry_array_crc32 !=

cpu_to_le32(calc_crc32)) {

disk/part_efi.c +1 -0
+		printf("%s: 'partition_entry_array_crc32' is

invalid\n",

disk/part_efi.c +5 -0
+		       __func__);
+		rc += 1;
+	}
+	return rc;
+}
  #endif
 
  /*
include/part.h +0 -0
index a496a4a..9cfa4c9 100644
@@ -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 */
Signature · 5 lines
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group