summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2014-01-30 17:19:46 -0600
committerAaron Durbin <adurbin@google.com>2014-02-15 18:39:29 +0100
commit0f333071ef9151b89de3fcf6dc5c14dba596941a (patch)
tree7a250a88218d16dd9baf7d5b1d9a35baa08c3390 /src/lib
parente9aaa71fb1e05c4432d768d87071ef842c536cb4 (diff)
coreboot: infrastructure for different ramstage loaders
There are 2 methods currently available in coreboot to load ramstage from romstage: cbfs and vboot. The vboot path had to be explicitly enabled and code needed to be added to each chipset to support both. Additionally, many of the paths were duplicated between the two. An additional complication is the presence of having a relocatable ramstage which creates another path with duplication. To rectify this situation provide a common API through the use of a callback to load the ramstage. The rest of the existing logic to handle all the various cases is put in a common place. Change-Id: I5268ce70686cc0d121161a775c3a86ea38a4d8ae Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5087 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.inc1
-rw-r--r--src/lib/cbfs.c53
-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
5 files changed, 189 insertions, 53 deletions
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 79ceebf44b..5c37329b5c 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -16,6 +16,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
+subdirs-y += loaders
bootblock-y += cbfs.c
ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y)
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 9fe1757a65..f2a2587669 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -123,58 +123,6 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
return dest;
}
-#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__)
-
-#include <rmodule.h>
-#include <romstage_handoff.h>
-static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name,
- struct romstage_handoff *handoff)
-{
- struct rmod_stage_load rmod_ram = {
- .cbmem_id = CBMEM_ID_RAMSTAGE,
- .name = name,
- };
-
- if (rmodule_stage_load_from_cbfs(&rmod_ram)) {
- printk(BIOS_DEBUG, "Could not load ramstage.\n");
- return (void *) -1;
- }
-
- cache_loaded_ramstage(handoff, rmod_ram.cbmem_entry, rmod_ram.entry);
-
- return rmod_ram.entry;
-}
-
-void * cbfs_load_stage(struct cbfs_media *media, const char *name)
-{
- struct romstage_handoff *handoff;
- const struct cbmem_entry *ramstage;
- void *entry;
-
- handoff = romstage_handoff_find_or_add();
-
- if (handoff == NULL) {
- LOG("Couldn't find or allocate romstage handoff.\n");
- return load_stage_from_cbfs(media, name, handoff);
- } else if (!handoff->s3_resume)
- return load_stage_from_cbfs(media, name, handoff);
-
- ramstage = cbmem_entry_find(CBMEM_ID_RAMSTAGE);
-
- if (ramstage == NULL)
- return load_stage_from_cbfs(media, name, handoff);
-
- /* S3 resume path. Load a cached copy of the loaded ramstage. If
- * return value is NULL load from cbfs. */
- entry = load_cached_ramstage(handoff, ramstage);
- if (entry == NULL)
- return load_stage_from_cbfs(media, name, handoff);
-
- return entry;
-}
-
-#else
-
void * cbfs_load_stage(struct cbfs_media *media, const char *name)
{
struct cbfs_stage *stage = (struct cbfs_stage *)
@@ -211,7 +159,6 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
return (void *) entry;
}
-#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
#if !CONFIG_ALT_CBFS_LOAD_PAYLOAD
void *cbfs_load_payload(struct cbfs_media *media, const char *name)
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");
+}