diff options
-rw-r--r-- | disk/part_efi.c | 110 | ||||
-rw-r--r-- | include/part.h | 35 |
2 files changed, 145 insertions, 0 deletions
diff --git a/disk/part_efi.c b/disk/part_efi.c index ea9c615ee5..40f0b361b4 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; diff --git a/include/part.h b/include/part.h index 8b5ac12e2b..720a867783 100644 --- a/include/part.h +++ b/include/part.h @@ -267,6 +267,41 @@ int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf); * @return - '0' on success, otherwise error */ int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf); + +/** + * gpt_verify_headers() - Function to read and CRC32 check of the GPT's header + * and partition table entries (PTE) + * + * As a side effect if sets gpt_head and gpt_pte so they point to GPT data. + * + * @param dev_desc - block device descriptor + * @param gpt_head - pointer to GPT header data read from medium + * @param gpt_pte - pointer to GPT partition table enties read from medium + * + * @return - '0' on success, otherwise error + */ +int gpt_verify_headers(block_dev_desc_t *dev_desc, gpt_header *gpt_head, + gpt_entry **gpt_pte); + +/** + * gpt_verify_partitions() - Function to check if partitions' name, start and + * size correspond to '$partitions' env variable + * + * This function checks if on medium stored GPT data is in sync with information + * provided in '$partitions' environment variable. Specificially, name, start + * and size of the partition is checked. + * + * @param dev_desc - block device descriptor + * @param partitions - partition data read from '$partitions' env variable + * @param parts - number of partitions read from '$partitions' env variable + * @param gpt_head - pointer to GPT header data read from medium + * @param gpt_pte - pointer to GPT partition table enties read from medium + * + * @return - '0' on success, otherwise error + */ +int gpt_verify_partitions(block_dev_desc_t *dev_desc, + disk_partition_t *partitions, int parts, + gpt_header *gpt_head, gpt_entry **gpt_pte); #endif #endif /* _PART_H */ |