summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandrine Bailleux (on vacation) <sandrine.bailleux@arm.com>2023-10-27 16:37:18 +0200
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2023-10-27 16:37:18 +0200
commita08964671140d1014b88ecc412e3d8c5d39a44fd (patch)
tree4dd0473d5d3eb1b96cdba438b9462e95e331f77b
parentefd812c3eee9a1faac01235110b471b110a286b3 (diff)
parent08ec77c7fe8b444f464ecba3655deaf272490f83 (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.c233
-rw-r--r--include/drivers/partition/gpt.h8
-rw-r--r--include/drivers/partition/partition.h5
-rw-r--r--include/export/common/tbbr/tbbr_img_def_exp.h27
-rw-r--r--plat/arm/common/arm_bl2_setup.c10
-rw-r--r--plat/arm/common/fconf/arm_fconf_io.c22
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] = {