From 46b03e682cd9cfc166425f0200336e786bcee65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Thu, 4 Sep 2025 14:26:13 +0200 Subject: [PATCH] util/amdfwtool: Handle address mode properly for Turin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to read a firmware binary for Turin platform results in "Invalid address(41400) or mode(0)" error. The utility does not respect the address mode set by the directory header. The address mode of th entries is valid only if the address mode of the directory is equal to 2 or 3. Check the address mode of the directory and use it for entries only when its value is less than 2. TEST=Successfuly parse vendor BIOS for Gigabyte MZ33-AR1. Change-Id: I479bc846bfb334231fdc707274a8ac44b6c384d4 Signed-off-by: Michał Żygowski Reviewed-on: https://review.coreboot.org/c/coreboot/+/89039 Tested-by: build bot (Jenkins) Reviewed-by: Benjamin Doron --- util/amdfwtool/amdfwread.c | 20 +++++++++++++++++++- util/amdfwtool/amdfwtool.h | 22 +++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/util/amdfwtool/amdfwread.c b/util/amdfwtool/amdfwread.c index 88ccf3a78d..ddd0bc3fb0 100644 --- a/util/amdfwtool/amdfwread.c +++ b/util/amdfwtool/amdfwread.c @@ -263,18 +263,27 @@ static int amdfw_bios_dir_walk(FILE *fw, uint32_t bios_offset, uint32_t cookie, size_t num_current_entries = 0; bios_directory_hdr header; uint32_t l2_dir_offset = 0; + uint64_t dir_mode = 0; char indent[MAX_INDENTATION_LEN] = {0}; if (read_bios_directory(fw, bios_offset, cookie, &header, ¤t_entries, &num_current_entries) != 0) return 1; + if (header.additional_info_fields.version == 1) + dir_mode = header.additional_info_fields_v1.address_mode; + else + dir_mode = header.additional_info_fields.address_mode; + do_indentation_string(indent, level); for (size_t i = 0; i < num_current_entries; i++) { uint32_t type = current_entries[i].type; uint64_t mode = current_entries[i].address_mode; uint64_t addr = current_entries[i].source; + if (dir_mode < 2) + mode = dir_mode; + if (type == AMD_BIOS_APOB || type == AMD_BIOS_PSP_SHARED_MEM) printf("%sBIOS%s: 0x%02x 0x%lx(DRAM-Address)\n", indent, cookie == BHD_COOKIE ? "L1" : "L2", @@ -313,22 +322,31 @@ static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, ui uint32_t bios_dir_offset = 0; uint32_t ish_dir_offset = 0; ish_directory_table ish_dir; + uint64_t dir_mode = 0; char indent[MAX_INDENTATION_LEN] = {0}; if (read_psp_directory(fw, psp_offset, cookie, &header, ¤t_entries, &num_current_entries) != 0) return 1; + if (header.additional_info_fields.version == 1) + dir_mode = header.additional_info_fields_v1.address_mode; + else + dir_mode = header.additional_info_fields.address_mode; + do_indentation_string(indent, level); for (size_t i = 0; i < num_current_entries; i++) { uint32_t type = current_entries[i].type; uint64_t mode = current_entries[i].address_mode; uint64_t addr = current_entries[i].addr; + if (dir_mode < 2) + mode = dir_mode; + if (type == AMD_PSP_FUSE_CHAIN) printf("%sPSP%s: 0x%02x 0x%lx(Soft-fuse)\n", indent, cookie == PSP_COOKIE ? "L1" : "L2", - type, mode << 62 | addr); + type, (uint64_t)current_entries[i].address_mode << 62 | addr); else printf("%sPSP%s: 0x%02x 0x%08lx 0x%08x\n", indent, cookie == PSP_COOKIE ? "L1" : "L2", diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h index 9897721607..2327584813 100644 --- a/util/amdfwtool/amdfwtool.h +++ b/util/amdfwtool/amdfwtool.h @@ -210,8 +210,16 @@ typedef struct _psp_directory_header { uint32_t spi_block_size:4; uint32_t base_addr:15; uint32_t address_mode:2; - uint32_t not_used:1; + uint32_t version:1; } __attribute__((packed)) additional_info_fields; + struct { + uint32_t dir_size:16; + uint32_t spi_block_size:4; + uint32_t dir_header_size:4; + uint32_t address_mode:2; + uint32_t reserved:5; + uint32_t version:1; + } __attribute__((packed)) additional_info_fields_v1; }; } __attribute__((packed, aligned(16))) psp_directory_header; @@ -272,8 +280,16 @@ typedef struct _bios_directory_hdr { uint32_t spi_block_size:4; uint32_t base_addr:15; uint32_t address_mode:2; - uint32_t not_used:1; + uint32_t version:1; } __attribute__((packed)) additional_info_fields; + struct { + uint32_t dir_size:16; + uint32_t spi_block_size:4; + uint32_t dir_header_size:4; + uint32_t address_mode:2; + uint32_t reserved:5; + uint32_t version:1; + } __attribute__((packed)) additional_info_fields_v1; }; } __attribute__((packed, aligned(16))) bios_directory_hdr; @@ -459,7 +475,7 @@ typedef struct _amd_cb_config { typedef struct _context { char *rom; /* target buffer, size of flash device */ uint32_t rom_size; /* size of flash device */ - uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table */ + uint32_t address_mode; /* 0:abs address; 1:relative to flash; 2: relative to table 3: relative to partition */ uint32_t current; /* pointer within flash & proxy buffer */ uint32_t current_pointer_saved; uint32_t current_table;