{commonlib, soc/intel/cmn/cse}: Store CSE firmware version into CBMEM

The patch implements an API that stores the CSE firmware version in the
CBMEM table. The API will be called from RAMSTAGE based on boot state
machine BS_PRE_DEVICE/BS_ON_EXIT

Additionally, renamed ramstage_cse_fw_sync() to ramstage_cse_misc_ops()
in order to add more CSE related operations at ramstage.

This patch also adds a configuration option,
'SOC_INTEL_STORE_CSE_FPT_PARTITION_VERSION', which enables the storage
of firmware version information in CBMEM memory. This information can be
used to identify the firmware version that is currently installed on the
system. The option depends on the `DRIVERS_INTEL_ISH` config and
platform should be flexible enough to opt out from enabling this
feature.

The cost of sending HECI command to read the CSE FPT is significant
(~200ms) hence, the idea is to read the CSE RW version on every cold
reset (to cover the CSE update scenarios) and store into CBMEM to
avoid the cost of resending the HECI command in all consecutive warm
boots.

Later boot stages can just read the CBMEM ID to retrieve the ISH
version if required.

Finally, ensure this feature is platform specific hence, getting
enabled for the platform that would like to store the ISH version into
the CBMEM and parse to perform some additional work.

BUG=b:273661726
TEST=Able to build and boot google/marasov.

Signed-off-by: Dinesh Gehlot <digehlot@google.com>
Change-Id: I923049d2f1f589f87e1a29e1ac94af7f5fccc2c8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/74256
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
diff --git a/src/soc/intel/common/block/cse/cse_lite.c b/src/soc/intel/common/block/cse/cse_lite.c
index 14a7381..f7ebed0 100644
--- a/src/soc/intel/common/block/cse/cse_lite.c
+++ b/src/soc/intel/common/block/cse/cse_lite.c
@@ -1159,6 +1159,26 @@
 	timestamp_add_now(TS_CSE_FW_SYNC_END);
 }
 
+/*
+ * Helper function that stores current CSE firmware version to CBMEM memory,
+ * except during recovery mode.
+ */
+static void store_cse_rw_fw_version(void)
+{
+	if (vboot_recovery_mode_enabled())
+		return;
+
+	struct get_bp_info_rsp cse_bp_info;
+	if (!cse_get_bp_info(&cse_bp_info)) {
+		printk(BIOS_ERR, "cse_lite: Failed to get CSE boot partition info\n");
+		return;
+	}
+	const struct cse_bp_entry *cse_bp = cse_get_bp_entry(RW, &cse_bp_info.bp_info);
+	struct cse_fw_partition_info *version;
+	version = cbmem_add(CBMEM_ID_CSE_PARTITION_VERSION, sizeof(*version));
+	memcpy(&(version->cur_cse_fw_version), &(cse_bp->fw_ver), sizeof(struct fw_version));
+}
+
 static enum cb_err send_get_fpt_partition_info_cmd(enum fpt_partition_id id,
 	struct fw_version_resp *resp)
 {
@@ -1216,13 +1236,21 @@
 	return send_get_fpt_partition_info_cmd(id, resp);
 }
 
-static void ramstage_cse_fw_sync(void *unused)
+static void ramstage_cse_misc_ops(void *unused)
 {
 	if (acpi_get_sleep_type() == ACPI_S3)
 		return;
 
 	if (CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_RAMSTAGE))
 		cse_fw_sync();
+
+	/*
+	 * Store the CSE RW Firmware Version into CBMEM if ISH partition
+	 * is available
+	 */
+	if (CONFIG(SOC_INTEL_STORE_CSE_FPT_PARTITION_VERSION) &&
+			 soc_is_ish_partition_enabled())
+		store_cse_rw_fw_version();
 }
 
-BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_EXIT, ramstage_cse_fw_sync, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_EXIT, ramstage_cse_misc_ops, NULL);