diff options
-rw-r--r-- | src/soc/intel/common/block/cse/cse_lite_cmos.c | 69 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse_lite_cmos.h | 10 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/cse.h | 12 |
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 { /* |