blob: 02d0232376a3f2e78f928fa59655264448c339a8 [file] [log] [blame]
Dinesh Gehlot91da19c2023-05-07 13:47:49 +00001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <console/console.h>
4#include <ip_checksum.h>
5#include <pc80/mc146818rtc.h>
6
7#include "cse_lite_cmos.h"
8
9/*
10 * We need a region in CMOS to store the firmware versions.
11 *
12 * This can either be declared as part of the option
13 * table or statically defined in the board config.
14 */
15#if CONFIG(USE_OPTION_TABLE)
16# include "option_table.h"
17
18#ifndef CMOS_VSTART_partition_fw
19#error "The `ramtop` CMOS entry is missing, please add it to your cmos.layout."
20#endif
21
22#if CMOS_VSTART_partition_fw % 8 != 0
23#error "The `partition firmware` CMOS entry needs to be byte aligned, check your cmos.layout."
24#endif // CMOS_VSTART_partition_fw % 8 != 0
25
26#if CMOS_VLEN_partition_fw != (32 * 8)
27#error "The partition firmware entry needs to be 32 bytes long, check your cmos.layout."
28#endif
29
30# define PARTITION_FW_CMOS_OFFSET (CMOS_VSTART_partition_fw >> 3)
31
32#else
33# if (CONFIG_SOC_INTEL_CSE_FW_PARTITION_CMOS_OFFSET != 0)
34# define PARTITION_FW_CMOS_OFFSET CONFIG_SOC_INTEL_CSE_FW_PARTITION_CMOS_OFFSET
35# else
36# error "Must configure CONFIG_SOC_INTEL_CSE_FW_PARTITION_CMOS_OFFSET"
37# endif
38#endif
39
Krishna Prasad Bhat98fb5ff2023-07-18 21:49:17 +053040#define PSR_BACKUP_STATUS_SIGNATURE 0x42525350 /* 'PSRB' */
41
Dinesh Gehlot91da19c2023-05-07 13:47:49 +000042/* Helper function to read CSE fpt information from cmos memory. */
43void cmos_read_fw_partition_info(struct cse_specific_info *info)
44{
45 for (uint8_t *p = (uint8_t *)info, i = 0; i < sizeof(*info); i++, p++)
46 *p = cmos_read(PARTITION_FW_CMOS_OFFSET + i);
47}
48
49/* Helper function to write CSE fpt information to cmos memory. */
50void cmos_write_fw_partition_info(const struct cse_specific_info *info)
51{
52 for (uint8_t *p = (uint8_t *)info, i = 0; i < sizeof(*info); i++, p++)
53 cmos_write(*p, PARTITION_FW_CMOS_OFFSET + i);
54}
Krishna Prasad Bhat98fb5ff2023-07-18 21:49:17 +053055
56/* Read and validate `psr_backup_status` structure from CMOS */
57static int psr_backup_status_cmos_read(struct psr_backup_status *psr)
58{
59 for (uint8_t *p = (uint8_t *)psr, i = 0; i < sizeof(*psr); i++, p++)
60 *p = cmos_read(PARTITION_FW_CMOS_OFFSET + sizeof(struct cse_specific_info) + i);
61
62 /* Verify signature */
63 if (psr->signature != PSR_BACKUP_STATUS_SIGNATURE) {
64 printk(BIOS_ERR, "PSR backup status invalid signature\n");
65 return -1;
66 }
67
68 /* Verify checksum over signature and backup_status only */
69 uint16_t csum = compute_ip_checksum(psr, offsetof(struct psr_backup_status, checksum));
70
71 if (csum != psr->checksum) {
72 printk(BIOS_ERR, "PSR backup status checksum mismatch\n");
73 return -1;
74 }
75
76 return 0;
77}
78
79/* Write `psr_backup_status structure` to CMOS */
80static void psr_backup_status_cmos_write(struct psr_backup_status *psr)
81{
82 /* Checksum over signature and backup_status only */
83 psr->checksum = compute_ip_checksum(
84 psr, offsetof(struct psr_backup_status, checksum));
85
86 for (uint8_t *p = (uint8_t *)psr, i = 0; i < sizeof(*psr); i++, p++)
87 cmos_write(*p, PARTITION_FW_CMOS_OFFSET + sizeof(struct cse_specific_info) + i);
88}
89
90/* Helper function to update the `psr_backup_status` in CMOS memory */
91void update_psr_backup_status(int8_t status)
92{
93 struct psr_backup_status psr;
94
95 /* Read and update psr_backup_status */
96 if (psr_backup_status_cmos_read(&psr) < 0)
97 /* Structure invalid, re-initialize */
98 psr.signature = PSR_BACKUP_STATUS_SIGNATURE;
99
100 psr.value = status;
101
102 /* Write the new status to CMOS */
103 psr_backup_status_cmos_write(&psr);
104
105 printk(BIOS_INFO, "PSR backup status updated\n");
106}
107
108/*
109 * Helper function to retrieve the current `psr_backup_status` in CMOS memory
110 * Returns current status on success, the status can be PSR_BACKUP_DONE or PSR_BACKUP_PENDING.
111 * Returns -1 in case of signature mismatch or checksum failure.
112 */
113int8_t get_psr_backup_status(void)
114{
115 struct psr_backup_status psr;
116
117 if (psr_backup_status_cmos_read(&psr) < 0)
118 return -1;
119
120 return psr.value;
121}