From fdd47ef1e6914acf205c7b6c041ae3f57404271d Mon Sep 17 00:00:00 2001 From: Zheng Bao Date: Fri, 17 Sep 2021 13:30:08 +0800 Subject: [PATCH] amdfwtool: Add ISH header support for A/B recovery layout Image Slot Header (ISH) is a new feature. The rom layout for A/B recovery with ISH: EFS -> PSP L1 0x48 -> ISH A -> PSP L2 A -> BIOS L2 A 0x4A -> ISH B -> PSP L2 B -> BIOS L2 B The newer 55758 will updated about the boot priority and update retry in ISH header. Change-Id: Ib0690cde1dce949514c7aacebe13096b7814ceff Signed-off-by: Zheng Bao Reviewed-on: https://review.coreboot.org/c/coreboot/+/57747 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- util/amdfwtool/Makefile | 2 +- util/amdfwtool/Makefile.inc | 2 +- util/amdfwtool/amdfwtool.c | 57 ++++++++++++++++++++++++++++++------- util/amdfwtool/amdfwtool.h | 13 +++++++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile index 18054593f5..7b7793535a 100644 --- a/util/amdfwtool/Makefile +++ b/util/amdfwtool/Makefile @@ -5,7 +5,7 @@ HOSTCC ?= cc SRC = amdfwtool.c data_parse.c OBJ = $(SRC:%.c=%.o) TARGET = amdfwtool -WERROR=-Werror -Wno-unused-function +WERROR=-Werror CFLAGS=-O2 -Wall -Wextra -Wshadow ${WERROR} all: $(TARGET) diff --git a/util/amdfwtool/Makefile.inc b/util/amdfwtool/Makefile.inc index f7722992ae..4b7db76e4d 100644 --- a/util/amdfwtool/Makefile.inc +++ b/util/amdfwtool/Makefile.inc @@ -2,7 +2,7 @@ amdfwtoolobj = amdfwtool.o data_parse.o -AMDFWTOOLCFLAGS=-O2 -Wall -Wextra -Wshadow -Werror -Wno-unused-function +AMDFWTOOLCFLAGS=-O2 -Wall -Wextra -Wshadow -Werror $(objutil)/amdfwtool/%.o: $(top)/util/amdfwtool/%.c # $(HEADER) $(HOSTCC) $(AMDFWTOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $< diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c index 263336a7f1..f0fdd0af93 100644 --- a/util/amdfwtool/amdfwtool.c +++ b/util/amdfwtool/amdfwtool.c @@ -421,6 +421,15 @@ static void *new_psp_dir(context *ctx, int multi) return ptr; } +static void *new_ish_dir(context *ctx) +{ + void *ptr; + ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT); + ptr = BUFF_CURRENT(*ctx); + ctx->current += TABLE_ALIGNMENT; + return ptr; +} + #if PSP_COMBO static void *new_combo_dir(context *ctx) { @@ -672,7 +681,8 @@ static void free_bdt_firmware_filenames(amd_bios_entry *fw_table) } static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir, - psp_directory_table *pspdir2, amd_fw_type ab) + psp_directory_table *pspdir2, ish_directory_table *ish, + amd_fw_type ab, enum platform soc_id) { uint32_t count; uint32_t current_table_save; @@ -684,11 +694,28 @@ static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir, pspdir->entries[count].type = (uint8_t)ab; pspdir->entries[count].subprog = 0; pspdir->entries[count].rsvd = 0; - pspdir->entries[count].addr = BUFF_TO_RUN_MODE(*ctx, pspdir2, ADDRESS_MODE_1_REL_BIOS); - pspdir->entries[count].address_mode = SET_ADDR_MODE(pspdir, ADDRESS_MODE_1_REL_BIOS); - pspdir->entries[count].size = pspdir2->header.num_entries * + if (ish != NULL) { + ish->pl2_location = BUFF_TO_RUN_MODE(*ctx, pspdir2, ADDRESS_MODE_1_REL_BIOS); + ish->boot_priority = ab == AMD_FW_RECOVERYAB_A ? 0xFFFFFFFF : 1; + ish->update_retry_count = 2; + ish->glitch_retry_count = 0; + ish->psp_id = get_psp_id(soc_id); + ish->checksum = fletcher32(&ish->boot_priority, + sizeof(ish_directory_table) - sizeof(uint32_t)); + pspdir->entries[count].addr = + BUFF_TO_RUN_MODE(*ctx, ish, ADDRESS_MODE_1_REL_BIOS); + pspdir->entries[count].address_mode = + SET_ADDR_MODE(pspdir, ADDRESS_MODE_1_REL_BIOS); + pspdir->entries[count].size = TABLE_ALIGNMENT; + } else { + pspdir->entries[count].addr = + BUFF_TO_RUN_MODE(*ctx, pspdir2, ADDRESS_MODE_1_REL_BIOS); + pspdir->entries[count].address_mode = + SET_ADDR_MODE(pspdir, ADDRESS_MODE_1_REL_BIOS); + pspdir->entries[count].size = pspdir2->header.num_entries * sizeof(psp_directory_entry) + sizeof(psp_directory_header); + } count++; pspdir->header.num_entries = count; @@ -701,6 +728,7 @@ static void integrate_psp_firmwares(context *ctx, psp_directory_table *pspdir2_b, amd_fw_entry *fw_table, uint32_t cookie, + enum platform soc_id, amd_cb_config *cb_config) { ssize_t bytes; @@ -708,6 +736,7 @@ static void integrate_psp_firmwares(context *ctx, int level; uint32_t current_table_save; bool recovery_ab = cb_config->recovery_ab; + ish_directory_table *ish_a_dir = NULL, *ish_b_dir = NULL; /* This function can create a primary table, a secondary table, or a * flattened table which contains all applicable types. These if-else @@ -815,10 +844,17 @@ static void integrate_psp_firmwares(context *ctx, } if (recovery_ab && (pspdir2 != NULL)) { + if (cb_config->need_ish) { /* Need ISH */ + ish_a_dir = new_ish_dir(ctx); + if (pspdir2_b != NULL) + ish_b_dir = new_ish_dir(ctx); + } pspdir->header.num_entries = count; - integrate_psp_ab(ctx, pspdir, pspdir2, AMD_FW_RECOVERYAB_A); + integrate_psp_ab(ctx, pspdir, pspdir2, ish_a_dir, + AMD_FW_RECOVERYAB_A, soc_id); if (pspdir2_b != NULL) - integrate_psp_ab(ctx, pspdir, pspdir2_b, AMD_FW_RECOVERYAB_B); + integrate_psp_ab(ctx, pspdir, pspdir2_b, ish_b_dir, + AMD_FW_RECOVERYAB_B, soc_id); count = pspdir->header.num_entries; } else if (pspdir2 != NULL) { assert_fw_entry(count, MAX_PSP_ENTRIES, ctx); @@ -1455,6 +1491,7 @@ int main(int argc, char **argv) cb_config.s0i3 = false; cb_config.multi_level = false; cb_config.recovery_ab = false; + cb_config.need_ish = false; while (1) { int optindex = 0; @@ -1777,25 +1814,25 @@ int main(int argc, char **argv) /* Do 2nd PSP directory followed by 1st */ pspdir2 = new_psp_dir(&ctx, cb_config.multi_level); integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL, - amd_psp_fw_table, PSPL2_COOKIE, &cb_config); + amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config); if (cb_config.recovery_ab) { /* B is same as above directories for A */ /* Skip creating pspdir2_b here to save flash space. Related * biosdir2_b will be skipped automatically. */ pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level); integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL, - amd_psp_fw_table, PSPL2_COOKIE, &cb_config); + amd_psp_fw_table, PSPL2_COOKIE, soc_id, &cb_config); } else { pspdir2_b = NULL; /* More explicitly */ } pspdir = new_psp_dir(&ctx, cb_config.multi_level); integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b, - amd_psp_fw_table, PSP_COOKIE, &cb_config); + amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config); } else { /* flat: PSP 1 cookie and no pointer to 2nd table */ pspdir = new_psp_dir(&ctx, cb_config.multi_level); integrate_psp_firmwares(&ctx, pspdir, NULL, NULL, - amd_psp_fw_table, PSP_COOKIE, &cb_config); + amd_psp_fw_table, PSP_COOKIE, soc_id, &cb_config); } if (comboable) diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h index ff2f63bb8f..a241316cbb 100644 --- a/util/amdfwtool/amdfwtool.h +++ b/util/amdfwtool/amdfwtool.h @@ -235,6 +235,18 @@ typedef struct _amd_bios_entry { int level; } amd_bios_entry; +typedef struct _ish_directory_table { + uint32_t checksum; + uint32_t boot_priority; + uint32_t update_retry_count; + uint8_t glitch_retry_count; + uint8_t glitch_higherbits_reserved[3]; + uint32_t pl2_location; + uint32_t psp_id; + uint32_t slot_max_size; + uint32_t reserved; +} __attribute__((packed)) ish_directory_table; + #define EMBEDDED_FW_SIGNATURE 0x55aa55aa #define PSP_COOKIE 0x50535024 /* 'PSP$' */ #define PSPL2_COOKIE 0x324c5024 /* '2LP$' */ @@ -265,6 +277,7 @@ typedef struct _amd_cb_config { bool s0i3; bool have_mb_spl; bool recovery_ab; + bool need_ish; } amd_cb_config; void register_fw_fuse(char *str);