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 <fishbaozi@gmail.com>
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/85650
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com>
This commit is contained in:
Zheng Bao 2025-01-14 22:04:52 +08:00 committed by Matt DeVillier
commit 492b7c7c09
2 changed files with 78 additions and 0 deletions

View file

@ -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__ */

View file

@ -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);
}