diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Makefile.inc | 1 | ||||
-rw-r--r-- | src/lib/cbfs.c | 53 | ||||
-rw-r--r-- | src/lib/loaders/Makefile.inc | 21 | ||||
-rw-r--r-- | src/lib/loaders/cbfs_ramstage_loader.c | 67 | ||||
-rw-r--r-- | src/lib/loaders/load_and_run_ramstage.c | 100 |
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"); +} |