diff options
author | Sandrine Bailleux (on vacation) <sandrine.bailleux@arm.com> | 2023-10-27 16:37:18 +0200 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2023-10-27 16:37:18 +0200 |
commit | a08964671140d1014b88ecc412e3d8c5d39a44fd (patch) | |
tree | 4dd0473d5d3eb1b96cdba438b9462e95e331f77b | |
parent | efd812c3eee9a1faac01235110b471b110a286b3 (diff) | |
parent | 08ec77c7fe8b444f464ecba3655deaf272490f83 (diff) |
Merge changes from topic "gpt_updates" into integration
* changes:
refactor(arm): use gpt_partition_init
feat(partition): add interface to init gpt
refactor(partition): convert warn to verbose
feat(partition): add support to use backup GPT header
refactor(partition): get GPT header location from MBR
feat(arm): add IO policy to use backup gpt header
feat(tbbr): add image id for backup GPT
-rw-r--r-- | drivers/partition/partition.c | 233 | ||||
-rw-r--r-- | include/drivers/partition/gpt.h | 8 | ||||
-rw-r--r-- | include/drivers/partition/partition.h | 5 | ||||
-rw-r--r-- | include/export/common/tbbr/tbbr_img_def_exp.h | 27 | ||||
-rw-r--r-- | plat/arm/common/arm_bl2_setup.c | 10 | ||||
-rw-r--r-- | plat/arm/common/fconf/arm_fconf_io.c | 22 |
6 files changed, 251 insertions, 54 deletions
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c index 1881c91b3..c60820dfc 100644 --- a/drivers/partition/partition.c +++ b/drivers/partition/partition.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -49,30 +49,43 @@ static void dump_entries(int num) static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) { size_t bytes_read; - uintptr_t offset; int result; + mbr_entry_t *tmp; assert(mbr_entry != NULL); /* MBR partition table is in LBA0. */ result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); if (result != 0) { - WARN("Failed to seek (%i)\n", result); + VERBOSE("Failed to seek (%i)\n", result); return result; } result = io_read(image_handle, (uintptr_t)&mbr_sector, PLAT_PARTITION_BLOCK_SIZE, &bytes_read); - if (result != 0) { - WARN("Failed to read data (%i)\n", result); + if ((result != 0) || (bytes_read != PLAT_PARTITION_BLOCK_SIZE)) { + VERBOSE("Failed to read data (%i)\n", result); return result; } /* Check MBR boot signature. */ if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + VERBOSE("MBR boot signature failure\n"); return -ENOENT; } - offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET; - memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); + + tmp = (mbr_entry_t *)(&mbr_sector[MBR_PRIMARY_ENTRY_OFFSET]); + + if (tmp->first_lba != 1) { + VERBOSE("MBR header may have an invalid first LBA\n"); + return -EINVAL; + } + + if ((tmp->sector_nums == 0) || (tmp->sector_nums == UINT32_MAX)) { + VERBOSE("MBR header entry has an invalid number of sectors\n"); + return -EINVAL; + } + + memcpy(mbr_entry, tmp, sizeof(mbr_entry_t)); return 0; } @@ -80,24 +93,31 @@ static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) * Load GPT header and check the GPT signature and header CRC. * If partition numbers could be found, check & update it. */ -static int load_gpt_header(uintptr_t image_handle) +static int load_gpt_header(uintptr_t image_handle, size_t header_offset, + unsigned long long *part_lba) { gpt_header_t header; size_t bytes_read; int result; uint32_t header_crc, calc_crc; - result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET); + result = io_seek(image_handle, IO_SEEK_SET, header_offset); if (result != 0) { + VERBOSE("Failed to seek into the GPT image at offset (%zu)\n", + header_offset); return result; } result = io_read(image_handle, (uintptr_t)&header, sizeof(gpt_header_t), &bytes_read); if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { + VERBOSE("GPT header read error(%i) or read mismatch occurred," + "expected(%zu) and actual(%zu)\n", result, + sizeof(gpt_header_t), bytes_read); return result; } if (memcmp(header.signature, GPT_SIGNATURE, - sizeof(header.signature)) != 0) { + sizeof(header.signature)) != 0) { + VERBOSE("GPT header signature failure\n"); return -EINVAL; } @@ -109,7 +129,7 @@ static int load_gpt_header(uintptr_t image_handle) header_crc = header.header_crc; header.header_crc = 0U; - calc_crc = tf_crc32(0U, (uint8_t *)&header, DEFAULT_GPT_HEADER_SIZE); + calc_crc = tf_crc32(0U, (uint8_t *)&header, sizeof(gpt_header_t)); if (header_crc != calc_crc) { ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n", header_crc, calc_crc); @@ -123,11 +143,16 @@ static int load_gpt_header(uintptr_t image_handle) if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { list.entry_count = PLAT_PARTITION_MAX_ENTRIES; } + + *part_lba = header.part_lba; return 0; } +/* + * Load a single MBR entry based on details from MBR header. + */ static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, - int part_number) + int part_number) { size_t bytes_read; uintptr_t offset; @@ -137,19 +162,20 @@ static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, /* MBR partition table is in LBA0. */ result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); if (result != 0) { - WARN("Failed to seek (%i)\n", result); + VERBOSE("Failed to seek (%i)\n", result); return result; } result = io_read(image_handle, (uintptr_t)&mbr_sector, PLAT_PARTITION_BLOCK_SIZE, &bytes_read); if (result != 0) { - WARN("Failed to read data (%i)\n", result); + VERBOSE("Failed to read data (%i)\n", result); return result; } /* Check MBR boot signature. */ if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + VERBOSE("MBR Entry boot signature failure\n"); return -ENOENT; } offset = (uintptr_t)&mbr_sector + @@ -160,6 +186,9 @@ static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, return 0; } +/* + * Load MBR entries based on max number of partition entries. + */ static int load_mbr_entries(uintptr_t image_handle) { mbr_entry_t mbr_entry; @@ -177,33 +206,60 @@ static int load_mbr_entries(uintptr_t image_handle) return 0; } +/* + * Try to read and load a single GPT entry. + */ static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) { - size_t bytes_read; + size_t bytes_read = 0U; int result; assert(entry != NULL); result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t), - &bytes_read); - if (sizeof(gpt_entry_t) != bytes_read) + &bytes_read); + if ((result != 0) || (sizeof(gpt_entry_t) != bytes_read)) { + VERBOSE("GPT Entry read error(%i) or read mismatch occurred," + "expected(%zu) and actual(%zu)\n", result, + sizeof(gpt_entry_t), bytes_read); return -EINVAL; + } + return result; } -static int verify_partition_gpt(uintptr_t image_handle) +/* + * Retrieve each entry in the partition table, parse the data from each + * entry and store them in the list of partition table entries. + */ +static int load_partition_gpt(uintptr_t image_handle, + unsigned long long part_lba) { + const signed long long gpt_entry_offset = LBA(part_lba); gpt_entry_t entry; int result, i; + result = io_seek(image_handle, IO_SEEK_SET, gpt_entry_offset); + if (result != 0) { + VERBOSE("Failed to seek (%i), Failed loading GPT partition" + "table entries\n", result); + return result; + } + for (i = 0; i < list.entry_count; i++) { result = load_gpt_entry(image_handle, &entry); - assert(result == 0); + if (result != 0) { + VERBOSE("Failed to load gpt entry data(%i) error is (%i)\n", + i, result); + return result; + } + result = parse_gpt_entry(&entry, &list.list[i]); if (result != 0) { break; } } if (i == 0) { + VERBOSE("No Valid GPT Entries found\n"); return -EINVAL; } /* @@ -216,6 +272,94 @@ static int verify_partition_gpt(uintptr_t image_handle) return 0; } +/* + * Try retrieving and parsing the backup-GPT header and backup GPT entries. + * Last 33 blocks contains the backup-GPT entries and header. + */ +static int load_backup_gpt(unsigned int image_id, unsigned int sector_nums) +{ + int result; + unsigned long long part_lba = 0; + size_t gpt_header_offset; + uintptr_t dev_handle, image_spec, image_handle; + io_block_spec_t *block_spec; + int part_num_entries; + + result = plat_get_image_source(image_id, &dev_handle, &image_spec); + if (result != 0) { + VERBOSE("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + block_spec = (io_block_spec_t *)image_spec; + /* + * We need to read 32 blocks of GPT entries and one block of GPT header + * try mapping only last 33 last blocks from the image to read the + * Backup-GPT header and its entries. + */ + part_num_entries = (PLAT_PARTITION_MAX_ENTRIES / 4); + /* Move the offset base to LBA-33 */ + block_spec->offset += LBA(sector_nums - part_num_entries); + /* + * Set length as LBA-33, 32 blocks of backup-GPT entries and one + * block of backup-GPT header. + */ + block_spec->length = LBA(part_num_entries + 1); + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + VERBOSE("Failed to access image id (%i)\n", result); + return result; + } + + INFO("Trying to retrieve back-up GPT header\n"); + /* Last block is backup-GPT header, after the end of GPT entries */ + gpt_header_offset = LBA(part_num_entries); + result = load_gpt_header(image_handle, gpt_header_offset, &part_lba); + if ((result != 0) || (part_lba == 0)) { + ERROR("Failed to retrieve Backup GPT header," + "Partition maybe corrupted\n"); + goto out; + } + + /* + * Note we mapped last 33 blocks(LBA-33), first block here starts with + * entries while last block was header. + */ + result = load_partition_gpt(image_handle, 0); + +out: + io_close(image_handle); + return result; +} + +/* + * Load a GPT partition, Try retrieving and parsing the primary GPT header, + * if its corrupted try loading backup GPT header and then retrieve list + * of partition table entries found from the GPT. + */ +static int load_primary_gpt(uintptr_t image_handle, unsigned int first_lba) +{ + int result; + unsigned long long part_lba; + size_t gpt_header_offset; + + /* Try to load Primary GPT header from LBA1 */ + gpt_header_offset = LBA(first_lba); + result = load_gpt_header(image_handle, gpt_header_offset, &part_lba); + if ((result != 0) || (part_lba == 0)) { + VERBOSE("Failed to retrieve Primary GPT header," + "trying to retrieve back-up GPT header\n"); + return result; + } + + return load_partition_gpt(image_handle, part_lba); +} + +/* + * Load the partition table info based on the image id provided. + */ int load_partition_table(unsigned int image_id) { uintptr_t dev_handle, image_handle, image_spec = 0; @@ -224,36 +368,41 @@ int load_partition_table(unsigned int image_id) result = plat_get_image_source(image_id, &dev_handle, &image_spec); if (result != 0) { - WARN("Failed to obtain reference to image id=%u (%i)\n", + VERBOSE("Failed to obtain reference to image id=%u (%i)\n", image_id, result); return result; } result = io_open(dev_handle, image_spec, &image_handle); if (result != 0) { - WARN("Failed to access image id=%u (%i)\n", image_id, result); + VERBOSE("Failed to access image id=%u (%i)\n", image_id, result); return result; } result = load_mbr_header(image_handle, &mbr_entry); if (result != 0) { - WARN("Failed to access image id=%u (%i)\n", image_id, result); - return result; + VERBOSE("Failed to access image id=%u (%i)\n", image_id, result); + goto out; } if (mbr_entry.type == PARTITION_TYPE_GPT) { - result = load_gpt_header(image_handle); - assert(result == 0); - result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET); - assert(result == 0); - result = verify_partition_gpt(image_handle); + result = load_primary_gpt(image_handle, mbr_entry.first_lba); + if (result != 0) { + io_close(image_handle); + return load_backup_gpt(BKUP_GPT_IMAGE_ID, + mbr_entry.sector_nums); + } } else { result = load_mbr_entries(image_handle); } +out: io_close(image_handle); return result; } +/* + * Try retrieving a partition table entry based on the name of the partition. + */ const partition_entry_t *get_partition_entry(const char *name) { int i; @@ -266,6 +415,9 @@ const partition_entry_t *get_partition_entry(const char *name) return NULL; } +/* + * Try retrieving a partition table entry based on the GUID. + */ const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid) { int i; @@ -279,6 +431,9 @@ const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid) return NULL; } +/* + * Try retrieving a partition table entry based on the UUID. + */ const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) { int i; @@ -292,12 +447,32 @@ const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) return NULL; } +/* + * Return entry to the list of partition table entries. + */ const partition_entry_list_t *get_partition_entry_list(void) { return &list; } +/* + * Try loading partition table info for the given image ID. + */ void partition_init(unsigned int image_id) { - load_partition_table(image_id); + int ret; + + ret = load_partition_table(image_id); + if (ret != 0) { + ERROR("Failed to parse partition with image id = %u\n", + image_id); + } +} + +/* + * Load a GPT based image. + */ +int gpt_partition_init(void) +{ + return load_partition_table(GPT_IMAGE_ID); } diff --git a/include/drivers/partition/gpt.h b/include/drivers/partition/gpt.h index c2a229e33..383c17de6 100644 --- a/include/drivers/partition/gpt.h +++ b/include/drivers/partition/gpt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,10 +12,6 @@ #include <tools_share/uuid.h> #define PARTITION_TYPE_GPT 0xee -#define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE -#define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + \ - PLAT_PARTITION_BLOCK_SIZE) - #define GPT_SIGNATURE "EFI PART" typedef struct gpt_entry { @@ -45,7 +41,7 @@ typedef struct gpt_header { /* size of a single partition entry (usually 128) */ unsigned int part_size; unsigned int part_crc; -} gpt_header_t; +} __packed gpt_header_t; int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry); diff --git a/include/drivers/partition/partition.h b/include/drivers/partition/partition.h index 6cb59c391..d567d4cbb 100644 --- a/include/drivers/partition/partition.h +++ b/include/drivers/partition/partition.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,7 +29,7 @@ CASSERT((PLAT_PARTITION_BLOCK_SIZE == 512) || #define LEGACY_PARTITION_BLOCK_SIZE 512 -#define DEFAULT_GPT_HEADER_SIZE 92 +#define LBA(n) ((unsigned long long)(n) * PLAT_PARTITION_BLOCK_SIZE) typedef struct partition_entry { uint64_t start; @@ -50,5 +50,6 @@ const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_guid); const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid); const partition_entry_list_t *get_partition_entry_list(void); void partition_init(unsigned int image_id); +int gpt_partition_init(void); #endif /* PARTITION_H */ diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h index 98a00999d..ce17b4afb 100644 --- a/include/export/common/tbbr/tbbr_img_def_exp.h +++ b/include/export/common/tbbr/tbbr_img_def_exp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -79,41 +79,44 @@ /* NT_FW_CONFIG */ #define NT_FW_CONFIG_ID U(27) -/* GPT Partition */ +/* GPT primary header and entries */ #define GPT_IMAGE_ID U(28) +/* GPT backup header and entries */ +#define BKUP_GPT_IMAGE_ID U(29) + /* Binary with STM32 header */ -#define STM32_IMAGE_ID U(29) +#define STM32_IMAGE_ID U(30) /* Encrypted image identifier */ -#define ENC_IMAGE_ID U(30) +#define ENC_IMAGE_ID U(31) /* FW_CONFIG */ -#define FW_CONFIG_ID U(31) +#define FW_CONFIG_ID U(32) /* * Primary FWU metadata image ID */ -#define FWU_METADATA_IMAGE_ID U(32) +#define FWU_METADATA_IMAGE_ID U(33) /* * Backup FWU metadata image ID */ -#define BKUP_FWU_METADATA_IMAGE_ID U(33) +#define BKUP_FWU_METADATA_IMAGE_ID U(34) /* Realm Monitor Manager (RMM) */ -#define RMM_IMAGE_ID U(34) +#define RMM_IMAGE_ID U(35) /* CCA Content Certificate ID */ -#define CCA_CONTENT_CERT_ID U(35) +#define CCA_CONTENT_CERT_ID U(36) /* Core SWD Key Certificate ID */ -#define CORE_SWD_KEY_CERT_ID U(36) +#define CORE_SWD_KEY_CERT_ID U(37) /* Platform Key Certificate ID */ -#define PLAT_KEY_CERT_ID U(37) +#define PLAT_KEY_CERT_ID U(38) /* Max Images */ -#define MAX_IMAGE_IDS U(38) +#define MAX_IMAGE_IDS U(39) #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */ diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index b142b6241..6f3d0e944 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -69,6 +69,8 @@ CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows); void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout) { + int __maybe_unused ret; + /* Initialize the console to provide early debug support */ arm_console_boot_init(); @@ -82,9 +84,13 @@ void arm_bl2_early_platform_setup(uintptr_t fw_config, /* Load partition table */ #if ARM_GPT_SUPPORT - partition_init(GPT_IMAGE_ID); -#endif /* ARM_GPT_SUPPORT */ + ret = gpt_partition_init(); + if (ret != 0) { + ERROR("GPT partition initialisation failed!\n"); + panic(); + } +#endif /* ARM_GPT_SUPPORT */ } void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c index 27acc3a64..07f6a8272 100644 --- a/plat/arm/common/fconf/arm_fconf_io.c +++ b/plat/arm/common/fconf/arm_fconf_io.c @@ -45,10 +45,21 @@ static const io_block_spec_t gpt_spec = { * each sector has 4 partition entries, and there are * 2 reserved sectors i.e. protective MBR and primary * GPT header hence length gets calculated as, - * length = 512 * (128/4 + 2) + * length = PLAT_PARTITION_BLOCK_SIZE * (128/4 + 2) */ - .length = PLAT_PARTITION_BLOCK_SIZE * - (PLAT_PARTITION_MAX_ENTRIES / 4 + 2), + .length = LBA(PLAT_PARTITION_MAX_ENTRIES / 4 + 2), +}; + +/* + * length will be assigned at runtime based on MBR header data. + * Backup GPT Header is present in Last LBA-1 and its entries + * are last 32 blocks starts at LBA-33, On runtime update these + * before device usage. Update offset to beginning LBA-33 and + * length to LBA-33. + */ +static io_block_spec_t bkup_gpt_spec = { + .offset = PLAT_ARM_FLASH_IMAGE_BASE, + .length = 0, }; #endif /* ARM_GPT_SUPPORT */ @@ -107,6 +118,11 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = { (uintptr_t)&gpt_spec, open_memmap }, + [BKUP_GPT_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&bkup_gpt_spec, + open_memmap + }, #endif /* ARM_GPT_SUPPORT */ #if PSA_FWU_SUPPORT [FWU_METADATA_IMAGE_ID] = { |