diff options
Diffstat (limited to 'disk/part_efi.c')
-rw-r--r-- | disk/part_efi.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/disk/part_efi.c b/disk/part_efi.c index 71c3cb3f78d..2973d52f6ab 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -428,11 +428,11 @@ int write_gpt_table(struct blk_desc *dev_desc, return -1; } -int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, - disk_partition_t *partitions, int parts) +int gpt_fill_pte(struct blk_desc *dev_desc, + gpt_header *gpt_h, gpt_entry *gpt_e, + disk_partition_t *partitions, int parts) { lbaint_t offset = (lbaint_t)le64_to_cpu(gpt_h->first_usable_lba); - lbaint_t start; lbaint_t last_usable_lba = (lbaint_t) le64_to_cpu(gpt_h->last_usable_lba); int i, k; @@ -445,27 +445,44 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, char *str_type_guid; unsigned char *bin_type_guid; #endif + size_t hdr_start = gpt_h->my_lba; + size_t hdr_end = hdr_start + 1; + + size_t pte_start = gpt_h->partition_entry_lba; + size_t pte_end = pte_start + + gpt_h->num_partition_entries * gpt_h->sizeof_partition_entry / + dev_desc->blksz; for (i = 0; i < parts; i++) { /* partition starting lba */ - start = partitions[i].start; - if (start && (start < offset)) { - printf("Partition overlap\n"); - return -1; - } + lbaint_t start = partitions[i].start; + lbaint_t size = partitions[i].size; + if (start) { - gpt_e[i].starting_lba = cpu_to_le64(start); - offset = start + partitions[i].size; + offset = start + size; } else { - gpt_e[i].starting_lba = cpu_to_le64(offset); - offset += partitions[i].size; + start = offset; + offset += size; + } + + /* + * If our partition overlaps with either the GPT + * header, or the partition entry, reject it. + */ + if (((start <= hdr_end && hdr_start <= (start + size)) || + (start <= pte_end && pte_start <= (start + size)))) { + printf("Partition overlap\n"); + return -1; } + + gpt_e[i].starting_lba = cpu_to_le64(start); + if (offset > (last_usable_lba + 1)) { printf("Partitions layout exceds disk size\n"); return -1; } /* partition ending lba */ - if ((i == parts - 1) && (partitions[i].size == 0)) + if ((i == parts - 1) && (size == 0)) /* extend the last partition to maximuim */ gpt_e[i].ending_lba = gpt_h->last_usable_lba; else @@ -525,7 +542,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, debug("%s: name: %s offset[%d]: 0x" LBAF " size[%d]: 0x" LBAF "\n", __func__, partitions[i].name, i, - offset, i, partitions[i].size); + offset, i, size); } return 0; @@ -534,6 +551,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, static uint32_t partition_entries_offset(struct blk_desc *dev_desc) { uint32_t offset_blks = 2; + uint32_t __maybe_unused offset_bytes; int __maybe_unused config_offset; #if defined(CONFIG_EFI_PARTITION_ENTRIES_OFF) @@ -545,8 +563,9 @@ static uint32_t partition_entries_offset(struct blk_desc *dev_desc) * the disk) for the entries can be set in * CONFIG_EFI_PARTITION_ENTRIES_OFF. */ - offset_blks = + offset_bytes = PAD_TO_BLOCKSIZE(CONFIG_EFI_PARTITION_ENTRIES_OFF, dev_desc); + offset_blks = offset_bytes / dev_desc->blksz; #endif #if defined(CONFIG_OF_CONTROL) @@ -558,8 +577,10 @@ static uint32_t partition_entries_offset(struct blk_desc *dev_desc) config_offset = fdtdec_get_config_int(gd->fdt_blob, "u-boot,efi-partition-entries-offset", -EINVAL); - if (config_offset != -EINVAL) - offset_blks = PAD_TO_BLOCKSIZE(config_offset, dev_desc); + if (config_offset != -EINVAL) { + offset_bytes = PAD_TO_BLOCKSIZE(config_offset, dev_desc); + offset_blks = offset_bytes / dev_desc->blksz; + } #endif debug("efi: partition entries offset (in blocks): %d\n", offset_blks); @@ -627,7 +648,7 @@ int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid, goto err; /* Generate partition entries */ - ret = gpt_fill_pte(gpt_h, gpt_e, partitions, parts_count); + ret = gpt_fill_pte(dev_desc, gpt_h, gpt_e, partitions, parts_count); if (ret) goto err; |