Dinesh Gehlot has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/75751?usp=email )
Change subject: soc/intel/cmd/blk/cse: Implement APIs to access CSE version in CMOS ......................................................................
soc/intel/cmd/blk/cse: Implement APIs to access CSE version in CMOS
This patch implements APIs to access the CSE version in CMOS. The get API allows users to retrieve the current CSE version from CMOS memory. The set API allows users to set the CSE version in CMOS memory.
BUG=b:280722061 Test=Verified the changes nissa board.
Signed-off-by: Dinesh Gehlot digehlot@google.com Change-Id: I3d5d895ab00766e0f1964d06e58738a2addb911f --- M src/soc/intel/common/block/cse/Makefile.inc A src/soc/intel/common/block/cse/cse_cmos.c A src/soc/intel/common/block/include/intelblocks/cse_cmos.h 3 files changed, 139 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/51/75751/1
diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc index 3e11279..ccf2f6e 100644 --- a/src/soc/intel/common/block/cse/Makefile.inc +++ b/src/soc/intel/common/block/cse/Makefile.inc @@ -1,4 +1,5 @@ ## SPDX-License-Identifier: GPL-2.0-only +ramstage-$(CONFIG_SOC_INTEL_CACHE_CSE_VERSION_IN_CMOS) += cse_cmos.c romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c romstage-$(CONFIG_SOC_INTEL_CSE_LITE_SKU) += cse_lite.c diff --git a/src/soc/intel/common/block/cse/cse_cmos.c b/src/soc/intel/common/block/cse/cse_cmos.c new file mode 100644 index 0000000..be0455f --- /dev/null +++ b/src/soc/intel/common/block/cse/cse_cmos.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <intelblocks/cse_cmos.h> +#include <ip_checksum.h> +#include <pc80/mc146818rtc.h> + +#define PARTITION_FW_SIGNATURE 0x46575054 /* 'FWPT' */ + +/* + * We need a region in CMOS to store the firmware versions. + * + * 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_partition_fw +#error "The `ramtop` CMOS entry is missing, please add it to your cmos.layout." +#endif + +#if CMOS_VSTART_partition_fw % 8 != 0 +#error "The `partition firmware` CMOS entry needs to be byte aligned, check your cmos.layout." +#endif // CMOS_VSTART_partition_fw % 8 != 0 + +#if CMOS_VLEN_partition_fw != (16 * 8) +#error "The partition firmware entry needs to be 16 bytes long, check your cmos.layout." +#endif + +# define PARTITION_FW_CMOS_OFFSET (CMOS_VSTART_partition_fw >> 3) + +#else +# if (CONFIG_SOC_INTEL_PARTITION_FW_CMOS_OFFSET != 0) +# define PARTITION_FW_CMOS_OFFSET CONFIG_SOC_INTEL_PARTITION_FW_CMOS_OFFSET +# else +# error "Must configure CONFIG_SOC_INTEL_PARTITION_FW_CMOS_OFFSET" +# endif +#endif + +struct cse_fw_table { + uint32_t signature; + struct fw_version cse_version; + uint16_t checksum; +} __packed; + +/* Helper function to read firmware version from cmos memory. */ +static uint32_t read_cmos_partition_version(struct cse_fw_table *version) +{ + u8 i, *p, offset = PARTITION_FW_CMOS_OFFSET; + u16 csum; + + for (p = (u8 *)version, i = 0; i < sizeof(*version); i++, p++) + *p = cmos_read(offset + i); + + /* Verify signature */ + if (version->signature != PARTITION_FW_SIGNATURE) { + printk(BIOS_DEBUG, "cse firmware partition invalid signature\n"); + return -1; + } + + /* Verify checksum over signature and firmware versions only */ + csum = compute_ip_checksum(version, offsetof(struct cse_fw_table, checksum)); + + if (csum != version->checksum) { + printk(BIOS_DEBUG, "cse firmware partition checksum mismatch\n"); + return -1; + } + + return 0; +} + +/* Helper function to write firmware version to cmos memory. */ +static void write_cmos_partition_version(struct cse_fw_table *version) +{ + u8 i, *p, offset = PARTITION_FW_CMOS_OFFSET; + + /* Checksum over signature and firmware versions only */ + version->checksum = compute_ip_checksum(version, offsetof(struct cse_fw_table, checksum)); + + for (p = (u8 *)version, i = 0; i < sizeof(*version); i++, p++) + cmos_write(*p, offset + i); +} + +/* Helper function to initialize cmos firmware version. */ +static void init_cmos_partition_version(struct cse_fw_table *version) +{ + u8 i, *p, offset = PARTITION_FW_CMOS_OFFSET; + version->signature = PARTITION_FW_SIGNATURE; + memset(&version->cse_version, 0, sizeof(struct fw_version)); + version->checksum = compute_ip_checksum(version, offsetof(struct cse_fw_table, checksum)); + + for (p = (u8 *)version, i = 0; i < sizeof(*version); i++, p++) + cmos_write(*p, offset + i); +} + +/* API that allows users to read CSE version stored in CMOS memory. */ +void get_cmos_cse_version(struct fw_version *cse_version) +{ + struct cse_fw_table version; + if (read_cmos_partition_version(&version)) { + /* + * CMOS failed to read the CSE version. This may be because the firmware version at + * cmos has not yet been initialized. + */ + init_cmos_partition_version(&version); + } + memcpy(cse_version, &version.cse_version, sizeof(struct fw_version)); +} + +/* API that allows users to update CSE version stored in CMOS memory. */ +void set_cmos_cse_version(const struct fw_version *cse_version) +{ + struct cse_fw_table version; + if (read_cmos_partition_version(&version)) { + /* + * CMOS failed to read the CSE version. This may be because the firmware version at + * cmos has not yet been initialized. + */ + init_cmos_partition_version(&version); + } + memcpy(&version.cse_version, cse_version, sizeof(struct fw_version)); + write_cmos_partition_version(&version); +} diff --git a/src/soc/intel/common/block/include/intelblocks/cse_cmos.h b/src/soc/intel/common/block/include/intelblocks/cse_cmos.h new file mode 100644 index 0000000..8026a19 --- /dev/null +++ b/src/soc/intel/common/block/include/intelblocks/cse_cmos.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_INTEL_COMMON_BLOCK_CSE_CMOS_H +#define SOC_INTEL_COMMON_BLOCK_CSE_CMOS_H + +#include <intelblocks/cse.h> + +/* Function to get the cse version stored in CMOS memory */ +void get_cmos_cse_version(struct fw_version *cse_version); + +/* Function to update the cse version stored in CMOS memory */ +void set_cmos_cse_version(const struct fw_version *cse_version); + +#endif /* SOC_INTEL_COMMON_BLOCK_CSE_CMOS_H */