diff options
author | Zheng Bao <fishbaozi@gmail.com> | 2021-09-17 13:24:54 +0800 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2022-02-21 23:47:20 +0000 |
commit | 990d154898f97318ec812bed1e0fc1b9e84666f5 (patch) | |
tree | 10ee741178dd0e9c1dc50a20db9e8f6771024cf7 | |
parent | 1a9e54302b421b6d838be48a921529b45bc89413 (diff) |
amdfwtool: Add support for AMD's BIOS A/B recovery feature
The rom layout for A/B recovery:
EFS -> PSP L1 0x48 -> PSP L2 A -> BIOS L2 A
0x4A -> PSP L2 B -> BIOS L2 B
The coreboot doesn't implement the AMD's A/B recovery. This is only
for the ROM layout. To save some flash space, the entire B section can
be eliminated.
To enable A/B recovery in PSP layout, add "--recovery-ab" to
amdfwtool.
TEST=Majolica(Cezanne)
Change-Id: I27f5d3476f648fcecafb8d258ccb6cfad4f50036
Signed-off-by: Zheng Bao <fishbaozi@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/56773
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
-rw-r--r-- | util/amdfwtool/amdfwtool.c | 246 | ||||
-rw-r--r-- | util/amdfwtool/amdfwtool.h | 10 | ||||
-rw-r--r-- | util/amdfwtool/data_parse.c | 36 |
3 files changed, 217 insertions, 75 deletions
diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c index e586748b13..38629b1b7c 100644 --- a/util/amdfwtool/amdfwtool.c +++ b/util/amdfwtool/amdfwtool.c @@ -165,6 +165,7 @@ static void usage(void) printf("--load-s0i3 Set if load s0i3 firmware\n"); printf("--verstage <FILE> Add verstage\n"); printf("--verstage_sig Add verstage signature\n"); + printf("--recovery-ab Use the recovery A/B layout\n"); printf("\nBIOS options:\n"); printf("--instance <number> Sets instance field for the next BIOS\n"); printf(" firmware\n"); @@ -220,60 +221,60 @@ static void usage(void) } amd_fw_entry amd_psp_fw_table[] = { - { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH }, + { .type = AMD_FW_PSP_PUBKEY, .level = PSP_BOTH | PSP_BOTH_AB }, + { .type = AMD_FW_PSP_BOOTLOADER, .level = PSP_BOTH | PSP_LVL1_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB }, { .type = AMD_FW_PSP_RECOVERY, .level = PSP_LVL1 }, { .type = AMD_FW_PSP_RTM_PUBKEY, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH }, - { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 }, - { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 }, - { .type = AMD_HW_IPCFG, .level = PSP_LVL2 }, - { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH }, - { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH }, - { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH }, - { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH }, - { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH }, - { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 }, - { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 }, - { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 }, - { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 }, - { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2}, - { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 }, - { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH }, - { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH }, - { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 }, - { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 }, - { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH }, - { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 }, - { .type = AMD_FW_SPL, .level = PSP_LVL2 }, - { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 }, - { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 }, - { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 }, - { .type = AMD_ABL0, .level = PSP_BOTH }, - { .type = AMD_ABL1, .level = PSP_BOTH }, - { .type = AMD_ABL2, .level = PSP_BOTH }, - { .type = AMD_ABL3, .level = PSP_BOTH }, - { .type = AMD_ABL4, .level = PSP_BOTH }, - { .type = AMD_ABL5, .level = PSP_BOTH }, - { .type = AMD_ABL6, .level = PSP_BOTH }, - { .type = AMD_ABL7, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH }, - { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH }, + { .type = AMD_FW_PSP_SECURED_OS, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SECURED_DEBUG, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_TRUSTLETS, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_TRUSTLETKEY, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE2, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMUSCS, .level = PSP_BOTH }, + { .type = AMD_PSP_FUSE_CHAIN, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_DEBUG_UNLOCK, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_HW_IPCFG, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_WRAPPED_IKEK, .level = PSP_BOTH | PSP_BOTH_AB }, + { .type = AMD_TOKEN_UNLOCK, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_SEC_GASKET, .subprog = 0, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_SEC_GASKET, .subprog = 2, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_SEC_GASKET, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_MP2_FW, .subprog = 2, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_MP2_FW, .subprog = 1, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_MP2_FW, .subprog = 0, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_DRIVER_ENTRIES, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_KVM_IMAGE, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_S0I3_DRIVER, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_VBIOS_BTLOADER, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_TOS_SEC_POLICY, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_USB_PHY, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_DRTM_TA, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_KEYDB_BL, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_KEYDB_TOS, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_SPL, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_DMCU_ERAM, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_DMCU_ISR, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_RPMC_NVRAM, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_BOOTLOADER_AB, .level = PSP_LVL2 | PSP_LVL2_AB }, + { .type = AMD_ABL0, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL1, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL2, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL3, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL4, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL5, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL6, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_ABL7, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB }, + { .type = AMD_FW_PSP_SMU_FIRMWARE2, .subprog = 1, .level = PSP_BOTH | PSP_LVL2_AB }, { .type = AMD_FW_PSP_WHITELIST, .level = PSP_LVL2 }, - { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH }, - { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH }, + { .type = AMD_FW_PSP_VERSTAGE, .level = PSP_BOTH | PSP_BOTH_AB }, + { .type = AMD_FW_VERSTAGE_SIG, .level = PSP_BOTH | PSP_BOTH_AB }, { .type = AMD_FW_INVALID }, }; @@ -405,6 +406,7 @@ static void *new_psp_dir(context *ctx, int multi) ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT); ptr = BUFF_CURRENT(*ctx); + ((psp_directory_header *)ptr)->num_entries = 0; ((psp_directory_header *)ptr)->additional_info = 0; ((psp_directory_header *)ptr)->additional_info_fields.address_mode = ctx->address_mode; ctx->current += sizeof(psp_directory_header) @@ -662,9 +664,34 @@ 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) +{ + uint32_t count; + uint32_t current_table_save; + + current_table_save = ctx->current_table; + ctx->current_table = (char *)pspdir - ctx->rom; + count = pspdir->header.num_entries; + assert_fw_entry(count, MAX_PSP_ENTRIES, ctx); + 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 * + sizeof(psp_directory_entry) + + sizeof(psp_directory_header); + + count++; + pspdir->header.num_entries = count; + ctx->current_table = current_table_save; +} + static void integrate_psp_firmwares(context *ctx, psp_directory_table *pspdir, psp_directory_table *pspdir2, + psp_directory_table *pspdir2_b, amd_fw_entry *fw_table, uint32_t cookie, amd_cb_config *cb_config) @@ -673,6 +700,7 @@ static void integrate_psp_firmwares(context *ctx, unsigned int i, count; int level; uint32_t current_table_save; + bool recovery_ab = cb_config->recovery_ab; /* This function can create a primary table, a secondary table, or a * flattened table which contains all applicable types. These if-else @@ -690,6 +718,14 @@ static void integrate_psp_firmwares(context *ctx, else level = PSP_BOTH; + if (recovery_ab) { + if (cookie == PSPL2_COOKIE) + level = PSP_LVL2_AB; + else if (pspdir2) + level = PSP_LVL1_AB; + else + level = PSP_BOTH_AB; + } current_table_save = ctx->current_table; ctx->current_table = (char *)pspdir - ctx->rom; ctx->current = ALIGN(ctx->current, TABLE_ALIGNMENT); @@ -771,7 +807,13 @@ static void integrate_psp_firmwares(context *ctx, } } - if (pspdir2) { + if (recovery_ab && (pspdir2 != NULL)) { + pspdir->header.num_entries = count; + integrate_psp_ab(ctx, pspdir, pspdir2, AMD_FW_RECOVERYAB_A); + if (pspdir2_b != NULL) + integrate_psp_ab(ctx, pspdir, pspdir2_b, AMD_FW_RECOVERYAB_B); + count = pspdir->header.num_entries; + } else if (pspdir2 != NULL) { assert_fw_entry(count, MAX_PSP_ENTRIES, ctx); pspdir->entries[count].type = AMD_FW_L2_PTR; pspdir->entries[count].subprog = 0; @@ -791,6 +833,42 @@ static void integrate_psp_firmwares(context *ctx, ctx->current_table = current_table_save; } +static void add_psp_firmware_entry(context *ctx, + psp_directory_table *pspdir, + void *table, amd_fw_type type, uint32_t size) +{ + uint32_t count = pspdir->header.num_entries; + uint32_t index; + uint32_t current_table_save; + + current_table_save = ctx->current_table; + ctx->current_table = (char *)pspdir - ctx->rom; + + /* If there is an entry of "type", replace it. */ + for (index = 0; index < count; index++) { + if (pspdir->entries[index].type == (uint8_t)type) + break; + } + + assert_fw_entry(count, MAX_PSP_ENTRIES, ctx); + pspdir->entries[index].type = (uint8_t)type; + pspdir->entries[index].subprog = 0; + pspdir->entries[index].rsvd = 0; + pspdir->entries[index].addr = BUFF_TO_RUN(*ctx, table); + pspdir->entries[index].address_mode = SET_ADDR_MODE_BY_TABLE(pspdir); + pspdir->entries[index].size = size; + if (index == count) + count++; + + pspdir->header.num_entries = count; + pspdir->header.checksum = fletcher32(&pspdir->header.num_entries, + count * sizeof(psp_directory_entry) + + sizeof(pspdir->header.num_entries) + + sizeof(pspdir->header.additional_info)); + + ctx->current_table = current_table_save; +} + static void *new_bios_dir(context *ctx, bool multi) { void *ptr; @@ -1078,6 +1156,7 @@ enum { AMDFW_OPT_IMC, AMDFW_OPT_GEC, AMDFW_OPT_COMBO, + AMDFW_OPT_RECOVERY_AB, AMDFW_OPT_MULTILEVEL, AMDFW_OPT_NVRAM, @@ -1125,6 +1204,7 @@ static struct option long_options[] = { {"gec", required_argument, 0, AMDFW_OPT_GEC }, /* PSP Directory Table items */ {"combo-capable", no_argument, 0, AMDFW_OPT_COMBO }, + {"recovery-ab", no_argument, 0, AMDFW_OPT_RECOVERY_AB }, {"multilevel", no_argument, 0, AMDFW_OPT_MULTILEVEL }, {"nvram", required_argument, 0, AMDFW_OPT_NVRAM }, {"soft-fuse", required_argument, 0, AMDFW_OPT_FUSE }, @@ -1337,7 +1417,9 @@ int main(int argc, char **argv) char *tmp; char *rom = NULL; embedded_firmware *amd_romsig; - psp_directory_table *pspdir; + psp_directory_table *pspdir = NULL; + psp_directory_table *pspdir2 = NULL; + psp_directory_table *pspdir2_b = NULL; bool comboable = false; int fuse_defined = 0; int targetfd; @@ -1365,6 +1447,7 @@ int main(int argc, char **argv) cb_config.load_mp2_fw = false; cb_config.s0i3 = false; cb_config.multi_level = false; + cb_config.recovery_ab = false; while (1) { int optindex = 0; @@ -1390,6 +1473,9 @@ int main(int argc, char **argv) case AMDFW_OPT_COMBO: comboable = true; break; + case AMDFW_OPT_RECOVERY_AB: + cb_config.recovery_ab = true; + break; case AMDFW_OPT_MULTILEVEL: cb_config.multi_level = true; break; @@ -1594,6 +1680,10 @@ int main(int argc, char **argv) retval = 1; } + if (cb_config.recovery_ab) { + cb_config.multi_level = true; + } + if (retval) { usage(); return retval; @@ -1678,16 +1768,26 @@ int main(int argc, char **argv) if (cb_config.multi_level) { /* Do 2nd PSP directory followed by 1st */ - psp_directory_table *pspdir2 = new_psp_dir(&ctx, cb_config.multi_level); - integrate_psp_firmwares(&ctx, pspdir2, NULL, - amd_psp_fw_table, PSPL2_COOKIE, &cb_config); + pspdir2 = new_psp_dir(&ctx, cb_config.multi_level); + integrate_psp_firmwares(&ctx, pspdir2, NULL, NULL, + amd_psp_fw_table, PSPL2_COOKIE, &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); + } else { + pspdir2_b = NULL; /* More explicitly */ + } pspdir = new_psp_dir(&ctx, cb_config.multi_level); - integrate_psp_firmwares(&ctx, pspdir, pspdir2, + integrate_psp_firmwares(&ctx, pspdir, pspdir2, pspdir2_b, amd_psp_fw_table, PSP_COOKIE, &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, + integrate_psp_firmwares(&ctx, pspdir, NULL, NULL, amd_psp_fw_table, PSP_COOKIE, &cb_config); } @@ -1709,17 +1809,32 @@ int main(int argc, char **argv) #endif if (have_bios_tables(amd_bios_table)) { - bios_directory_table *biosdir; + bios_directory_table *biosdir = NULL; if (cb_config.multi_level) { /* Do 2nd level BIOS directory followed by 1st */ - bios_directory_table *biosdir2 = - new_bios_dir(&ctx, cb_config.multi_level); + bios_directory_table *biosdir2 = NULL; + bios_directory_table *biosdir2_b = NULL; + + biosdir2 = new_bios_dir(&ctx, cb_config.multi_level); + integrate_bios_firmwares(&ctx, biosdir2, NULL, amd_bios_table, BDT2_COOKIE, &cb_config); - - biosdir = new_bios_dir(&ctx, cb_config.multi_level); - integrate_bios_firmwares(&ctx, biosdir, biosdir2, + if (cb_config.recovery_ab) { + if (pspdir2_b != NULL) { + biosdir2_b = new_bios_dir(&ctx, cb_config.multi_level); + integrate_bios_firmwares(&ctx, biosdir2_b, NULL, + amd_bios_table, BDT2_COOKIE, &cb_config); + } + add_psp_firmware_entry(&ctx, pspdir2, biosdir2, + AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT); + if (pspdir2_b != NULL) + add_psp_firmware_entry(&ctx, pspdir2_b, biosdir2_b, + AMD_FW_BIOS_TABLE, TABLE_ALIGNMENT); + } else { + biosdir = new_bios_dir(&ctx, cb_config.multi_level); + integrate_bios_firmwares(&ctx, biosdir, biosdir2, amd_bios_table, BDT1_COOKIE, &cb_config); + } } else { /* flat: BDT1 cookie and no pointer to 2nd table */ biosdir = new_bios_dir(&ctx, cb_config.multi_level); @@ -1730,7 +1845,8 @@ int main(int argc, char **argv) case PLATFORM_RENOIR: case PLATFORM_LUCIENNE: case PLATFORM_CEZANNE: - amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir); + if (!cb_config.recovery_ab) + amd_romsig->bios3_entry = BUFF_TO_RUN(ctx, biosdir); break; case PLATFORM_MENDOCINO: break; diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h index 79e52fc932..70afe3c6df 100644 --- a/util/amdfwtool/amdfwtool.h +++ b/util/amdfwtool/amdfwtool.h @@ -43,6 +43,9 @@ typedef enum _amd_fw_type { AMD_FW_USB_PHY = 0x44, AMD_FW_TOS_SEC_POLICY = 0x45, AMD_FW_DRTM_TA = 0x47, + AMD_FW_RECOVERYAB_A = 0x48, + AMD_FW_RECOVERYAB_B = 0x4A, + AMD_FW_BIOS_TABLE = 0x49, AMD_FW_KEYDB_BL = 0x50, AMD_FW_KEYDB_TOS = 0x51, AMD_FW_PSP_VERSTAGE = 0x52, @@ -209,7 +212,10 @@ typedef struct _bios_directory_table { #define BDT_LVL1 (1 << 0) #define BDT_LVL2 (1 << 1) +#define BDT_LVL1_AB (1 << 2) +#define BDT_LVL2_AB (1 << 3) #define BDT_BOTH (BDT_LVL1 | BDT_LVL2) +#define BDT_BOTH_AB (BDT_LVL1_AB | BDT_LVL2_AB) typedef struct _amd_bios_entry { amd_bios_type type; char *filename; @@ -235,7 +241,10 @@ typedef struct _amd_bios_entry { #define PSP_LVL1 (1 << 0) #define PSP_LVL2 (1 << 1) +#define PSP_LVL1_AB (1 << 2) +#define PSP_LVL2_AB (1 << 3) #define PSP_BOTH (PSP_LVL1 | PSP_LVL2) +#define PSP_BOTH_AB (PSP_LVL1_AB | PSP_LVL2_AB) typedef struct _amd_fw_entry { amd_fw_type type; char *filename; @@ -252,6 +261,7 @@ typedef struct _amd_cb_config { bool multi_level; bool s0i3; bool have_mb_spl; + bool recovery_ab; } amd_cb_config; void register_fw_fuse(char *str); diff --git a/util/amdfwtool/data_parse.c b/util/amdfwtool/data_parse.c index d27b7bb1e6..c69a38958e 100644 --- a/util/amdfwtool/data_parse.c +++ b/util/amdfwtool/data_parse.c @@ -78,18 +78,18 @@ void compile_reg_expr(int cflags, const char *expr, regex_t *reg) } } -#define SET_LEVEL(tableptr, l, TABLE) \ +#define SET_LEVEL(tableptr, l, TABLE, ab) \ do { \ switch ((l)) { \ case '1': \ - (tableptr)->level = TABLE##_LVL1;\ + (tableptr)->level = ab ? TABLE##_LVL1_AB : TABLE##_LVL1; \ break; \ case '2': \ - (tableptr)->level = TABLE##_LVL2;\ + (tableptr)->level = ab ? TABLE##_LVL2_AB : TABLE##_LVL2; \ break; \ case 'b': \ case 'B': \ - (tableptr)->level = TABLE##_BOTH;\ + (tableptr)->level = ab ? TABLE##_BOTH_AB : TABLE##_BOTH; \ break; \ default: \ /* use default value */ \ @@ -114,9 +114,20 @@ static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename, } else { fw_type = AMD_FW_SKIP; } + } else if (strcmp(fw_name, "PSPBTLDR_AB_STAGE1_FILE") == 0) { + if (cb_config->recovery_ab) { + fw_type = AMD_FW_PSP_BOOTLOADER; + subprog = 0; + } else { + fw_type = AMD_FW_SKIP; + } } else if (strcmp(fw_name, "PSPBTLDR_FILE") == 0) { - fw_type = AMD_FW_PSP_BOOTLOADER; - subprog = 0; + if (!cb_config->recovery_ab) { + fw_type = AMD_FW_PSP_BOOTLOADER; + subprog = 0; + } else { + fw_type = AMD_FW_SKIP; + } } else if (strcmp(fw_name, "AMD_PUBKEY_FILE") == 0) { fw_type = AMD_FW_PSP_PUBKEY; subprog = 0; @@ -302,7 +313,7 @@ static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename, fw_type = AMD_RPMC_NVRAM; subprog = 0; } else if (strcmp(fw_name, "PSPBTLDR_AB_FILE") == 0) { - if (!cb_config->have_whitelist) { + if (!cb_config->have_whitelist || cb_config->recovery_ab) { fw_type = AMD_FW_PSP_BOOTLOADER_AB; subprog = 0; } else { @@ -320,7 +331,8 @@ static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename, /* instance are not used in PSP table */ if (psp_tableptr->type == fw_type && psp_tableptr->subprog == subprog) { psp_tableptr->filename = filename; - SET_LEVEL(psp_tableptr, level_to_set, PSP); + SET_LEVEL(psp_tableptr, level_to_set, PSP, + cb_config->recovery_ab); break; } psp_tableptr++; @@ -378,7 +390,8 @@ static uint8_t find_register_fw_filename_bios_dir(char *fw_name, char *filename, bhd_tableptr->subpr == subprog && bhd_tableptr->inst == instance) { bhd_tableptr->filename = filename; - SET_LEVEL(bhd_tableptr, level_to_set, BDT); + SET_LEVEL(bhd_tableptr, level_to_set, BDT, + cb_config->recovery_ab); break; } bhd_tableptr++; @@ -512,7 +525,10 @@ uint8_t process_config(FILE *config, amd_cb_config *cb_config, uint8_t print_dep /* If the optional level field is present, extract the level char. */ if (match[3].rm_so != 0) { - ch_lvl = oneline[match[3].rm_so + 1]; + if (cb_config->recovery_ab == 0) + ch_lvl = oneline[match[3].rm_so + 1]; + else + ch_lvl = oneline[match[3].rm_so + 2]; } if (find_register_fw_filename_psp_dir( |