From 496b15ceade91f9d86007ce71eeb25ea427a3091 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Tue, 2 Dec 2025 08:36:14 +0100 Subject: [PATCH] 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/90329 Tested-by: build bot (Jenkins) Reviewed-by: Alicja Michalska Reviewed-by: Matt DeVillier Upstream-Status: Backport [CB:90329] --- util/amdfwtool/amdfwread.c | 90 +++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/util/amdfwtool/amdfwread.c b/util/amdfwtool/amdfwread.c index 1deb1a3ba9..5c6764607f 100644 --- a/util/amdfwtool/amdfwread.c +++ b/util/amdfwtool/amdfwread.c @@ -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;