util/amdfwtool: Handle address mode properly for Turin

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 <michal.zygowski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89039
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Benjamin Doron <benjamin.doron00@gmail.com>
This commit is contained in:
Michał Żygowski 2025-09-04 14:26:13 +02:00 committed by Matt DeVillier
commit 46b03e682c
2 changed files with 38 additions and 4 deletions

View file

@ -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,
&current_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,
&current_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",

View file

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