aboutsummaryrefslogtreecommitdiff
path: root/disk/part_efi.c
diff options
context:
space:
mode:
Diffstat (limited to 'disk/part_efi.c')
-rw-r--r--disk/part_efi.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/disk/part_efi.c b/disk/part_efi.c
index ea9c615ee58..40f0b361b4c 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -578,6 +578,116 @@ err:
return ret;
}
+static void gpt_convert_efi_name_to_char(char *s, efi_char16_t *es, int n)
+{
+ char *ess = (char *)es;
+ int i, j;
+
+ memset(s, '\0', n);
+
+ for (i = 0, j = 0; j < n; i += 2, j++) {
+ s[j] = ess[i];
+ if (!ess[i])
+ return;
+ }
+}
+
+int gpt_verify_headers(block_dev_desc_t *dev_desc, gpt_header *gpt_head,
+ gpt_entry **gpt_pte)
+{
+ /*
+ * This function validates AND
+ * fills in the GPT header and PTE
+ */
+ if (is_gpt_valid(dev_desc,
+ GPT_PRIMARY_PARTITION_TABLE_LBA,
+ gpt_head, gpt_pte) != 1) {
+ printf("%s: *** ERROR: Invalid GPT ***\n",
+ __func__);
+ return -1;
+ }
+ if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
+ gpt_head, gpt_pte) != 1) {
+ printf("%s: *** ERROR: Invalid Backup GPT ***\n",
+ __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int gpt_verify_partitions(block_dev_desc_t *dev_desc,
+ disk_partition_t *partitions, int parts,
+ gpt_header *gpt_head, gpt_entry **gpt_pte)
+{
+ char efi_str[PARTNAME_SZ + 1];
+ u64 gpt_part_size;
+ gpt_entry *gpt_e;
+ int ret, i;
+
+ ret = gpt_verify_headers(dev_desc, gpt_head, gpt_pte);
+ if (ret)
+ return ret;
+
+ gpt_e = *gpt_pte;
+
+ for (i = 0; i < parts; i++) {
+ if (i == gpt_head->num_partition_entries) {
+ error("More partitions than allowed!\n");
+ return -1;
+ }
+
+ /* Check if GPT and ENV partition names match */
+ gpt_convert_efi_name_to_char(efi_str, gpt_e[i].partition_name,
+ PARTNAME_SZ + 1);
+
+ debug("%s: part: %2d name - GPT: %16s, ENV: %16s ",
+ __func__, i, efi_str, partitions[i].name);
+
+ if (strncmp(efi_str, (char *)partitions[i].name,
+ sizeof(partitions->name))) {
+ error("Partition name: %s does not match %s!\n",
+ efi_str, (char *)partitions[i].name);
+ return -1;
+ }
+
+ /* Check if GPT and ENV sizes match */
+ gpt_part_size = le64_to_cpu(gpt_e[i].ending_lba) -
+ le64_to_cpu(gpt_e[i].starting_lba) + 1;
+ debug("size(LBA) - GPT: %8llu, ENV: %8llu ",
+ gpt_part_size, (u64) partitions[i].size);
+
+ if (le64_to_cpu(gpt_part_size) != partitions[i].size) {
+ error("Partition %s size: %llu does not match %llu!\n",
+ efi_str, gpt_part_size, (u64) partitions[i].size);
+ return -1;
+ }
+
+ /*
+ * Start address is optional - check only if provided
+ * in '$partition' variable
+ */
+ if (!partitions[i].start) {
+ debug("\n");
+ continue;
+ }
+
+ /* Check if GPT and ENV start LBAs match */
+ debug("start LBA - GPT: %8llu, ENV: %8llu\n",
+ le64_to_cpu(gpt_e[i].starting_lba),
+ (u64) partitions[i].start);
+
+ if (le64_to_cpu(gpt_e[i].starting_lba) != partitions[i].start) {
+ error("Partition %s start: %llu does not match %llu!\n",
+ efi_str, le64_to_cpu(gpt_e[i].starting_lba),
+ (u64) partitions[i].start);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf)
{
gpt_header *gpt_h;