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 <fishbaozi@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57747
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Zheng Bao 2021-09-17 13:30:08 +08:00 committed by Felix Held
parent 5f18bb75fb
commit fdd47ef1e6
4 changed files with 62 additions and 12 deletions

View File

@ -5,7 +5,7 @@ HOSTCC ?= cc
SRC = amdfwtool.c data_parse.c SRC = amdfwtool.c data_parse.c
OBJ = $(SRC:%.c=%.o) OBJ = $(SRC:%.c=%.o)
TARGET = amdfwtool TARGET = amdfwtool
WERROR=-Werror -Wno-unused-function WERROR=-Werror
CFLAGS=-O2 -Wall -Wextra -Wshadow ${WERROR} CFLAGS=-O2 -Wall -Wextra -Wshadow ${WERROR}
all: $(TARGET) all: $(TARGET)

View File

@ -2,7 +2,7 @@
amdfwtoolobj = amdfwtool.o data_parse.o 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) $(objutil)/amdfwtool/%.o: $(top)/util/amdfwtool/%.c # $(HEADER)
$(HOSTCC) $(AMDFWTOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $< $(HOSTCC) $(AMDFWTOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $<

View File

@ -421,6 +421,15 @@ static void *new_psp_dir(context *ctx, int multi)
return ptr; 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 #if PSP_COMBO
static void *new_combo_dir(context *ctx) 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, 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 count;
uint32_t current_table_save; 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].type = (uint8_t)ab;
pspdir->entries[count].subprog = 0; pspdir->entries[count].subprog = 0;
pspdir->entries[count].rsvd = 0; pspdir->entries[count].rsvd = 0;
pspdir->entries[count].addr = BUFF_TO_RUN_MODE(*ctx, pspdir2, ADDRESS_MODE_1_REL_BIOS); if (ish != NULL) {
pspdir->entries[count].address_mode = SET_ADDR_MODE(pspdir, ADDRESS_MODE_1_REL_BIOS); 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 * pspdir->entries[count].size = pspdir2->header.num_entries *
sizeof(psp_directory_entry) + sizeof(psp_directory_entry) +
sizeof(psp_directory_header); sizeof(psp_directory_header);
}
count++; count++;
pspdir->header.num_entries = count; pspdir->header.num_entries = count;
@ -701,6 +728,7 @@ static void integrate_psp_firmwares(context *ctx,
psp_directory_table *pspdir2_b, psp_directory_table *pspdir2_b,
amd_fw_entry *fw_table, amd_fw_entry *fw_table,
uint32_t cookie, uint32_t cookie,
enum platform soc_id,
amd_cb_config *cb_config) amd_cb_config *cb_config)
{ {
ssize_t bytes; ssize_t bytes;
@ -708,6 +736,7 @@ static void integrate_psp_firmwares(context *ctx,
int level; int level;
uint32_t current_table_save; uint32_t current_table_save;
bool recovery_ab = cb_config->recovery_ab; 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 /* This function can create a primary table, a secondary table, or a
* flattened table which contains all applicable types. These if-else * 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 (recovery_ab && (pspdir2 != NULL)) {
pspdir->header.num_entries = count; if (cb_config->need_ish) { /* Need ISH */
integrate_psp_ab(ctx, pspdir, pspdir2, AMD_FW_RECOVERYAB_A); ish_a_dir = new_ish_dir(ctx);
if (pspdir2_b != NULL) if (pspdir2_b != NULL)
integrate_psp_ab(ctx, pspdir, pspdir2_b, AMD_FW_RECOVERYAB_B); ish_b_dir = new_ish_dir(ctx);
}
pspdir->header.num_entries = count;
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, ish_b_dir,
AMD_FW_RECOVERYAB_B, soc_id);
count = pspdir->header.num_entries; count = pspdir->header.num_entries;
} else if (pspdir2 != NULL) { } else if (pspdir2 != NULL) {
assert_fw_entry(count, MAX_PSP_ENTRIES, ctx); assert_fw_entry(count, MAX_PSP_ENTRIES, ctx);
@ -1455,6 +1491,7 @@ int main(int argc, char **argv)
cb_config.s0i3 = false; cb_config.s0i3 = false;
cb_config.multi_level = false; cb_config.multi_level = false;
cb_config.recovery_ab = false; cb_config.recovery_ab = false;
cb_config.need_ish = false;
while (1) { while (1) {
int optindex = 0; int optindex = 0;
@ -1777,25 +1814,25 @@ int main(int argc, char **argv)
/* Do 2nd PSP directory followed by 1st */ /* Do 2nd PSP directory followed by 1st */
pspdir2 = new_psp_dir(&ctx, cb_config.multi_level); pspdir2 = new_psp_dir(&ctx, cb_config.multi_level);
integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL, 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) { if (cb_config.recovery_ab) {
/* B is same as above directories for A */ /* B is same as above directories for A */
/* Skip creating pspdir2_b here to save flash space. Related /* Skip creating pspdir2_b here to save flash space. Related
* biosdir2_b will be skipped automatically. */ * biosdir2_b will be skipped automatically. */
pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level); pspdir2_b = new_psp_dir(&ctx, cb_config.multi_level);
integrate_psp_firmwares(&ctx, pspdir2_b, NULL, NULL, 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 { } else {
pspdir2_b = NULL; /* More explicitly */ pspdir2_b = NULL; /* More explicitly */
} }
pspdir = new_psp_dir(&ctx, cb_config.multi_level); pspdir = new_psp_dir(&ctx, cb_config.multi_level);
integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b, 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 { } else {
/* flat: PSP 1 cookie and no pointer to 2nd table */ /* flat: PSP 1 cookie and no pointer to 2nd table */
pspdir = new_psp_dir(&ctx, cb_config.multi_level); pspdir = new_psp_dir(&ctx, cb_config.multi_level);
integrate_psp_firmwares(&ctx, pspdir, NULL, NULL, 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) if (comboable)

View File

@ -235,6 +235,18 @@ typedef struct _amd_bios_entry {
int level; int level;
} amd_bios_entry; } 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 EMBEDDED_FW_SIGNATURE 0x55aa55aa
#define PSP_COOKIE 0x50535024 /* 'PSP$' */ #define PSP_COOKIE 0x50535024 /* 'PSP$' */
#define PSPL2_COOKIE 0x324c5024 /* '2LP$' */ #define PSPL2_COOKIE 0x324c5024 /* '2LP$' */
@ -265,6 +277,7 @@ typedef struct _amd_cb_config {
bool s0i3; bool s0i3;
bool have_mb_spl; bool have_mb_spl;
bool recovery_ab; bool recovery_ab;
bool need_ish;
} amd_cb_config; } amd_cb_config;
void register_fw_fuse(char *str); void register_fw_fuse(char *str);