X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=disk%2Fpart_efi.c;h=0af1e9248d0f867e949c29f2a1e2ab4fc69ab65b;hb=66669fcf809c1e3ff644b12e04e625d3737ffd8e;hp=612f0926b62bbceb8b35ef9fc6aa259145c35c95;hpb=dab5e3469d294a4e1ffed8407d296a78e02cc01f;p=u-boot diff --git a/disk/part_efi.c b/disk/part_efi.c index 612f0926b6..0af1e9248d 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include @@ -39,10 +41,10 @@ static inline u32 efi_crc32(const void *buf, u32 len) static int pmbr_part_valid(struct partition *part); static int is_pmbr_valid(legacy_mbr * mbr); -static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba, +static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba, gpt_header *pgpt_head, gpt_entry **pgpt_pte); -static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, - gpt_header * pgpt_head); +static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc, + gpt_header *pgpt_head); static int is_pte_valid(gpt_entry * pte); static char *print_efiname(gpt_entry *pte) @@ -68,12 +70,113 @@ static inline int is_bootable(gpt_entry *p) sizeof(efi_guid_t)); } +static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba, + lbaint_t lastlba) +{ + uint32_t crc32_backup = 0; + uint32_t calc_crc32; + + /* Check the GPT header signature */ + if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) { + printf("%s signature is wrong: 0x%llX != 0x%llX\n", + "GUID Partition Table Header", + le64_to_cpu(gpt_h->signature), + GPT_HEADER_SIGNATURE); + return -1; + } + + /* Check the GUID Partition Table CRC */ + memcpy(&crc32_backup, &gpt_h->header_crc32, sizeof(crc32_backup)); + memset(&gpt_h->header_crc32, 0, sizeof(gpt_h->header_crc32)); + + calc_crc32 = efi_crc32((const unsigned char *)gpt_h, + le32_to_cpu(gpt_h->header_size)); + + memcpy(&gpt_h->header_crc32, &crc32_backup, sizeof(crc32_backup)); + + if (calc_crc32 != le32_to_cpu(crc32_backup)) { + printf("%s CRC is wrong: 0x%x != 0x%x\n", + "GUID Partition Table Header", + le32_to_cpu(crc32_backup), calc_crc32); + return -1; + } + + /* + * Check that the my_lba entry points to the LBA that contains the GPT + */ + if (le64_to_cpu(gpt_h->my_lba) != lba) { + printf("GPT: my_lba incorrect: %llX != " LBAF "\n", + le64_to_cpu(gpt_h->my_lba), + lba); + return -1; + } + + /* + * Check that the first_usable_lba and that the last_usable_lba are + * within the disk. + */ + if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) { + printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n", + le64_to_cpu(gpt_h->first_usable_lba), lastlba); + return -1; + } + if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) { + printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n", + le64_to_cpu(gpt_h->last_usable_lba), lastlba); + return -1; + } + + debug("GPT: first_usable_lba: %llX last_usable_lba: %llX last lba: " + LBAF "\n", le64_to_cpu(gpt_h->first_usable_lba), + le64_to_cpu(gpt_h->last_usable_lba), lastlba); + + return 0; +} + +static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e) +{ + uint32_t calc_crc32; + + /* Check the GUID Partition Table Entry Array CRC */ + 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 (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) { + printf("%s: 0x%x != 0x%x\n", + "GUID Partition Table Entry Array CRC is wrong", + le32_to_cpu(gpt_h->partition_entry_array_crc32), + calc_crc32); + return -1; + } + + return 0; +} + +static void prepare_backup_gpt_header(gpt_header *gpt_h) +{ + uint32_t calc_crc32; + uint64_t val; + + /* recalculate the values for the Backup GPT Header */ + val = le64_to_cpu(gpt_h->my_lba); + gpt_h->my_lba = gpt_h->alternate_lba; + gpt_h->alternate_lba = cpu_to_le64(val); + gpt_h->partition_entry_lba = + cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1); + gpt_h->header_crc32 = 0; + + calc_crc32 = efi_crc32((const unsigned char *)gpt_h, + le32_to_cpu(gpt_h->header_size)); + gpt_h->header_crc32 = cpu_to_le32(calc_crc32); +} + #ifdef CONFIG_EFI_PARTITION /* * Public Functions (include/part.h) */ -void print_part_efi(block_dev_desc_t * dev_desc) +void part_print_efi(struct blk_desc *dev_desc) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); gpt_entry *gpt_pte = NULL; @@ -81,10 +184,6 @@ void print_part_efi(block_dev_desc_t * dev_desc) char uuid[37]; unsigned char *uuid_bin; - if (!dev_desc) { - printf("%s: Invalid Argument(s)\n", __func__); - return; - } /* 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) { @@ -120,6 +219,10 @@ void print_part_efi(block_dev_desc_t * dev_desc) uuid_bin = (unsigned char *)gpt_pte[i].partition_type_guid.b; uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID); printf("\ttype:\t%s\n", uuid); +#ifdef CONFIG_PARTITION_TYPE_GUID + if (!uuid_guid_get_str(uuid_bin, uuid)) + printf("\ttype:\t%s\n", uuid); +#endif uuid_bin = (unsigned char *)gpt_pte[i].unique_partition_guid.b; uuid_bin_to_str(uuid_bin, uuid, UUID_STR_FORMAT_GUID); printf("\tguid:\t%s\n", uuid); @@ -130,14 +233,14 @@ void print_part_efi(block_dev_desc_t * dev_desc) return; } -int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, - disk_partition_t * info) +int part_get_info_efi(struct blk_desc *dev_desc, int part, + disk_partition_t *info) { ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz); gpt_entry *gpt_pte = NULL; /* "part" argument must be at least 1 */ - if (!dev_desc || !info || part < 1) { + if (part < 1) { printf("%s: Invalid Argument(s)\n", __func__); return -1; } @@ -174,12 +277,16 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, sprintf((char *)info->name, "%s", print_efiname(&gpt_pte[part - 1])); - sprintf((char *)info->type, "U-Boot"); + strcpy((char *)info->type, "U-Boot"); info->bootable = is_bootable(&gpt_pte[part - 1]); #ifdef CONFIG_PARTITION_UUIDS uuid_bin_to_str(gpt_pte[part - 1].unique_partition_guid.b, info->uuid, UUID_STR_FORMAT_GUID); #endif +#ifdef CONFIG_PARTITION_TYPE_GUID + uuid_bin_to_str(gpt_pte[part - 1].partition_type_guid.b, + info->type_guid, UUID_STR_FORMAT_GUID); +#endif debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__, info->start, info->size, info->name); @@ -189,13 +296,13 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part, return 0; } -int get_partition_info_efi_by_name(block_dev_desc_t *dev_desc, +int part_get_info_efi_by_name(struct blk_desc *dev_desc, const char *name, disk_partition_t *info) { int ret; int i; for (i = 1; i < GPT_ENTRY_NUMBERS; i++) { - ret = get_partition_info_efi(dev_desc, i, info); + ret = part_get_info_efi(dev_desc, i, info); if (ret != 0) { /* no more entries in table */ return -1; @@ -208,12 +315,12 @@ int get_partition_info_efi_by_name(block_dev_desc_t *dev_desc, return -2; } -int test_part_efi(block_dev_desc_t * dev_desc) +static int part_test_efi(struct blk_desc *dev_desc) { ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz); /* Read legacy MBR from block 0 and validate it */ - if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1) + if ((blk_dread(dev_desc, 0, 1, (ulong *)legacymbr) != 1) || (is_pmbr_valid(legacymbr) != 1)) { return -1; } @@ -226,7 +333,7 @@ int test_part_efi(block_dev_desc_t * dev_desc) * * @return - zero on success, otherwise error */ -static int set_protective_mbr(block_dev_desc_t *dev_desc) +static int set_protective_mbr(struct blk_desc *dev_desc) { /* Setup the Protective MBR */ ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, p_mbr, 1); @@ -240,25 +347,24 @@ static int set_protective_mbr(block_dev_desc_t *dev_desc) p_mbr->signature = MSDOS_MBR_SIGNATURE; p_mbr->partition_record[0].sys_ind = EFI_PMBR_OSTYPE_EFI_GPT; p_mbr->partition_record[0].start_sect = 1; - p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba; + p_mbr->partition_record[0].nr_sects = (u32) dev_desc->lba - 1; /* Write MBR sector to the MMC device */ - if (dev_desc->block_write(dev_desc->dev, 0, 1, p_mbr) != 1) { + if (blk_dwrite(dev_desc, 0, 1, p_mbr) != 1) { printf("** Can't write to device %d **\n", - dev_desc->dev); + dev_desc->devnum); return -1; } return 0; } -int write_gpt_table(block_dev_desc_t *dev_desc, +int write_gpt_table(struct blk_desc *dev_desc, gpt_header *gpt_h, gpt_entry *gpt_e) { const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries * sizeof(gpt_entry)), dev_desc); u32 calc_crc32; - u64 val; debug("max lba: %x\n", (u32) dev_desc->lba); /* Setup the Protective MBR */ @@ -276,39 +382,28 @@ int write_gpt_table(block_dev_desc_t *dev_desc, gpt_h->header_crc32 = cpu_to_le32(calc_crc32); /* Write the First GPT to the block right after the Legacy MBR */ - if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1) + if (blk_dwrite(dev_desc, 1, 1, gpt_h) != 1) goto err; - if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_cnt, gpt_e) + if (blk_dwrite(dev_desc, 2, pte_blk_cnt, gpt_e) != pte_blk_cnt) goto err; - /* recalculate the values for the Backup GPT Header */ - val = le64_to_cpu(gpt_h->my_lba); - gpt_h->my_lba = gpt_h->alternate_lba; - gpt_h->alternate_lba = cpu_to_le64(val); - gpt_h->header_crc32 = 0; + prepare_backup_gpt_header(gpt_h); - calc_crc32 = efi_crc32((const unsigned char *)gpt_h, - le32_to_cpu(gpt_h->header_size)); - gpt_h->header_crc32 = cpu_to_le32(calc_crc32); - - if (dev_desc->block_write(dev_desc->dev, - (lbaint_t)le64_to_cpu(gpt_h->last_usable_lba) - + 1, - pte_blk_cnt, gpt_e) != pte_blk_cnt) + if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->last_usable_lba) + + 1, pte_blk_cnt, gpt_e) != pte_blk_cnt) goto err; - if (dev_desc->block_write(dev_desc->dev, - (lbaint_t)le64_to_cpu(gpt_h->my_lba), 1, - gpt_h) != 1) + if (blk_dwrite(dev_desc, (lbaint_t)le64_to_cpu(gpt_h->my_lba), 1, + gpt_h) != 1) goto err; debug("GPT successfully written to block device!\n"); return 0; err: - printf("** Can't write to device %d **\n", dev_desc->dev); + printf("** Can't write to device %d **\n", dev_desc->devnum); return -1; } @@ -325,6 +420,10 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, char *str_uuid; unsigned char *bin_uuid; #endif +#ifdef CONFIG_PARTITION_TYPE_GUID + char *str_type_guid; + unsigned char *bin_type_guid; +#endif for (i = 0; i < parts; i++) { /* partition starting lba */ @@ -340,7 +439,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, gpt_e[i].starting_lba = cpu_to_le64(offset); offset += partitions[i].size; } - if (offset >= last_usable_lba) { + if (offset > (last_usable_lba + 1)) { printf("Partitions layout exceds disk size\n"); return -1; } @@ -351,9 +450,26 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, else gpt_e[i].ending_lba = cpu_to_le64(offset - 1); +#ifdef CONFIG_PARTITION_TYPE_GUID + str_type_guid = partitions[i].type_guid; + bin_type_guid = gpt_e[i].partition_type_guid.b; + if (strlen(str_type_guid)) { + if (uuid_str_to_bin(str_type_guid, bin_type_guid, + UUID_STR_FORMAT_GUID)) { + printf("Partition no. %d: invalid type guid: %s\n", + i, str_type_guid); + return -1; + } + } else { + /* default partition type GUID */ + memcpy(bin_type_guid, + &PARTITION_BASIC_DATA_GUID, 16); + } +#else /* partition type GUID */ memcpy(gpt_e[i].partition_type_guid.b, &PARTITION_BASIC_DATA_GUID, 16); +#endif #ifdef CONFIG_PARTITION_UUIDS str_uuid = partitions[i].uuid; @@ -370,6 +486,9 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, memset(&gpt_e[i].attributes, 0, sizeof(gpt_entry_attributes)); + if (partitions[i].bootable) + gpt_e[i].attributes.fields.legacy_bios_bootable = 1; + /* partition name */ efiname_len = sizeof(gpt_e[i].partition_name) / sizeof(efi_char16_t); @@ -391,7 +510,7 @@ int gpt_fill_pte(gpt_header *gpt_h, gpt_entry *gpt_e, return 0; } -int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h, +int gpt_fill_header(struct blk_desc *dev_desc, gpt_header *gpt_h, char *str_guid, int parts_count) { gpt_h->signature = cpu_to_le64(GPT_HEADER_SIGNATURE); @@ -413,7 +532,7 @@ int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h, return 0; } -int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid, +int gpt_restore(struct blk_desc *dev_desc, char *str_disk_guid, disk_partition_t *partitions, int parts_count) { int ret; @@ -454,6 +573,209 @@ err: free(gpt_h); 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(struct blk_desc *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(struct blk_desc *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 ", + (unsigned long long)gpt_part_size, + (unsigned long long)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, (unsigned long long)gpt_part_size, + (unsigned long long)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), + (unsigned long long)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), + (unsigned long long)partitions[i].start); + return -1; + } + } + + return 0; +} + +int is_valid_gpt_buf(struct blk_desc *dev_desc, void *buf) +{ + gpt_header *gpt_h; + gpt_entry *gpt_e; + + /* determine start of GPT Header in the buffer */ + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * + dev_desc->blksz); + if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA, + dev_desc->lba)) + return -1; + + /* determine start of GPT Entries in the buffer */ + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) * + dev_desc->blksz); + if (validate_gpt_entries(gpt_h, gpt_e)) + return -1; + + return 0; +} + +int write_mbr_and_gpt_partitions(struct blk_desc *dev_desc, void *buf) +{ + gpt_header *gpt_h; + gpt_entry *gpt_e; + int gpt_e_blk_cnt; + lbaint_t lba; + int cnt; + + if (is_valid_gpt_buf(dev_desc, buf)) + return -1; + + /* determine start of GPT Header in the buffer */ + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA * + dev_desc->blksz); + + /* determine start of GPT Entries in the buffer */ + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) * + dev_desc->blksz); + gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) * + le32_to_cpu(gpt_h->sizeof_partition_entry)), + dev_desc); + + /* write MBR */ + lba = 0; /* MBR is always at 0 */ + cnt = 1; /* MBR (1 block) */ + if (blk_dwrite(dev_desc, lba, cnt, buf) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "MBR", cnt, lba); + return 1; + } + + /* write Primary GPT */ + lba = GPT_PRIMARY_PARTITION_TABLE_LBA; + cnt = 1; /* GPT Header (1 block) */ + if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Primary GPT Header", cnt, lba); + return 1; + } + + lba = le64_to_cpu(gpt_h->partition_entry_lba); + cnt = gpt_e_blk_cnt; + if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Primary GPT Entries", cnt, lba); + return 1; + } + + prepare_backup_gpt_header(gpt_h); + + /* write Backup GPT */ + lba = le64_to_cpu(gpt_h->partition_entry_lba); + cnt = gpt_e_blk_cnt; + if (blk_dwrite(dev_desc, lba, cnt, gpt_e) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Backup GPT Entries", cnt, lba); + return 1; + } + + lba = le64_to_cpu(gpt_h->my_lba); + cnt = 1; /* GPT Header (1 block) */ + if (blk_dwrite(dev_desc, lba, cnt, gpt_h) != cnt) { + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n", + __func__, "Backup GPT Header", cnt, lba); + return 1; + } + + return 0; +} #endif /* @@ -507,74 +829,22 @@ static int is_pmbr_valid(legacy_mbr * mbr) * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to PTEs. */ -static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba, +static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba, gpt_header *pgpt_head, gpt_entry **pgpt_pte) { - u32 crc32_backup = 0; - u32 calc_crc32; - u64 lastlba; - if (!dev_desc || !pgpt_head) { printf("%s: Invalid Argument(s)\n", __func__); return 0; } /* Read GPT Header from device */ - if (dev_desc->block_read(dev_desc->dev, (lbaint_t)lba, 1, pgpt_head) - != 1) { + if (blk_dread(dev_desc, (lbaint_t)lba, 1, pgpt_head) != 1) { printf("*** ERROR: Can't read GPT header ***\n"); return 0; } - /* Check the GPT header signature */ - if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) { - printf("GUID Partition Table Header signature is wrong:" - "0x%llX != 0x%llX\n", - le64_to_cpu(pgpt_head->signature), - GPT_HEADER_SIGNATURE); - return 0; - } - - /* Check the GUID Partition Table CRC */ - memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup)); - memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32)); - - calc_crc32 = efi_crc32((const unsigned char *)pgpt_head, - le32_to_cpu(pgpt_head->header_size)); - - memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup)); - - if (calc_crc32 != le32_to_cpu(crc32_backup)) { - printf("GUID Partition Table Header CRC is wrong:" - "0x%x != 0x%x\n", - le32_to_cpu(crc32_backup), calc_crc32); - return 0; - } - - /* Check that the my_lba entry points to the LBA that contains the GPT */ - if (le64_to_cpu(pgpt_head->my_lba) != lba) { - printf("GPT: my_lba incorrect: %llX != %llX\n", - le64_to_cpu(pgpt_head->my_lba), - lba); - return 0; - } - - /* Check the first_usable_lba and last_usable_lba are within the disk. */ - lastlba = (u64)dev_desc->lba; - if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) { - printf("GPT: first_usable_lba incorrect: %llX > %llX\n", - le64_to_cpu(pgpt_head->first_usable_lba), lastlba); + if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba)) return 0; - } - if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) { - printf("GPT: last_usable_lba incorrect: %llX > %llX\n", - le64_to_cpu(pgpt_head->last_usable_lba), lastlba); - return 0; - } - - debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %llX\n", - le64_to_cpu(pgpt_head->first_usable_lba), - le64_to_cpu(pgpt_head->last_usable_lba), lastlba); /* Read and allocate Partition Table Entries */ *pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head); @@ -583,17 +853,7 @@ static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba, return 0; } - /* Check the GUID Partition Table Entry Array CRC */ - calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte, - le32_to_cpu(pgpt_head->num_partition_entries) * - le32_to_cpu(pgpt_head->sizeof_partition_entry)); - - if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) { - printf("GUID Partition Table Entry Array CRC is wrong:" - "0x%x != 0x%x\n", - le32_to_cpu(pgpt_head->partition_entry_array_crc32), - calc_crc32); - + if (validate_gpt_entries(pgpt_head, *pgpt_pte)) { free(*pgpt_pte); return 0; } @@ -611,10 +871,11 @@ static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba, * Allocates space for PTEs based on information found in @gpt. * Notes: remember to free pte when you're done! */ -static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, - gpt_header * pgpt_head) +static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc, + gpt_header *pgpt_head) { size_t count = 0, blk_cnt; + lbaint_t blk; gpt_entry *pte = NULL; if (!dev_desc || !pgpt_head) { @@ -643,12 +904,9 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc, } /* Read GPT Entries from device */ + blk = le64_to_cpu(pgpt_head->partition_entry_lba); blk_cnt = BLOCK_CNT(count, dev_desc); - if (dev_desc->block_read (dev_desc->dev, - (lbaint_t)le64_to_cpu(pgpt_head->partition_entry_lba), - (lbaint_t) (blk_cnt), pte) - != blk_cnt) { - + if (blk_dread(dev_desc, blk, (lbaint_t)blk_cnt, pte) != blk_cnt) { printf("*** ERROR: Can't read GPT Entries ***\n"); free(pte); return NULL; @@ -687,4 +945,17 @@ static int is_pte_valid(gpt_entry * pte) return 1; } } + +/* + * Add an 'a_' prefix so it comes before 'dos' in the linker list. We need to + * check EFI first, since a DOS partition is often used as a 'protective MBR' + * with EFI. + */ +U_BOOT_PART_TYPE(a_efi) = { + .name = "EFI", + .part_type = PART_TYPE_EFI, + .get_info = part_get_info_ptr(part_get_info_efi), + .print = part_print_ptr(part_print_efi), + .test = part_test_efi, +}; #endif