From 492b7c7c098623d96e2882fdee0d349178cfc6f1 Mon Sep 17 00:00:00 2001 From: Zheng Bao Date: Tue, 14 Jan 2025 22:04:52 +0800 Subject: [PATCH] soc/amd/common/block/psp: Add commands for A/B recovery PSP supports A/B updates of the PSP directory structure. This is unrelated to VBOOT's A/B update scheme. At boot the PSP structures of partition A are verified. If A is found corrupted partition B will used to read in the PSP files. x86 software can then fix the A partition and switch back to the A partition. Add functions to get, set and toggle the active boot partition used on the next boot. Change-Id: Ia7f2eedae5b277745cb34a0761bd1a8b61441695 Signed-off-by: Zheng Bao Signed-off-by: Patrick Rudolph Reviewed-on: https://review.coreboot.org/c/coreboot/+/85650 Tested-by: build bot (Jenkins) Reviewed-by: Maximilian Brune --- src/soc/amd/common/block/psp/psp_def.h | 30 ++++++++++++++++ src/soc/amd/common/block/psp/psp_gen2.c | 48 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/soc/amd/common/block/psp/psp_def.h b/src/soc/amd/common/block/psp/psp_def.h index c1513337cf..e20627e650 100644 --- a/src/soc/amd/common/block/psp/psp_def.h +++ b/src/soc/amd/common/block/psp/psp_def.h @@ -29,6 +29,8 @@ #define MBOX_BIOS_CMD_HSTI_QUERY 0x14 #define HSTI_STATE_ROM_ARMOR_ENFORCED BIT(11) #define MBOX_BIOS_CMD_PSB_AUTO_FUSING 0x21 +#define MBOX_BIOS_CMD_SET_BOOTPARTITION 0x26 +#define MBOX_BIOS_CMD_GET_BOOTPARTITION 0x36 #define MBOX_BIOS_CMD_PSP_CAPS_QUERY 0x27 #define MBOX_BIOS_CMD_SET_SPL_FUSE 0x2d #define MBOX_BIOS_CMD_SET_RPMC_ADDRESS 0x39 @@ -115,6 +117,17 @@ struct mbox_cmd_late_spl_buffer { uint32_t spl_value; } __packed __aligned(32); +/* + * MBOX_BIOS_CMD_SET_BOOTPARTITION, + * MBOX_BIOS_CMD_GET_BOOTPARTITION + * + * boot_partition is typically 0 or 1. + */ +struct mbox_cmd_boot_partition_buffer { + struct mbox_buffer_header header; + uint32_t boot_partition; +} __packed __aligned(32); + struct dtpm_config { uint32_t gpio; } __packed; @@ -179,4 +192,21 @@ void enable_psp_smi(void); void psp_set_smm_flag(void); void psp_clear_smm_flag(void); +/* psp_ab_recovery_set_bootpartition - Set active partition on next boot. + * @param partition: Active partition on next boot. 0: A, 1: B. + * @return 0 on success + */ +int psp_ab_recovery_set_bootpartition(const uint32_t partition); + +/* psp_ab_recovery_get_bootpartition - Get active partition on next boot. + * @return negative on failure. 0 if A is active boot partition, 1 if B is active + * boot partition. + */ +int psp_ab_recovery_get_bootpartition(void); + +/* psp_ab_recovery_toggle_bootpartition - Toggle active partition on next boot. + * @return 0 on success + */ +int psp_ab_recovery_toggle_bootpartition(void); + #endif /* __AMD_PSP_DEF_H__ */ diff --git a/src/soc/amd/common/block/psp/psp_gen2.c b/src/soc/amd/common/block/psp/psp_gen2.c index b3cb6ef8ed..10784acfc7 100644 --- a/src/soc/amd/common/block/psp/psp_gen2.c +++ b/src/soc/amd/common/block/psp/psp_gen2.c @@ -223,3 +223,51 @@ enum cb_err soc_read_c2p38(uint32_t *msg_38_value) *msg_38_value = read32p(psp_mmio | CORE_2_PSP_MSG_38_OFFSET); return CB_SUCCESS; } + +int psp_ab_recovery_set_bootpartition(const uint32_t partition) +{ + struct mbox_cmd_boot_partition_buffer boot_partition_cmd = { + .header = { + .size = sizeof(boot_partition_cmd) + }, + .boot_partition = partition, + }; + int cmd_status; + + cmd_status = send_psp_command(MBOX_BIOS_CMD_SET_BOOTPARTITION, &boot_partition_cmd); + + /* buffer's status shouldn't change but report it if it does */ + psp_print_cmd_status(cmd_status, &boot_partition_cmd.header); + + return cmd_status; +} + +int psp_ab_recovery_get_bootpartition(void) +{ + struct mbox_cmd_boot_partition_buffer boot_partition_cmd = { + .header = { + .size = sizeof(boot_partition_cmd) + }, + .boot_partition = 0xFFFFFFFF, + }; + int cmd_status; + + cmd_status = send_psp_command(MBOX_BIOS_CMD_GET_BOOTPARTITION, &boot_partition_cmd); + + /* buffer's status shouldn't change but report it if it does */ + psp_print_cmd_status(cmd_status, &boot_partition_cmd.header); + + if (cmd_status < 0) + return cmd_status; + + return boot_partition_cmd.boot_partition; +} + +int psp_ab_recovery_toggle_bootpartition(void) +{ + int cmd_status = psp_ab_recovery_get_bootpartition(); + if (cmd_status < 0) + return cmd_status; + + return psp_ab_recovery_set_bootpartition(cmd_status ? 0 : 1); +}