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:
@@ -88,6 +88,7 @@
|
|||||||
#define CBMEM_ID_AMD_STB 0x5f425453
|
#define CBMEM_ID_AMD_STB 0x5f425453
|
||||||
#define CBMEM_ID_AMD_MP2 0x5f32504d
|
#define CBMEM_ID_AMD_MP2 0x5f32504d
|
||||||
#define CBMEM_ID_CSE_PARTITION_VERSION 0x43535056
|
#define CBMEM_ID_CSE_PARTITION_VERSION 0x43535056
|
||||||
|
#define CBMEM_ID_CSE_INFO 0x4553435F
|
||||||
|
|
||||||
#define CBMEM_ID_TO_NAME_TABLE \
|
#define CBMEM_ID_TO_NAME_TABLE \
|
||||||
{ CBMEM_ID_ACPI, "ACPI " }, \
|
{ CBMEM_ID_ACPI, "ACPI " }, \
|
||||||
@@ -168,5 +169,6 @@
|
|||||||
{ CBMEM_ID_MEM_CHIP_INFO, "MEM CHIP INFO"},\
|
{ CBMEM_ID_MEM_CHIP_INFO, "MEM CHIP INFO"},\
|
||||||
{ CBMEM_ID_AMD_STB, "AMD STB"},\
|
{ CBMEM_ID_AMD_STB, "AMD STB"},\
|
||||||
{ CBMEM_ID_AMD_MP2, "AMD MP2 BUFFER"},\
|
{ 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_ */
|
#endif /* _CBMEM_ID_H_ */
|
||||||
|
@@ -1420,15 +1420,15 @@ void cse_late_finalize(void)
|
|||||||
|
|
||||||
static void intel_cse_get_rw_version(void)
|
static void intel_cse_get_rw_version(void)
|
||||||
{
|
{
|
||||||
struct cse_fw_partition_info *version = cbmem_find(CBMEM_ID_CSE_PARTITION_VERSION);
|
struct cse_specific_info *info = cbmem_find(CBMEM_ID_CSE_INFO);
|
||||||
if (version == NULL)
|
if (info == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "CSE RW Firmware Version: %d.%d.%d.%d\n",
|
printk(BIOS_DEBUG, "CSE RW Firmware Version: %d.%d.%d.%d\n",
|
||||||
version->cur_cse_fw_version.major,
|
info->cse_fwp_version.cur_cse_fw_version.major,
|
||||||
version->cur_cse_fw_version.minor,
|
info->cse_fwp_version.cur_cse_fw_version.minor,
|
||||||
version->cur_cse_fw_version.hotfix,
|
info->cse_fwp_version.cur_cse_fw_version.hotfix,
|
||||||
version->cur_cse_fw_version.build);
|
info->cse_fwp_version.cur_cse_fw_version.build);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include <commonlib/region.h>
|
#include <commonlib/region.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
|
#include <crc_byte.h>
|
||||||
#include <fmap.h>
|
#include <fmap.h>
|
||||||
#include <intelbasecode/debug_feature.h>
|
#include <intelbasecode/debug_feature.h>
|
||||||
#include <intelblocks/cse.h>
|
#include <intelblocks/cse.h>
|
||||||
@@ -134,6 +135,8 @@ struct get_bp_info_rsp {
|
|||||||
|
|
||||||
static const char * const cse_regions[] = {"RO", "RW"};
|
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)
|
void cse_log_ro_write_protection_info(bool mfg_mode)
|
||||||
{
|
{
|
||||||
bool cse_ro_wp_en = is_spi_wp_cse_ro_en();
|
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];
|
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)
|
static void cse_print_boot_partition_info(const struct cse_bp_info *cse_bp_info)
|
||||||
{
|
{
|
||||||
const struct cse_bp_entry *cse_bp;
|
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->fw_ver.hotfix, cse_bp->fw_ver.build,
|
||||||
cse_bp->status, cse_bp->start_offset,
|
cse_bp->status, cse_bp->start_offset,
|
||||||
cse_bp->end_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);
|
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,
|
static enum cb_err send_get_fpt_partition_info_cmd(enum fpt_partition_id id,
|
||||||
struct fw_version_resp *resp)
|
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))
|
if (CONFIG(SOC_INTEL_CSE_LITE_SYNC_IN_RAMSTAGE))
|
||||||
cse_fw_sync();
|
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
|
* Store the ISH RW Firmware Version into CBMEM if ISH partition
|
||||||
* is available
|
* is available
|
||||||
|
@@ -160,6 +160,13 @@ struct cse_fw_partition_info {
|
|||||||
struct cse_fw_ish_version_info ish_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 */
|
/* CSE RX and TX error status */
|
||||||
enum cse_tx_rx_status {
|
enum cse_tx_rx_status {
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user