soc/intel/cmn/cse: Refactor CSE RW FW Version implementation

This patch introduces a CSE firmware specific data in order
to store Intel CSE and associated firmware related information which
requires a sync between Pre-RAM and Post-RAM phase.

This information will be used further to retrieve currently running
CSE RW firmware instead of fetching the version information by sending
a HECI cmd (which consumes 7ms-15ms depending upon the CSE operational
state).

Current implementation attempts to simply the CSE RW FW version store
and retrieval operations as below

* CSE sync in romstage (aka Pre-RAM) - Relying on .bss segment to store
  the CSE info data in absence of real physical memory and sync back into
  the CBMEM once available (after FSP-M exits).

* CSE sync in ramstage (aka Post-RAM) - Directly stored the CSE RW
  version into the CBMEM (as CBMEM is online).

BUG=b:285405031
TEST=Able to build and boot google/rex. Verified CSE RW FW version
(for LITE SKU) is getting displayed without impacting the boot time.

w/o this patch:
  10:start of ramstage                         722,257 (43)
  17:starting LZ4 decompress (ignore for x86)  723,777 (1,520)

w/ this patch:
  10:start of ramstage                         722,257 (43)
  17:starting LZ4 decompress (ignore for x86)  723,777 (1,520)

Change-Id: Ia873af512851a682cf1fac0e128d842562a316ab
Signed-off-by: Subrata Banik <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77174
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Rizwan Qureshi <rizwan.qureshi@intel.com>
This commit is contained in:
Subrata Banik 2023-08-13 13:03:50 +00:00
parent 5ba16d02b6
commit 65a6d1714d
4 changed files with 105 additions and 30 deletions

View File

@ -88,6 +88,7 @@
#define CBMEM_ID_AMD_STB 0x5f425453
#define CBMEM_ID_AMD_MP2 0x5f32504d
#define CBMEM_ID_CSE_PARTITION_VERSION 0x43535056
#define CBMEM_ID_CSE_INFO 0x4553435F
#define CBMEM_ID_TO_NAME_TABLE \
{ CBMEM_ID_ACPI, "ACPI " }, \
@ -168,5 +169,6 @@
{ CBMEM_ID_MEM_CHIP_INFO, "MEM CHIP INFO"},\
{ CBMEM_ID_AMD_STB, "AMD STB"},\
{ CBMEM_ID_AMD_MP2, "AMD MP2 BUFFER"},\
{ CBMEM_ID_CSE_PARTITION_VERSION, "CSE PARTITION VERSION"}
{ CBMEM_ID_CSE_PARTITION_VERSION, "CSE PARTITION VERSION"},\
{ CBMEM_ID_CSE_INFO, "CSE SPECIFIC INFORMATION"}
#endif /* _CBMEM_ID_H_ */

View File

@ -1420,15 +1420,15 @@ void cse_late_finalize(void)
static void intel_cse_get_rw_version(void)
{
struct cse_fw_partition_info *version = cbmem_find(CBMEM_ID_CSE_PARTITION_VERSION);
if (version == NULL)
struct cse_specific_info *info = cbmem_find(CBMEM_ID_CSE_INFO);
if (info == NULL)
return;
printk(BIOS_DEBUG, "CSE RW Firmware Version: %d.%d.%d.%d\n",
version->cur_cse_fw_version.major,
version->cur_cse_fw_version.minor,
version->cur_cse_fw_version.hotfix,
version->cur_cse_fw_version.build);
info->cse_fwp_version.cur_cse_fw_version.major,
info->cse_fwp_version.cur_cse_fw_version.minor,
info->cse_fwp_version.cur_cse_fw_version.hotfix,
info->cse_fwp_version.cur_cse_fw_version.build);
}
/*

View File

@ -6,6 +6,7 @@
#include <commonlib/region.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <crc_byte.h>
#include <fmap.h>
#include <intelbasecode/debug_feature.h>
#include <intelblocks/cse.h>
@ -134,6 +135,8 @@ struct get_bp_info_rsp {
static const char * const cse_regions[] = {"RO", "RW"};
static struct cse_specific_info cse_info;
void cse_log_ro_write_protection_info(bool mfg_mode)
{
bool cse_ro_wp_en = is_spi_wp_cse_ro_en();
@ -198,6 +201,88 @@ static const struct cse_bp_entry *cse_get_bp_entry(enum boot_partition_id bp,
return &cse_bp_info->bp_entries[bp];
}
static bool is_cbmem_cse_info_valid(const struct cse_specific_info *info)
{
uint32_t crc = ~CRC(info, offsetof(struct cse_specific_info, crc), crc32_byte);
/*
* Authenticate the CBMEM persistent data.
*
* The underlying assumption is that an event (i.e., CSE upgrade/downgrade) which
* could change the values stored in this region has to also trigger the global
* reset. Hence, CBMEM persistent data won't be available any time after such
* event (global reset or cold reset) being initiated.
*
* During warm boot scenarios CBMEM contents remain persistent hence, we don't
* want to override the existing data in CBMEM to avoid any additional boot latency.
*/
if (info->crc != crc)
return false;
return true;
}
static void cbmem_store_cse_info_crc(struct cse_specific_info *info)
{
info->crc = ~CRC(info, offsetof(struct cse_specific_info, crc), crc32_byte);
}
/*
* Helper function that stores current CSE firmware version to CBMEM memory,
* except during recovery mode.
*/
static void cse_store_rw_fw_version(const struct cse_bp_entry *cse_bp)
{
if (vboot_recovery_mode_enabled())
return;
if (CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_ROMSTAGE)) {
memcpy(&(cse_info.cse_fwp_version.cur_cse_fw_version), &(cse_bp->fw_ver),
sizeof(struct fw_version));
return;
}
struct cse_specific_info *info = cbmem_add(CBMEM_ID_CSE_INFO, sizeof(*info));
if (!info)
return;
/* Avoid CBMEM update if CBMEM already has persistent data */
if (is_cbmem_cse_info_valid(info))
return;
memset(info, 0, sizeof(*info));
memcpy(&(info->cse_fwp_version.cur_cse_fw_version), &(cse_bp->fw_ver),
sizeof(struct fw_version));
/* Update the CRC */
cbmem_store_cse_info_crc(info);
}
#if CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_ROMSTAGE)
/* Function to copy PRERAM CSE specific info to pertinent CBMEM. */
static void preram_cse_info_sync_to_cbmem(int is_recovery)
{
if (vboot_recovery_mode_enabled() || !CONFIG(SOC_INTEL_STORE_CSE_FW_VERSION))
return;
struct cse_specific_info *info = cbmem_add(CBMEM_ID_CSE_INFO, sizeof(*info));
if (!info)
return;
/* Avoid sync into CBMEM if CBMEM already has persistent data */
if (is_cbmem_cse_info_valid(info))
return;
memcpy(info, &cse_info, sizeof(struct cse_specific_info));
/* Update the CRC */
cbmem_store_cse_info_crc(info);
}
CBMEM_CREATION_HOOK(preram_cse_info_sync_to_cbmem);
#endif
static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info)
{
const struct cse_bp_entry *cse_bp;
@ -223,6 +308,10 @@ static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info)
cse_bp->fw_ver.hotfix, cse_bp->fw_ver.build,
cse_bp->status, cse_bp->start_offset,
cse_bp->end_offset);
/* Store the CSE RW Firmware Version into CBMEM */
if (CONFIG(SOC_INTEL_STORE_CSE_FW_VERSION))
cse_store_rw_fw_version(cse_bp);
}
/*
@ -1171,26 +1260,6 @@ void cse_fw_sync(void)
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 cse_store_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) != CB_SUCCESS) {
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)
{
@ -1303,9 +1372,6 @@ static void ramstage_cse_misc_ops(void *unused)
if (CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_RAMSTAGE))
cse_fw_sync();
/* Store the CSE RW Firmware Version into CBMEM */
if (CONFIG(SOC_INTEL_STORE_CSE_FW_VERSION))
cse_store_rw_fw_version();
/*
* Store the ISH RW Firmware Version into CBMEM if ISH partition
* is available

View File

@ -160,6 +160,13 @@ struct cse_fw_partition_info {
struct cse_fw_ish_version_info ish_partition_info;
};
/* CSE Specific Information */
struct cse_specific_info {
struct cse_fw_partition_info cse_fwp_version;
bool cse_downgrade_requested;
uint32_t crc;
};
/* CSE RX and TX error status */
enum cse_tx_rx_status {
/*