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
This commit is contained in:
Sandrine Bailleux (on vacation) 2023-10-27 16:37:18 +02:00 committed by TrustedFirmware Code Review
commit a089646711
6 changed files with 251 additions and 54 deletions

View file

@ -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) {
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,9 +143,14 @@ 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)
{
@ -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)
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);
}

View file

@ -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);

View file

@ -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 */

View file

@ -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 */

View file

@ -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)

View file

@ -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] = {