summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/common/block/cse/cse_lite_cmos.c69
-rw-r--r--src/soc/intel/common/block/cse/cse_lite_cmos.h10
-rw-r--r--src/soc/intel/common/block/include/intelblocks/cse.h12
3 files changed, 91 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/cse/cse_lite_cmos.c b/src/soc/intel/common/block/cse/cse_lite_cmos.c
index 5fc3fb0e42..02d0232376 100644
--- a/src/soc/intel/common/block/cse/cse_lite_cmos.c
+++ b/src/soc/intel/common/block/cse/cse_lite_cmos.c
@@ -37,6 +37,8 @@
# endif
#endif
+#define PSR_BACKUP_STATUS_SIGNATURE 0x42525350 /* 'PSRB' */
+
/* Helper function to read CSE fpt information from cmos memory. */
void cmos_read_fw_partition_info(struct cse_specific_info *info)
{
@@ -50,3 +52,70 @@ void cmos_write_fw_partition_info(const struct cse_specific_info *info)
for (uint8_t *p = (uint8_t *)info, i = 0; i < sizeof(*info); i++, p++)
cmos_write(*p, PARTITION_FW_CMOS_OFFSET + i);
}
+
+/* Read and validate `psr_backup_status` structure from CMOS */
+static int psr_backup_status_cmos_read(struct psr_backup_status *psr)
+{
+ for (uint8_t *p = (uint8_t *)psr, i = 0; i < sizeof(*psr); i++, p++)
+ *p = cmos_read(PARTITION_FW_CMOS_OFFSET + sizeof(struct cse_specific_info) + i);
+
+ /* Verify signature */
+ if (psr->signature != PSR_BACKUP_STATUS_SIGNATURE) {
+ printk(BIOS_ERR, "PSR backup status invalid signature\n");
+ return -1;
+ }
+
+ /* Verify checksum over signature and backup_status only */
+ uint16_t csum = compute_ip_checksum(psr, offsetof(struct psr_backup_status, checksum));
+
+ if (csum != psr->checksum) {
+ printk(BIOS_ERR, "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)
+{
+ /* Checksum over signature and backup_status only */
+ psr->checksum = compute_ip_checksum(
+ psr, offsetof(struct psr_backup_status, checksum));
+
+ for (uint8_t *p = (uint8_t *)psr, i = 0; i < sizeof(*psr); i++, p++)
+ cmos_write(*p, PARTITION_FW_CMOS_OFFSET + sizeof(struct cse_specific_info) + i);
+}
+
+/* Helper function to update the `psr_backup_status` in CMOS memory */
+void update_psr_backup_status(int8_t 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.value = status;
+
+ /* Write the new status to CMOS */
+ psr_backup_status_cmos_write(&psr);
+
+ printk(BIOS_INFO, "PSR backup status updated\n");
+}
+
+/*
+ * Helper function to retrieve the current `psr_backup_status` in CMOS memory
+ * Returns current status on success, the status can be PSR_BACKUP_DONE or PSR_BACKUP_PENDING.
+ * Returns -1 in case of signature mismatch or checksum failure.
+ */
+int8_t get_psr_backup_status(void)
+{
+ struct psr_backup_status psr;
+
+ if (psr_backup_status_cmos_read(&psr) < 0)
+ return -1;
+
+ return psr.value;
+}
diff --git a/src/soc/intel/common/block/cse/cse_lite_cmos.h b/src/soc/intel/common/block/cse/cse_lite_cmos.h
index a6dd6ce7f2..c8cd6e3d42 100644
--- a/src/soc/intel/common/block/cse/cse_lite_cmos.h
+++ b/src/soc/intel/common/block/cse/cse_lite_cmos.h
@@ -11,4 +11,14 @@ void cmos_read_fw_partition_info(struct cse_specific_info *info);
/* Helper function to write CSE fpt information to cmos memory. */
void cmos_write_fw_partition_info(const struct cse_specific_info *info);
+/* Helper function to update the `psr_backup_status` in CMOS memory */
+void update_psr_backup_status(int8_t status);
+
+/*
+ * Helper function to retrieve the current `psr_backup_status` in CMOS memory
+ * Returns current status on success, the status can be PSR_BACKUP_DONE or PSR_BACKUP_PENDING.
+ * Returns -1 in case of signature mismatch or checksum failure.
+ */
+int8_t get_psr_backup_status(void);
+
#endif /* SOC_INTEL_COMMON_BLOCK_CSE_LITE_CMOS_H */
diff --git a/src/soc/intel/common/block/include/intelblocks/cse.h b/src/soc/intel/common/block/include/intelblocks/cse.h
index 0f7356854d..ebf20ed857 100644
--- a/src/soc/intel/common/block/include/intelblocks/cse.h
+++ b/src/soc/intel/common/block/include/intelblocks/cse.h
@@ -167,6 +167,18 @@ struct cse_specific_info {
uint32_t crc;
};
+/* PSR backup status */
+enum psr_backup_state {
+ PSR_BACKUP_DONE = 0,
+ PSR_BACKUP_PENDING = 1,
+};
+
+struct psr_backup_status {
+ uint32_t signature;
+ int8_t value;
+ uint16_t checksum;
+};
+
/* CSE RX and TX error status */
enum cse_tx_rx_status {
/*