Attention is currently required from: Zheng Bao.
Hello Zheng Bao,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/72741
to review the following change.
Change subject: amdfwread: Extract the FWs in image. ......................................................................
amdfwread: Extract the FWs in image.
Prepare for replacement.
Change-Id: I4714c45dafc3d5e5c95bb15258711a061e2582c0 Signed-off-by: Zheng Bao fishbaozi@gmail.com --- M util/amdfwtool/amdfwread.c 1 file changed, 111 insertions(+), 10 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/41/72741/1
diff --git a/util/amdfwtool/amdfwread.c b/util/amdfwtool/amdfwread.c index 711b158..f2d8590 100644 --- a/util/amdfwtool/amdfwread.c +++ b/util/amdfwtool/amdfwread.c @@ -82,6 +82,18 @@ return fw_header->signature != EMBEDDED_FW_SIGNATURE; }
+static int write_bin(FILE *fw, void *data, size_t bin_size) +{ + fwrite(data, bin_size, 1, fw); + + return 0; +} + +static int read_bin(FILE *fw, uint32_t offset, void *binary, size_t bin_size) +{ + return read_header(fw, offset, binary, bin_size); +} + static int read_psp_directory(FILE *fw, uint32_t offset, uint32_t expected_cookie, psp_directory_header *header, psp_directory_entry **entries, size_t *num_entries) @@ -234,6 +246,28 @@ return 1; }
+static void save_fws(FILE *fw, uint32_t type, uint32_t offset, uint32_t bytes) +{ + char filename[512]; + uint32_t *buffer; + + sprintf(filename, "PspDirL1_Typex%02x.bin", type); + buffer = malloc(bytes); + read_bin(fw, offset, buffer, bytes); + + FILE *mod_fd = fopen(filename, "wb"); + + if (mod_fd) { + write_bin(mod_fd, buffer, bytes); + fclose(mod_fd); + } else { + fprintf(stderr, "Error: could not open file: %s\n", filename); + } + + free(buffer); +} + + #define MAX_NUM_LEVELS 10 #define MAX_INDENT_PER_LEVEL 4 #define MAX_INDENTATION_LEN (MAX_NUM_LEVELS * MAX_INDENT_PER_LEVEL + 1) @@ -244,7 +278,8 @@ strcat(dest, "+-->"); }
-static int amdfw_bios_dir_walk(FILE *fw, uint32_t bios_offset, uint32_t cookie, uint8_t level) +static int amdfw_bios_dir_walk(FILE *fw, uint32_t bios_offset, uint32_t cookie, uint8_t level, + uint8_t extract) { bios_directory_entry *current_entries = NULL; size_t num_current_entries = 0; @@ -271,11 +306,15 @@ indent, cookie == BHD_COOKIE ? "L1" : "L2", type, relative_offset(bios_offset, addr, AMD_ADDR_PHYSICAL), current_entries[i].size); - else + else { printf("%sBIOS%s: 0x%02x 0x%08lx 0x%08x\n", indent, cookie == BHD_COOKIE ? "L1" : "L2", type, relative_offset(bios_offset, addr, mode), current_entries[i].size); + if (extract) + save_fws(fw, type, relative_offset(bios_offset, addr, mode), + current_entries[i].size); + }
if (type == AMD_BIOS_L2_PTR) { /* There's a second level BIOS directory to read */ @@ -288,7 +327,7 @@
l2_dir_offset = relative_offset(bios_offset, addr, mode); printf(" %sBIOSL2: Dir 0x%08x\n", indent, l2_dir_offset); - amdfw_bios_dir_walk(fw, l2_dir_offset, BHDL2_COOKIE, level + 2); + amdfw_bios_dir_walk(fw, l2_dir_offset, BHDL2_COOKIE, level + 2, extract); } }
@@ -296,7 +335,8 @@ return 0; }
-static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, uint8_t level) +static int amdfw_psp_dir_walk(FILE *fw, uint32_t psp_offset, uint32_t cookie, uint8_t level, + uint8_t extract) { psp_directory_entry *current_entries = NULL; size_t num_current_entries = 0; @@ -321,11 +361,15 @@ printf("%sPSP%s: 0x%02x 0x%lx(Soft-fuse)\n", indent, cookie == PSP_COOKIE ? "L1" : "L2", type, mode << 62 | addr); - else + else { printf("%sPSP%s: 0x%02x 0x%08lx 0x%08x\n", indent, cookie == PSP_COOKIE ? "L1" : "L2", type, relative_offset(psp_offset, addr, mode), current_entries[i].size); + if (extract) + save_fws(fw, type, relative_offset(psp_offset, addr, mode), + current_entries[i].size); + }
switch (type) { case AMD_FW_L2_PTR: @@ -339,7 +383,7 @@
l2_dir_offset = relative_offset(psp_offset, addr, mode); printf(" %sPSPL2: Dir 0x%08x\n", indent, l2_dir_offset); - amdfw_psp_dir_walk(fw, l2_dir_offset, PSPL2_COOKIE, level + 2); + amdfw_psp_dir_walk(fw, l2_dir_offset, PSPL2_COOKIE, level + 2, extract); break;
case AMD_FW_RECOVERYAB_A: @@ -359,13 +403,13 @@
l2_dir_offset = ish_dir.pl2_location; printf(" %sPSPL2: Dir 0x%08x\n", indent, l2_dir_offset); - amdfw_psp_dir_walk(fw, l2_dir_offset, PSPL2_COOKIE, level + 2); + amdfw_psp_dir_walk(fw, l2_dir_offset, PSPL2_COOKIE, level + 2, extract); 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); - amdfw_bios_dir_walk(fw, bios_dir_offset, BHDL2_COOKIE, level + 2); + amdfw_bios_dir_walk(fw, bios_dir_offset, BHDL2_COOKIE, level + 2, extract); break;
default: @@ -389,7 +433,7 @@ psp_offset = fw_header->new_psp_directory;
printf("PSPL1: Dir 0x%08x\n", psp_offset); - amdfw_psp_dir_walk(fw, psp_offset, PSP_COOKIE, 0); + amdfw_psp_dir_walk(fw, psp_offset, PSP_COOKIE, 0, 0); return 0; }
@@ -399,7 +443,7 @@ is present and that too as part of PSP L2 directory. */ if (fw_header->bios3_entry != 0xffffffff) { printf("BIOSL1: Dir 0x%08x\n", fw_header->bios3_entry); - amdfw_bios_dir_walk(fw, fw_header->bios3_entry, BHD_COOKIE, 0); + amdfw_bios_dir_walk(fw, fw_header->bios3_entry, BHD_COOKIE, 0, 0); } return 0; } @@ -413,10 +457,46 @@ return 0; }
+static int extract_amdfw_psp_dir(FILE *fw, const embedded_firmware *fw_header) +{ + uint32_t psp_offset = 0; + + /* 0xffffffff indicates that the offset is in new_psp_directory */ + if (fw_header->psp_directory != 0xffffffff) + psp_offset = fw_header->psp_directory; + else + psp_offset = fw_header->new_psp_directory; + + printf("PSPL1: Dir 0x%08x\n", psp_offset); + amdfw_psp_dir_walk(fw, psp_offset, PSP_COOKIE, 0, 1); + return 0; +} + +static int extract_amdfw_bios_dir(FILE *fw, const embedded_firmware *fw_header) +{ + /* 0xffffffff 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) { + printf("BIOSL1: Dir 0x%08x\n", fw_header->bios3_entry); + amdfw_bios_dir_walk(fw, fw_header->bios3_entry, BHD_COOKIE, 0, 1); + } + return 0; +} + + +static int extract_all(FILE *fw, const embedded_firmware *fw_header) +{ + extract_amdfw_psp_dir(fw, fw_header); + extract_amdfw_bios_dir(fw, fw_header); + + return 0; +} + enum { AMDFW_OPT_HELP = 'h', AMDFW_OPT_SOFT_FUSE = 1UL << 0, /* Print Softfuse */ AMDFW_OPT_RO_LIST = 1UL << 1, /* List entries in AMDFW RO */ + AMDFW_OPT_EXTRACT_ALL = 1UL << 2, /* Extract all FWs */ };
static char const optstring[] = {AMDFW_OPT_HELP}; @@ -425,6 +505,7 @@ {"help", no_argument, 0, AMDFW_OPT_HELP}, {"soft-fuse", no_argument, 0, AMDFW_OPT_SOFT_FUSE}, {"ro-list", no_argument, 0, AMDFW_OPT_RO_LIST}, + {"extract-all", no_argument, 0, AMDFW_OPT_EXTRACT_ALL}, };
static void print_usage(void) @@ -462,6 +543,7 @@
case AMDFW_OPT_SOFT_FUSE: case AMDFW_OPT_RO_LIST: + case AMDFW_OPT_EXTRACT_ALL: selected_functions |= opt; break;
@@ -506,6 +588,13 @@ } }
+ if (selected_functions & AMDFW_OPT_EXTRACT_ALL) { + if (extract_all(fw, &fw_header) != 0) { + fclose(fw); + return 1; + } + } + fclose(fw); return 0; }