Attention is currently required from: Rizwan Qureshi.
Hello Rizwan Qureshi,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/77069?usp=email
to review the following change.
Change subject: soc/intel/cse: Implement APIs to access PSR backup status in CMOS ......................................................................
soc/intel/cse: Implement APIs to access PSR backup status in CMOS
PSR data is created and stored in CSE data partition. In platforms that employ CSE Lite SKU firmware, a firmware downgrade involves clearing of CSE data partition which results in PSR data being lost. The PSR data needs to be preserved across the firmware downgrade flow. CSE Lite SKU firmware supports command to backup PSR data. Since firmware downgrade and PSR data backup flows involve global resets, there is a need to track the PSR data backup status across resets. So adding a CMOS variable for the same.
This patch implements API to access PSR backup status stored in CMOS. The get API allows to retrieve the PSR backup status from CMOS memory. The update API allows to update the PSR backup status in CMOS.
This patch also adds config option for the user to choose an available offset in CMOS memory for a given platform. The offset can be configured from mainboard Kconfig.
BRANCH=None BUG=b:273207144 TEST=Able to retrieve status across resets.
Change-Id: I270894e3e08dd50ca88e5402b59c211d7e693d14 Signed-off-by: Krishna Prasad Bhat krishna.p.bhat.d@intel.com Signed-off-by: Rizwan Qureshi rizwan.qureshi@intel.com --- M src/soc/intel/common/block/cse/Kconfig M src/soc/intel/common/block/cse/Makefile.inc A src/soc/intel/common/block/cse/cmos_psr.c A src/soc/intel/common/block/include/intelblocks/cmos_psr.h 4 files changed, 135 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/77069/1
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig index 6b04b08..36cce6e 100644 --- a/src/soc/intel/common/block/cse/Kconfig +++ b/src/soc/intel/common/block/cse/Kconfig @@ -140,6 +140,14 @@ config is applicable only for Lite SKU, where PSR data backup is required prior to a CSE firmware downgrade during which data is cleared.
+config PSR_BACKUP_STATUS_CMOS_OFFSET + int + default 0 + depends on SOC_INTEL_CSE_LITE_PSR && !USE_OPTION_TABLE + help + Offset in CMOS to store the PSR backup status. The value in this offset indicates + whether PSR data has been backed up or not. + config SOC_INTEL_CSE_SERVER_SKU bool default n diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index ad15dc4..2a540ee 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -8,6 +8,8 @@ smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += disable_heci.c ramstage-$(CONFIG_SOC_INTEL_CSE_SET_EOP) += cse_eop.c romstage-$(CONFIG_SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY) += telemetry.c +romstage-$(CONFIG_SOC_INTEL_CSE_LITE_PSR) += cmos_psr.c +ramstage-$(CONFIG_SOC_INTEL_CSE_LITE_PSR) += cmos_psr.c
ifeq ($(CONFIG_STITCH_ME_BIN),y)
diff --git a/src/soc/intel/common/block/cse/cmos_psr.c b/src/soc/intel/common/block/cse/cmos_psr.c new file mode 100644 index 0000000..407fa65 --- /dev/null +++ b/src/soc/intel/common/block/cse/cmos_psr.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <ip_checksum.h> +#include <pc80/mc146818rtc.h> +#include <stdint.h> +#include <intelblocks/cmos_psr.h> + +/* + * We need a region in CMOS to store the psr_backup_status. + * + * This can either be declared as part of the option + * table or statically defined in the board config. + */ +#if CONFIG(USE_OPTION_TABLE) +# include "option_table.h" + +#ifndef CMOS_VSTART_psr_backup_status +#error "The `psr_backup_status` CMOS entry is missing, please add it to your cmos.layout." +#endif + +# define PSR_BACKUP_STATUS_CMOS_OFFSET (CMOS_VSTART_psr_backup_status_offset >> 3) +#else +# if (CONFIG_PSR_BACKUP_STATUS_CMOS_OFFSET != 0) +# define PSR_BACKUP_STATUS_CMOS_OFFSET CONFIG_PSR_BACKUP_STATUS_CMOS_OFFSET +# else +# error "Must configure CONFIG_PSR_BACKUP_STATUS_CMOS_OFFSET" +# endif +#endif + +#define PSR_BACKUP_STATUS_SIGNATURE 0x50535242 /* 'PSRB' */ + +struct psr_backup_status { + u32 signature; + u8 backup_status; + u16 checksum; +} __packed; + +/* Read and validate psr_backup_status structure from CMOS */ +static int psr_backup_status_cmos_read(struct psr_backup_status *psr) +{ + u8 i, *p; + u16 csum; + + for (p = (u8 *)psr, i = 0; i < sizeof(*psr); i++, p++) + *p = cmos_read(PSR_BACKUP_STATUS_CMOS_OFFSET + i); + + /* Verify signature */ + if (psr->signature != PSR_BACKUP_STATUS_SIGNATURE) { + printk(BIOS_DEBUG, "PSR backup status invalid signature\n"); + return -1; + } + + /* Verify checksum over signature and backup_status only */ + csum = compute_ip_checksum(psr, offsetof(struct psr_backup_status, checksum)); + + if (csum != psr->checksum) { + printk(BIOS_DEBUG, "PSR backup status checksum mismatch\n"); + return -1; + } + + return 0; +} + +/* Write psr_backup_status structure to CMOS */ +static void psr_backup_status_cmos_write(struct psr_backup_status *psr) +{ + u8 i, *p; + + /* Checksum over signature and backup_status only */ + psr->checksum = compute_ip_checksum( + psr, offsetof(struct psr_backup_status, checksum)); + + for (p = (u8 *)psr, i = 0; i < sizeof(*psr); i++, p++) + cmos_write(*p, PSR_BACKUP_STATUS_CMOS_OFFSET + i); +} + +/* Update psr_backup_status */ +void update_psr_backup_status(u8 status) +{ + struct psr_backup_status psr; + + /* Read and update psr_backup_status */ + if (psr_backup_status_cmos_read(&psr) < 0) { + /* Structure invalid, re-initialize */ + psr.signature = PSR_BACKUP_STATUS_SIGNATURE; + psr.backup_status = PSR_BACKUP_PENDING; + } + + psr.backup_status = status; + + /* Write the new status to CMOS */ + psr_backup_status_cmos_write(&psr); + + printk(BIOS_DEBUG, "PSR backup status updated\n"); +} + +/* Return the current backup_status */ +u8 get_psr_backup_status(void) +{ + struct psr_backup_status psr; + + if (psr_backup_status_cmos_read(&psr) < 0) + return 0; + + return psr.backup_status; +} diff --git a/src/soc/intel/common/block/include/intelblocks/cmos_psr.h b/src/soc/intel/common/block/include/intelblocks/cmos_psr.h new file mode 100644 index 0000000..4c6f14b --- /dev/null +++ b/src/soc/intel/common/block/include/intelblocks/cmos_psr.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_INTEL_COMMON_CMOS_PSR_H +#define SOC_INTEL_COMMON_CMOS_PSR_H + +#include <types.h> + +/* PSR backup status */ +#define PSR_BACKUP_DONE 0x55 +#define PSR_BACKUP_PENDING 0x22 + +/* Update psr_backup_status */ +void update_psr_backup_status(uint8_t status); + +/* Return the current backup_status */ +uint8_t get_psr_backup_status(void); + +#endif // SOC_INTEL_COMMON_CMOS_PSR_H