aboutsummaryrefslogtreecommitdiff
path: root/src/lib/loaders
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/loaders')
-rw-r--r--src/lib/loaders/Makefile.inc21
-rw-r--r--src/lib/loaders/cbfs_ramstage_loader.c67
-rw-r--r--src/lib/loaders/load_and_run_ramstage.c100
3 files changed, 188 insertions, 0 deletions
diff --git a/src/lib/loaders/Makefile.inc b/src/lib/loaders/Makefile.inc
new file mode 100644
index 0000000000..eceaa00c44
--- /dev/null
+++ b/src/lib/loaders/Makefile.inc
@@ -0,0 +1,21 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2014 Google Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+romstage-y += cbfs_ramstage_loader.c
+romstage-y += load_and_run_ramstage.c
diff --git a/src/lib/loaders/cbfs_ramstage_loader.c b/src/lib/loaders/cbfs_ramstage_loader.c
new file mode 100644
index 0000000000..5d5cc0b0ec
--- /dev/null
+++ b/src/lib/loaders/cbfs_ramstage_loader.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <console/console.h>
+#include <cbfs.h>
+#include <arch/stages.h>
+#include <ramstage_loader.h>
+#include <timestamp.h>
+
+#if CONFIG_RELOCATABLE_RAMSTAGE
+#include <rmodule.h>
+
+static void *cbfs_load_ramstage(uint32_t cbmem_id, const char *name,
+ const struct cbmem_entry **cbmem_entry)
+{
+ struct rmod_stage_load rmod_ram = {
+ .cbmem_id = cbmem_id,
+ .name = name,
+ };
+
+ if (rmodule_stage_load_from_cbfs(&rmod_ram)) {
+ printk(BIOS_DEBUG, "Could not load ramstage.\n");
+ return NULL;
+ }
+
+ *cbmem_entry = rmod_ram.cbmem_entry;
+
+ return rmod_ram.entry;
+}
+
+#else /* CONFIG_RELOCATABLE_RAMSTAGE */
+
+static void *cbfs_load_ramstage(uint32_t cbmem_id, const char *name,
+ const struct cbmem_entry **cbmem_entry)
+{
+ void *entry;
+
+ entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, name);
+
+ if ((void *)entry == (void *) -1)
+ entry = NULL;
+
+ return entry;
+}
+
+#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
+
+const struct ramstage_loader_ops cbfs_ramstage_loader = {
+ .name = "CBFS",
+ .load = cbfs_load_ramstage,
+};
diff --git a/src/lib/loaders/load_and_run_ramstage.c b/src/lib/loaders/load_and_run_ramstage.c
new file mode 100644
index 0000000000..be2be8219c
--- /dev/null
+++ b/src/lib/loaders/load_and_run_ramstage.c
@@ -0,0 +1,100 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <console/console.h>
+#include <arch/stages.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <ramstage_loader.h>
+#include <romstage_handoff.h>
+#include <timestamp.h>
+
+extern const struct ramstage_loader_ops cbfs_ramstage_loader;
+extern const struct ramstage_loader_ops vboot_ramstage_loader;
+
+static const struct ramstage_loader_ops *loaders[] = {
+#if CONFIG_VBOOT_VERIFY_FIRMWARE
+ &vboot_ramstage_loader,
+#endif
+ &cbfs_ramstage_loader,
+};
+
+static const char *ramstage_name = CONFIG_CBFS_PREFIX "/coreboot_ram";
+static const uint32_t ramstage_id = CBMEM_ID_RAMSTAGE;
+
+static void
+load_ramstage(const struct ramstage_loader_ops *ops, struct romstage_handoff *handoff)
+{
+ const struct cbmem_entry *cbmem_entry;
+ void *entry_point;
+
+ timestamp_add_now(TS_START_COPYRAM);
+ entry_point = ops->load(ramstage_id, ramstage_name, &cbmem_entry);
+
+ if (entry_point == NULL)
+ return;
+
+ cache_loaded_ramstage(handoff, cbmem_entry, entry_point);
+
+ timestamp_add_now(TS_END_COPYRAM);
+
+ stage_exit(entry_point);
+}
+
+static void run_ramstage_from_resume(struct romstage_handoff *handoff)
+{
+ void *entry;
+ const struct cbmem_entry *cbmem_entry;
+
+ if (handoff != NULL && handoff->s3_resume) {
+ cbmem_entry = cbmem_entry_find(ramstage_id);
+
+ /* No place to load ramstage. */
+ if (cbmem_entry == NULL)
+ return;
+
+ /* Load the cached ramstage to runtime location. */
+ entry = load_cached_ramstage(handoff, cbmem_entry);
+
+ if (entry != NULL) {
+ print_debug("Jumping to image.\n");
+ stage_exit(entry);
+ }
+ }
+}
+
+void run_ramstage(void)
+{
+ struct romstage_handoff *handoff;
+ const struct ramstage_loader_ops *ops;
+ int i;
+
+ handoff = romstage_handoff_find_or_add();
+
+ run_ramstage_from_resume(handoff);
+
+ for (i = 0; i < ARRAY_SIZE(loaders); i++) {
+ ops = loaders[i];
+ printk(BIOS_DEBUG, "Trying %s ramstage loader.\n", ops->name);
+ load_ramstage(ops, handoff);
+ }
+
+ die("Ramstage was not loaded!\n");
+}