[coreboot] New patch to review for coreboot: 65cb69c haswell: implement ramstage caching in SMM region

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Tue Mar 19 01:59:21 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2806

-gerrit

commit 65cb69c95de57f0d79512c777ed9ff1ba6e2f267
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Sat Feb 16 00:05:52 2013 -0600

    haswell: implement ramstage caching in SMM region
    
    Cache the relocated ramstage into the SMM region. There is
    a reserved region within the final SMM region (TSEG). Use that
    space to cache the relocated ramstage program. That way, on S3 resume
    there is a copy that can be loaded quickly instead of accessing the
    flash. Caching the ramstage in the SMM space is also helpful in that
    it prevents the OS from tampering with the ramstage program.
    
    Change-Id: Ifa695ad1c350d5b504b14cc29d3e83c79b317a62
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/cpu/intel/haswell/haswell.h  | 17 +++++++++++
 src/cpu/intel/haswell/romstage.c | 65 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h
index 3a5ebe6..a1c6f39 100644
--- a/src/cpu/intel/haswell/haswell.h
+++ b/src/cpu/intel/haswell/haswell.h
@@ -174,6 +174,23 @@ int setup_ap_init(struct bus *cpu_bus, int *max_cpus,
 int start_aps(struct bus *cpu_bus, int max_cpus);
 void release_aps_for_smm_relocation(int do_parallel_relocation);
 #endif
+
+/* This structure is saved along with the relocated ramstage program in SMM
+ * space. It is used to protect the integrity of the ramstage program on S3
+ * resume by saving a copy of the relocated ramstage in SMM space with the
+ * assumption that the SMM region cannot be altered from the OS. The magic
+ * value just serves as a quick sanity check. */
+
+#define RAMSTAGE_CACHE_MAGIC 0xf3c3a02a
+
+struct ramstage_cache {
+	uint32_t magic;
+	uint32_t entry_point;
+	uint32_t load_address;
+	uint32_t size;
+	char program[0];
+} __attribute__((packed));
+
 #endif
 
 #endif
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index b26cbde..d491c7e 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -34,6 +34,7 @@
 #include <device/pci_def.h>
 #include <cpu/x86/lapic.h>
 #include <cbmem.h>
+#include <cbfs.h>
 #include <romstage_handoff.h>
 #if CONFIG_CHROMEOS
 #include <vendorcode/google/chromeos/chromeos.h>
@@ -320,3 +321,67 @@ void romstage_after_car(void)
 	/* Load the ramstage. */
 	copy_and_run(0);
 }
+
+
+#if CONFIG_RELOCATABLE_RAMSTAGE
+void cache_loaded_ramstage(struct romstage_handoff *handoff,
+                           void *ramstage_base, uint32_t ramstage_size,
+                           void *entry_point)
+{
+	struct ramstage_cache *cache;
+	uint32_t total_size;
+
+	/* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
+	 * The top of ram is defined to be the TSEG base address. */
+	cache = (void *)(get_top_of_ram() + RESERVED_SMM_OFFSET);
+	total_size = sizeof(*cache) + ramstage_size;
+	if (total_size > RESERVED_SMM_SIZE) {
+		printk(BIOS_DEBUG, "0x%08x > RESERVED_SMM_SIZE (0x%08x)\n",
+		       total_size, RESERVED_SMM_SIZE);
+		/* Nuke whatever may be there now just in case. */
+		cache->magic = ~RAMSTAGE_CACHE_MAGIC;
+		return;
+	}
+
+	cache->magic = RAMSTAGE_CACHE_MAGIC;
+	cache->entry_point = (uint32_t)entry_point;
+	cache->load_address = (uint32_t)ramstage_base;
+	cache->size = ramstage_size;
+
+	printk(BIOS_DEBUG, "Saving ramstage to SMM space cache.\n");
+
+	/* Copy over the program. */
+	memcpy(&cache->program[0], ramstage_base, ramstage_size);
+
+	/* Do not update reserve region if the handoff structure is not
+	 * available. Perhaps the ramstage will fix things up for the resume
+	 * path. */
+	if (handoff == NULL)
+		return;
+
+	/* Update entry and reserve region. */
+	handoff->reserve_base = (uint32_t)ramstage_base;
+	handoff->reserve_size = ramstage_size;
+	handoff->ramstage_entry_point = (uint32_t)entry_point;
+}
+
+void *load_cached_ramstage(struct romstage_handoff *handoff)
+{
+	struct ramstage_cache *cache;
+
+	/* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
+	 * The top of ram is defined to be the TSEG base address. */
+	cache = (void *)(get_top_of_ram() + RESERVED_SMM_OFFSET);
+
+	if (cache->magic != RAMSTAGE_CACHE_MAGIC) {
+		printk(BIOS_DEBUG, "Invalid ramstage cache found.\n");
+		return NULL;
+	}
+
+	printk(BIOS_DEBUG, "Loading ramstage from SMM space cache.\n");
+
+	memcpy((void *)cache->load_address, &cache->program[0], cache->size);
+
+	return (void *)cache->entry_point;
+}
+#endif



More information about the coreboot mailing list