summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2013-12-12 10:29:48 -0800
committerKyösti Mälkki <kyosti.malkki@gmail.com>2014-05-10 06:31:59 +0200
commit63fcb4a1f89f1b74f834249b1bc683da280221fa (patch)
tree76b0dc41d9473bb67e6fe6fd111c0bca7793044d /src/soc
parentce727e18f0992126b7a27b8a51b426834e804390 (diff)
downloadcoreboot-63fcb4a1f89f1b74f834249b1bc683da280221fa.tar.xz
baytrail: cache reference code for S3 resume
In order to use the same reference code on S3 resume that was booted the program needs to be cached. Piggy back on the ramstage cache to save the loaded reference code program. BUG=chrome-os-partner:22867 BRANCH=None TEST=Built and booted. S3 resumed. Noted locations of reference code caching and load addresses in console. Change-Id: I90ceaf5697e8c269c3244370519d4d8a8ee2eb4a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/179777 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/5013 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/baytrail/refcode.c109
1 files changed, 101 insertions, 8 deletions
diff --git a/src/soc/intel/baytrail/refcode.c b/src/soc/intel/baytrail/refcode.c
index 9b5aa6790e..f746358faf 100644
--- a/src/soc/intel/baytrail/refcode.c
+++ b/src/soc/intel/baytrail/refcode.c
@@ -17,19 +17,113 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <string.h>
+#include <arch/acpi.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/tsc.h>
#include <rmodule.h>
+#include <ramstage_cache.h>
#include <baytrail/ramstage.h>
#include <baytrail/efi_wrapper.h>
+static inline int is_s3_resume(void)
+{
+#if CONFIG_HAVE_ACPI_RESUME
+ return acpi_slp_type == 3;
+#else
+ return 0;
+#endif
+}
+
+static inline struct ramstage_cache *next_cache(struct ramstage_cache *c)
+{
+ return (struct ramstage_cache *)&c->program[c->size];
+}
+
static void ABI_X86 send_to_console(unsigned char b)
{
console_tx_byte(b);
}
+static efi_wrapper_entry_t load_refcode_from_cache(void)
+{
+ struct ramstage_cache *c;
+ long cache_size;
+
+ printk(BIOS_DEBUG, "refcode loading from cache.\n");
+
+ c = ramstage_cache_location(&cache_size);
+
+ if (!ramstage_cache_is_valid(c)) {
+ printk(BIOS_DEBUG, "Invalid ramstage cache descriptor.\n");
+ return NULL;
+ }
+
+ c = next_cache(c);
+ if (!ramstage_cache_is_valid(c)) {
+ printk(BIOS_DEBUG, "Invalid refcode cache descriptor.\n");
+ return NULL;
+ }
+
+ printk(BIOS_DEBUG, "Loading cached reference code from 0x%08x(%x)\n",
+ c->load_address, c->size);
+ memcpy((void *)c->load_address, &c->program[0], c->size);
+
+ return (efi_wrapper_entry_t)c->entry_point;
+}
+
+static void cache_refcode(const struct rmod_stage_load *rsl)
+{
+ struct ramstage_cache *c;
+ long cache_size;
+
+ c = ramstage_cache_location(&cache_size);
+
+ if (!ramstage_cache_is_valid(c)) {
+ printk(BIOS_DEBUG, "No place to cache reference code.\n");
+ return;
+ }
+
+ /* Determine how much remaining cache available. */
+ cache_size -= c->size + sizeof(*c);
+
+ if (cache_size < (sizeof(*c) + cbmem_entry_size(rsl->cbmem_entry))) {
+ printk(BIOS_DEBUG, "Not enough cache space for ref code.\n");
+ return;
+ }
+
+ c = next_cache(c);
+ c->magic = RAMSTAGE_CACHE_MAGIC;
+ c->entry_point = (uint32_t)rsl->entry;
+ c->load_address = (uint32_t)cbmem_entry_start(rsl->cbmem_entry);
+ c->size = cbmem_entry_size(rsl->cbmem_entry);;
+
+ printk(BIOS_DEBUG, "Caching refcode at 0x%p(%x)\n",
+ &c->program[0], c->size);
+ memcpy(&c->program[0], (void *)c->load_address, c->size);
+}
+
+static efi_wrapper_entry_t load_refcode_from_cbfs(void)
+{
+ struct rmod_stage_load refcode = {
+ .cbmem_id = CBMEM_ID_REFCODE,
+ .name = CONFIG_CBFS_PREFIX "/refcode",
+ };
+
+ printk(BIOS_DEBUG, "refcode loading from cbfs.\n");
+
+ if (rmodule_stage_load_from_cbfs(&refcode) || refcode.entry == NULL) {
+ printk(BIOS_DEBUG, "Error loading reference code.\n");
+ return NULL;
+ }
+
+ cache_refcode(&refcode);
+
+ return refcode.entry;
+}
+
void baytrail_run_reference_code(void)
{
int ret;
@@ -38,18 +132,17 @@ void baytrail_run_reference_code(void)
.version = EFI_WRAPPER_VER,
.console_out = send_to_console,
};
- struct rmod_stage_load refcode = {
- .cbmem_id = CBMEM_ID_REFCODE,
- .name = CONFIG_CBFS_PREFIX "/refcode",
- };
- if (rmodule_stage_load_from_cbfs(&refcode) || refcode.entry == NULL) {
- printk(BIOS_DEBUG, "Error loading reference code.\n");
- return;
+ if (is_s3_resume()) {
+ entry = load_refcode_from_cache();
+ } else {
+ entry = load_refcode_from_cbfs();
}
+ if (entry == NULL)
+ return;
+
wrp.tsc_ticks_per_microsecond = tsc_freq_mhz();
- entry = refcode.entry;
/* Call into reference code. */
ret = entry(&wrp);