amdfwread: Parse and print directory sizes

Parse the directory table size field and print along walking
the PSP directory tables.

Example output:
Table: FW   Offset     Size
PSPL1: Dir  [0x00b10000-0x00b12000)
+-->PSPL1: 0x48 0x00b30000 0x00010000
    +-->PSPL2: Dir  [0x00030000-0x00081000)
        +-->PSPL2: 0x00 0x00040000 0x00000440

Change-Id: I355c301c83af25524353a2e980066ce78b01fc37
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90329
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Alicja Michalska <ahplka19@gmail.com>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Upstream-Status: Backport [CB:90329]
This commit is contained in:
Patrick Rudolph
2025-12-02 08:36:14 +01:00
committed by Michał Żygowski
parent 2747cac191
commit 496b15cead
+85 -5
View File
@@ -144,6 +144,9 @@ static int read_psp_directory(FILE *fw, uint32_t offset, uint32_t expected_cooki
return 1;
}
if (!entries || !num_entries)
return 0;
/* Read the entries */
*num_entries = header->num_entries;
*entries = malloc(sizeof(psp_directory_entry) * header->num_entries);
@@ -197,6 +200,9 @@ static int read_bios_directory(FILE *fw, uint32_t offset, uint32_t expected_cook
return 1;
}
if (!entries || !num_entries)
return 0;
/* Read the entries */
*num_entries = header->num_entries;
*entries = malloc(sizeof(bios_directory_entry) * header->num_entries);
@@ -362,6 +368,64 @@ static int amdfw_bios_dir_walk(FILE *fw, uint32_t bios_offset, uint32_t cookie,
return 0;
}
/*
* Returns the size of the PSP directory.
*
* @param fw File to operate on
* @param psp_offset Relative offset to PSP directory
* @param cookie Expected table cookie
* @param size Where to write the size to
*
* @return 0 on success, or < 0 on error.
*/
static int amdfw_psp_dir_size(FILE *fw, uint32_t psp_offset, uint32_t cookie, uint32_t *size)
{
psp_directory_header header;
if (!fw || !size)
return -1;
if (read_psp_directory(fw, psp_offset, cookie, &header, NULL, NULL) != 0)
return -1;
if (header.additional_info_fields.version == 1)
*size = header.additional_info_fields_v1.dir_size;
else
*size = header.additional_info_fields.dir_size;
*size *= TABLE_ALIGNMENT;
return 0;
}
/*
* Returns the size of the BIOS directory.
*
* @param fw File to operate on
* @param bios_offset Relative offset to BIOS directory
* @param cookie Expected table cookie
* @param size Where to write the size to
*
* @return 0 on success, or < 0 on error.
*/
static int amdfw_bios_dir_size(FILE *fw, uint32_t bios_offset, uint32_t cookie, uint32_t *size)
{
bios_directory_hdr header;
if (!fw || !size)
return -1;
if (read_bios_directory(fw, bios_offset, cookie, &header, NULL, NULL) != 0)
return -1;
if (header.additional_info_fields.version == 1)
*size = header.additional_info_fields_v1.dir_size;
else
*size = header.additional_info_fields.dir_size;
*size *= TABLE_ALIGNMENT;
return 0;
}
static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, uint8_t level)
{
psp_directory_entry *current_entries = NULL;
@@ -443,13 +507,19 @@ static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, ui
}
l2_dir_offset = ish_dir.pl2_location;
printf(" %sPSPL2: Dir 0x%08x\n", indent, l2_dir_offset);
if (amdfw_psp_dir_size(fw, l2_dir_offset, PSPL2_COOKIE, &dir_size) == 0)
printf(" %sPSPL2: Dir [0x%08x-0x%08x)\n", indent, l2_dir_offset, l2_dir_offset + dir_size);
else
printf(" %sPSPL2: Dir @0x%08x\n", indent, l2_dir_offset);
amdfw_psp_dir_walk(fw, l2_dir_offset, PSPL2_COOKIE, level + 2);
break;
case AMD_FW_BIOS_TABLE:
bios_dir_offset = relative_offset(psp_offset, addr, mode);
printf(" %sBIOSL2: Dir 0x%08x\n", indent, bios_dir_offset);
if (amdfw_bios_dir_size(fw, bios_dir_offset, BHDL2_COOKIE, &dir_size) == 0)
printf(" %sBIOSL2: Dir [0x%08x-0x%08x)\n", indent, bios_dir_offset, bios_dir_offset + dir_size);
else
printf(" %sBIOSL2: Dir @0x%08x\n", indent, bios_dir_offset);
amdfw_bios_dir_walk(fw, bios_dir_offset, BHDL2_COOKIE, level + 2);
break;
@@ -465,7 +535,7 @@ static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, ui
static int list_amdfw_psp_dir(FILE *fw, const embedded_firmware *fw_header)
{
uint32_t psp_offset = 0;
uint32_t psp_offset = 0, dir_size = 0;
/* 0xffffffff or 0x00000000 indicates that the offset is in new_psp_directory */
if (fw_header->psp_directory != 0xffffffff && fw_header->psp_directory != 0x00000000)
@@ -473,7 +543,11 @@ static int list_amdfw_psp_dir(FILE *fw, const embedded_firmware *fw_header)
else
psp_offset = fw_header->new_psp_directory;
printf("PSPL1: Dir 0x%08x\n", psp_offset);
if (amdfw_psp_dir_size(fw, psp_offset, PSP_COOKIE, &dir_size) == 0)
printf("PSPL1: Dir [0x%08x-0x%08x)\n", psp_offset, psp_offset + dir_size);
else
printf("PSPL1: Dir @0x%08x\n", psp_offset);
amdfw_psp_dir_walk(fw, psp_offset, PSP_COOKIE, 0);
if (fw_header->psp_bak_directory != 0xffffffff && fw_header->psp_bak_directory != 0x00000000) {
@@ -492,11 +566,17 @@ static int list_amdfw_psp_dir(FILE *fw, const embedded_firmware *fw_header)
static int list_amdfw_bios_dir(FILE *fw, const embedded_firmware *fw_header)
{
uint32_t dir_size = 0;
/* 0xffffffff or 0x00000000 implies that the SoC uses recovery A/B
layout. Only BIOS L2 directory is present and that too as part of
PSP L2 directory. */
if (fw_header->bios3_entry != 0xffffffff && fw_header->bios3_entry != 0x00000000) {
printf("BIOSL1: Dir 0x%08x\n", fw_header->bios3_entry);
if (amdfw_psp_dir_size(fw, fw_header->bios3_entry, BHD_COOKIE, &dir_size) == 0)
printf("BIOSL1: Dir [0x%08x-0x%08x)\n", fw_header->bios3_entry, fw_header->bios3_entry + dir_size);
else
printf("BIOSL1: Dir @0x%08x\n", fw_header->bios3_entry);
amdfw_bios_dir_walk(fw, fw_header->bios3_entry, BHD_COOKIE, 0);
}
return 0;