summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/intel/fsp1_1/romstage.c48
-rw-r--r--src/drivers/intel/fsp2_0/memory_init.c13
-rw-r--r--src/drivers/mrc_cache/mrc_cache.c106
3 files changed, 107 insertions, 60 deletions
diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c
index 46df1c8697..5a59c502a9 100644
--- a/src/drivers/intel/fsp1_1/romstage.c
+++ b/src/drivers/intel/fsp1_1/romstage.c
@@ -23,7 +23,7 @@
static void raminit_common(struct romstage_params *params)
{
bool s3wake;
- struct region_device rdev;
+ size_t mrc_size;
post_code(0x32);
@@ -45,24 +45,31 @@ static void raminit_common(struct romstage_params *params)
/* Recovery mode does not use MRC cache */
printk(BIOS_DEBUG,
"Recovery mode: not using MRC cache.\n");
- } else if (CONFIG(CACHE_MRC_SETTINGS)
- && (!mrc_cache_get_current(MRC_TRAINING_DATA,
- params->fsp_version,
- &rdev))) {
- /* MRC cache found */
- params->saved_data_size = region_device_sz(&rdev);
- params->saved_data = rdev_mmap_full(&rdev);
+ } else {
/* Assume boot device is memory mapped. */
assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
- } else if (s3wake) {
- /* Waking from S3 and no cache. */
- printk(BIOS_DEBUG,
- "No MRC cache found in S3 resume path.\n");
- post_code(POST_RESUME_FAILURE);
- /* FIXME: A "system" reset is likely enough: */
- full_reset();
- } else {
- printk(BIOS_DEBUG, "No MRC cache found.\n");
+
+ params->saved_data = NULL;
+ if (CONFIG(CACHE_MRC_SETTINGS))
+ params->saved_data =
+ mrc_cache_current_mmap_leak(MRC_TRAINING_DATA,
+ params->fsp_version,
+ &mrc_size);
+ if (params->saved_data) {
+ /* MRC cache found */
+ params->saved_data_size = mrc_size;
+
+ } else if (s3wake) {
+ /* Waking from S3 and no cache. */
+ printk(BIOS_DEBUG,
+ "No MRC cache "
+ "found in S3 resume path.\n");
+ post_code(POST_RESUME_FAILURE);
+ /* FIXME: A "system" reset is likely enough: */
+ full_reset();
+ } else {
+ printk(BIOS_DEBUG, "No MRC cache found.\n");
+ }
}
}
@@ -283,13 +290,6 @@ __weak void mainboard_add_dimm_info(
{
}
-/* Get the memory configuration data */
-__weak int mrc_cache_get_current(int type, uint32_t version,
- struct region_device *rdev)
-{
- return -1;
-}
-
/* Save the memory configuration data */
__weak int mrc_cache_stash_data(int type, uint32_t version,
const void *data, size_t size)
diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c
index 57a052037e..07c4463e56 100644
--- a/src/drivers/intel/fsp2_0/memory_init.c
+++ b/src/drivers/intel/fsp2_0/memory_init.c
@@ -93,8 +93,8 @@ static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)
static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t fsp_version)
{
- struct region_device rdev;
void *data;
+ size_t mrc_size;
arch_upd->NvsBufferPtr = NULL;
@@ -113,25 +113,22 @@ static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t fsp_version)
return;
}
- if (mrc_cache_get_current(MRC_TRAINING_DATA, fsp_version, &rdev) < 0)
- return;
-
/* Assume boot device is memory mapped. */
assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
- data = rdev_mmap_full(&rdev);
+ data = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, fsp_version,
+ &mrc_size);
if (data == NULL)
return;
if (CONFIG(FSP2_0_USES_TPM_MRC_HASH) &&
- !mrc_cache_verify_hash(data, region_device_sz(&rdev)))
+ !mrc_cache_verify_hash(data, mrc_size))
return;
/* MRC cache found */
arch_upd->NvsBufferPtr = data;
- printk(BIOS_SPEW, "MRC cache found, size %zx\n",
- region_device_sz(&rdev));
+ printk(BIOS_SPEW, "MRC cache found, size %zx\n", mrc_size);
}
static enum cb_err check_region_overlap(const struct memranges *ranges,
diff --git a/src/drivers/mrc_cache/mrc_cache.c b/src/drivers/mrc_cache/mrc_cache.c
index d567a20f11..1b1ad6332f 100644
--- a/src/drivers/mrc_cache/mrc_cache.c
+++ b/src/drivers/mrc_cache/mrc_cache.c
@@ -204,23 +204,16 @@ static int mrc_header_valid(struct region_device *rdev, struct mrc_metadata *md)
return 0;
}
-static int mrc_data_valid(const struct region_device *rdev,
- const struct mrc_metadata *md)
+static int mrc_data_valid(const struct mrc_metadata *md,
+ void *data, size_t data_size)
{
- void *data;
uint16_t checksum;
- const size_t md_size = sizeof(*md);
- const size_t data_size = md->data_size;
- data = rdev_mmap(rdev, md_size, data_size);
- if (data == NULL) {
- printk(BIOS_ERR, "MRC: mmap failure on data verification.\n");
+ if (md->data_size != data_size)
return -1;
- }
checksum = compute_ip_checksum(data, data_size);
- rdev_munmap(rdev, data);
if (md->data_checksum != checksum) {
printk(BIOS_ERR, "MRC: data checksum mismatch: %x vs %x\n",
md->data_checksum, checksum);
@@ -230,7 +223,7 @@ static int mrc_data_valid(const struct region_device *rdev,
return 0;
}
-static int mrc_cache_latest(const char *name,
+static int mrc_cache_get_latest_slot_info(const char *name,
const struct region_device *backing_rdev,
struct mrc_metadata *md,
struct region_file *cache_file,
@@ -260,25 +253,19 @@ static int mrc_cache_latest(const char *name,
return fail_bad_data ? -1 : 0;
}
- /* Validate Data */
- if (mrc_data_valid(rdev, md) < 0) {
- printk(BIOS_ERR, "MRC: invalid data in '%s'\n", name);
- return fail_bad_data ? -1 : 0;
- }
-
return 0;
}
-int mrc_cache_get_current(int type, uint32_t version,
- struct region_device *rdev)
+static int mrc_cache_find_current(int type, uint32_t version,
+ struct region_device *rdev,
+ struct mrc_metadata *md)
{
const struct cache_region *cr;
struct region region;
struct region_device read_rdev;
struct region_file cache_file;
- struct mrc_metadata md;
size_t data_size;
- const size_t md_size = sizeof(md);
+ const size_t md_size = sizeof(*md);
const bool fail_bad_data = true;
cr = lookup_region(&region, type);
@@ -289,21 +276,75 @@ int mrc_cache_get_current(int type, uint32_t version,
if (boot_device_ro_subregion(&region, &read_rdev) < 0)
return -1;
- if (mrc_cache_latest(cr->name, &read_rdev, &md, &cache_file, rdev,
- fail_bad_data) < 0)
+ if (mrc_cache_get_latest_slot_info(cr->name,
+ &read_rdev,
+ md,
+ &cache_file,
+ rdev,
+ fail_bad_data) < 0)
return -1;
- if (version != md.version) {
+ if (version != md->version) {
printk(BIOS_INFO, "MRC: version mismatch: %x vs %x\n",
- md.version, version);
+ md->version, version);
return -1;
}
/* Re-size rdev to only contain the data. i.e. remove metadata. */
- data_size = md.data_size;
+ data_size = md->data_size;
return rdev_chain(rdev, rdev, md_size, data_size);
}
+int mrc_cache_load_current(int type, uint32_t version, void *buffer,
+ size_t buffer_size)
+{
+ struct region_device rdev;
+ struct mrc_metadata md;
+ size_t data_size;
+
+ if (mrc_cache_find_current(type, version, &rdev, &md) < 0)
+ return -1;
+
+ data_size = region_device_sz(&rdev);
+ if (buffer_size < data_size)
+ return -1;
+
+ if (rdev_readat(&rdev, buffer, 0, data_size) != data_size)
+ return -1;
+
+ if (mrc_data_valid(&md, buffer, data_size) < 0)
+ return -1;
+
+ return 0;
+}
+
+void *mrc_cache_current_mmap_leak(int type, uint32_t version,
+ size_t *data_size)
+{
+ struct region_device rdev;
+ void *data;
+ size_t region_device_size;
+ struct mrc_metadata md;
+
+ if (mrc_cache_find_current(type, version, &rdev, &md) < 0)
+ return NULL;
+
+ region_device_size = region_device_sz(&rdev);
+ if (data_size)
+ *data_size = region_device_size;
+ data = rdev_mmap_full(&rdev);
+
+ if (data == NULL) {
+ printk(BIOS_INFO, "MRC: mmap failure.\n");
+ return NULL;
+ }
+
+ if (mrc_data_valid(&md, data, region_device_size) < 0)
+ return NULL;
+
+ return data;
+}
+
static bool mrc_cache_needs_update(const struct region_device *rdev,
const struct cbmem_entry *to_be_updated)
{
@@ -392,8 +433,17 @@ static void update_mrc_cache_by_type(int type)
if (backing_rdev == NULL)
return;
- if (mrc_cache_latest(cr->name, backing_rdev, &md, &cache_file,
- &latest_rdev, fail_bad_data) < 0)
+ /* Note that mrc_cache_get_latest_slot_info doesn't check the
+ * validity of the current slot. If the slot is invalid,
+ * we'll overwrite it anyway when we update the mrc_cache.
+ */
+ if (mrc_cache_get_latest_slot_info(cr->name,
+ backing_rdev,
+ &md,
+ &cache_file,
+ &latest_rdev,
+ fail_bad_data) < 0)
+
return;
if (!mrc_cache_needs_update(&latest_rdev, to_be_updated)) {