diff options
-rw-r--r-- | src/arch/x86/lib/cbfs_and_run.c | 21 | ||||
-rw-r--r-- | src/cpu/intel/haswell/romstage.c | 2 | ||||
-rw-r--r-- | src/include/cbfs.h | 22 | ||||
-rw-r--r-- | src/include/cbmem.h | 5 | ||||
-rw-r--r-- | src/include/ramstage_loader.h | 34 | ||||
-rw-r--r-- | src/include/romstage_handoff.h | 10 | ||||
-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 | ||||
-rw-r--r-- | src/soc/intel/baytrail/romstage/romstage.c | 4 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/chromeos.h | 4 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot_loader.c | 87 |
14 files changed, 297 insertions, 134 deletions
diff --git a/src/arch/x86/lib/cbfs_and_run.c b/src/arch/x86/lib/cbfs_and_run.c index 3d56e19318..ca8d61be54 100644 --- a/src/arch/x86/lib/cbfs_and_run.c +++ b/src/arch/x86/lib/cbfs_and_run.c @@ -17,27 +17,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <console/console.h> -#include <cbfs.h> #include <arch/stages.h> -#include <timestamp.h> - -static void cbfs_and_run_core(const char *filename) -{ - u8 *dst; - - timestamp_add_now(TS_START_COPYRAM); - print_debug("Loading image.\n"); - dst = cbfs_load_stage(CBFS_DEFAULT_MEDIA, filename); - if ((void *)dst == (void *) -1) - die("FATAL: Essential component is missing.\n"); - - timestamp_add_now(TS_END_COPYRAM); - print_debug("Jumping to image.\n"); - stage_exit(dst); -} +#include <ramstage_loader.h> void asmlinkage copy_and_run(void) { - cbfs_and_run_core(CONFIG_CBFS_PREFIX "/coreboot_ram"); + run_ramstage(); } diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index 60a1c3a155..9e2766808d 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -309,8 +309,6 @@ void romstage_after_car(void) prepare_for_resume(handoff); - vboot_verify_firmware(handoff); - /* Load the ramstage. */ copy_and_run(); } diff --git a/src/include/cbfs.h b/src/include/cbfs.h index c05566d0b0..9ce862bbe5 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -83,6 +83,10 @@ void selfboot(void *entry); /* Defined in individual arch / board implementation. */ int init_default_cbfs_media(struct cbfs_media *media); +#if defined(__PRE_RAM__) +struct romstage_handoff; +struct cbmem_entry; + #if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__) /* The cache_loaded_ramstage() and load_cached_ramstage() functions are defined * to be weak so that board and chipset code may override them. Their job is to @@ -90,9 +94,6 @@ int init_default_cbfs_media(struct cbfs_media *media); * relocated ramstage is saved using the cbmem infrastructure. These * functions are only valid during romstage. */ -struct romstage_handoff; -struct cbmem_entry; - /* The implementer of cache_loaded_ramstage() may use the romstage_handoff * structure to store information, but note that the handoff variable can be * NULL. The ramstage cbmem_entry represents the region occupied by the loaded @@ -105,7 +106,22 @@ cache_loaded_ramstage(struct romstage_handoff *handoff, void * __attribute__((weak)) load_cached_ramstage(struct romstage_handoff *handoff, const struct cbmem_entry *ramstage); +#else /* CONFIG_RELOCATABLE_RAMSTAGE */ + +static inline void cache_loaded_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage, void *entry_point) +{ +} + +static inline void * +load_cached_ramstage(struct romstage_handoff *handoff, + const struct cbmem_entry *ramstage) +{ + return NULL; +} + #endif /* CONFIG_RELOCATABLE_RAMSTAGE */ +#endif /* defined(__PRE_RAM__) */ #endif diff --git a/src/include/cbmem.h b/src/include/cbmem.h index 9e68ba92f4..b47a847718 100644 --- a/src/include/cbmem.h +++ b/src/include/cbmem.h @@ -66,6 +66,7 @@ #define CBMEM_ID_HOB_POINTER 0x484f4221 #ifndef __ASSEMBLER__ +#include <stddef.h> #include <stdint.h> struct cbmem_entry; @@ -150,6 +151,10 @@ void cbmem_late_set_table(uint64_t base, uint64_t size); void get_cbmem_table(uint64_t *base, uint64_t *size); struct cbmem_entry *get_cbmem_toc(void); +static inline const struct cbmem_entry *cbmem_entry_find(uint32_t id) +{ + return NULL; +} #endif /* CONFIG_DYNAMIC_CBMEM */ /* Common API between cbmem and dynamic cbmem. */ diff --git a/src/include/ramstage_loader.h b/src/include/ramstage_loader.h new file mode 100644 index 0000000000..ad085c0ba5 --- /dev/null +++ b/src/include/ramstage_loader.h @@ -0,0 +1,34 @@ +/* + * 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 + */ +#ifndef RAMSTAGE_LOADER_H +#define RAMSTAGE_LOADER_H + +#include <stdint.h> +struct cbmem_entry; + +/* Run ramstage from romstage. */ +void run_ramstage(void); + +struct ramstage_loader_ops { + const char *name; + void *(*load)(uint32_t cbmem_id, const char *name, + const struct cbmem_entry **cbmem_entry); +}; + +#endif /* RAMSTAGE_LOADER_H */ diff --git a/src/include/romstage_handoff.h b/src/include/romstage_handoff.h index 699838a260..307babd329 100644 --- a/src/include/romstage_handoff.h +++ b/src/include/romstage_handoff.h @@ -41,6 +41,7 @@ struct romstage_handoff { }; #if defined(__PRE_RAM__) +#if CONFIG_EARLY_CBMEM_INIT /* The romstage_handoff_find_or_add() function provides the necessary logic * for initializing the romstage_handoff structure in cbmem. Different components * of the romstage may be responsible for setting up different fields. Therefore @@ -63,7 +64,14 @@ static inline struct romstage_handoff *romstage_handoff_find_or_add(void) return handoff; } -#endif +#else /* CONFIG_EARLY_CBMEM_INIT */ +static inline struct romstage_handoff *romstage_handoff_find_or_add(void) +{ + return NULL; +} +#endif /* CONFIG_EARLY_CBMEM_INIT */ + +#endif /* defined(__PRE_RAM__) */ #endif /* ROMSTAGE_HANDOFF_H */ 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"); +} diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c index 4d74b53e3e..3ab726df91 100644 --- a/src/soc/intel/baytrail/romstage/romstage.c +++ b/src/soc/intel/baytrail/romstage/romstage.c @@ -28,7 +28,6 @@ #include <ramstage_cache.h> #include <romstage_handoff.h> #include <timestamp.h> -#include <vendorcode/google/chromeos/chromeos.h> #include <baytrail/gpio.h> #include <baytrail/iomap.h> #include <baytrail/lpc.h> @@ -172,9 +171,6 @@ void asmlinkage romstage_after_car(void) timestamp_add_now(TS_END_ROMSTAGE); - /* Run vboot verification if configured. */ - vboot_verify_firmware(romstage_handoff_find_or_add()); - /* Load the ramstage. */ copy_and_run(); while (1); diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h index 5493801a09..0359c91409 100644 --- a/src/vendorcode/google/chromeos/chromeos.h +++ b/src/vendorcode/google/chromeos/chromeos.h @@ -46,14 +46,10 @@ int recovery_mode_enabled(void); /* functions implemented in vboot.c */ void init_chromeos(int bootmode); -struct romstage_handoff; #if CONFIG_VBOOT_VERIFY_FIRMWARE -void vboot_verify_firmware(struct romstage_handoff *handoff); void *vboot_get_payload(size_t *len); /* Returns 0 on success < 0 on error. */ int vboot_get_handoff_info(void **addr, uint32_t *size); -#else -static inline void vboot_verify_firmware(struct romstage_handoff *h) {} #endif #endif diff --git a/src/vendorcode/google/chromeos/vboot_loader.c b/src/vendorcode/google/chromeos/vboot_loader.c index cc7c25d873..0c5220a82b 100644 --- a/src/vendorcode/google/chromeos/vboot_loader.c +++ b/src/vendorcode/google/chromeos/vboot_loader.c @@ -26,6 +26,7 @@ #include <console/vtxprintf.h> #include <pc80/tpm.h> #include <reset.h> +#include <ramstage_loader.h> #include <romstage_handoff.h> #include <rmodule.h> #include <string.h> @@ -141,27 +142,52 @@ static void vboot_invoke_wrapper(struct vboot_handoff *vboot_handoff) vboot_run_stub(&context); } -static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff, - struct romstage_handoff *handoff) +static void *vboot_load_ramstage(uint32_t cbmem_id, const char *name, + const struct cbmem_entry **cbmem_entry) { + struct vboot_handoff *vboot_handoff; struct cbfs_stage *stage; const struct firmware_component *fwc; struct rmod_stage_load rmod_load = { - .cbmem_id = CBMEM_ID_RAMSTAGE, - .name = CONFIG_CBFS_PREFIX "/coreboot_ram", + .cbmem_id = cbmem_id, + .name = name, }; + timestamp_add_now(TS_START_VBOOT); + + vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, + sizeof(*vboot_handoff)); + + if (vboot_handoff == NULL) { + printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n"); + return NULL; + } + + memset(vboot_handoff, 0, sizeof(*vboot_handoff)); + + vboot_invoke_wrapper(vboot_handoff); + + timestamp_add_now(TS_END_VBOOT); + + /* Take RO firmware path since no RW area was selected. */ + if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A && + vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) { + printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n", + vboot_handoff->selected_firmware); + return NULL; + } + if (CONFIG_VBOOT_RAMSTAGE_INDEX >= MAX_PARSED_FW_COMPONENTS) { printk(BIOS_ERR, "Invalid ramstage index: %d\n", CONFIG_VBOOT_RAMSTAGE_INDEX); - return; + return NULL; } /* Check for invalid address. */ fwc = &vboot_handoff->components[CONFIG_VBOOT_RAMSTAGE_INDEX]; if (fwc->address == 0) { printk(BIOS_DEBUG, "RW ramstage image address invalid.\n"); - return; + return NULL; } printk(BIOS_DEBUG, "RW ramstage image at 0x%08x, 0x%08x bytes.\n", @@ -169,53 +195,18 @@ static void vboot_load_ramstage(struct vboot_handoff *vboot_handoff, stage = (void *)fwc->address; - timestamp_add_now(TS_START_COPYRAM); - if (rmodule_stage_load(&rmod_load, stage)) { vboot_handoff->selected_firmware = VB_SELECT_FIRMWARE_READONLY; printk(BIOS_DEBUG, "Could not load ramstage region.\n"); - return; + return NULL; } - cache_loaded_ramstage(handoff, rmod_load.cbmem_entry, rmod_load.entry); - - timestamp_add_now(TS_END_COPYRAM); + *cbmem_entry = rmod_load.cbmem_entry; - stage_exit(rmod_load.entry); + return rmod_load.entry; } -void vboot_verify_firmware(struct romstage_handoff *handoff) -{ - struct vboot_handoff *vboot_handoff; - - /* Don't go down verified boot path on S3 resume. */ - if (handoff != NULL && handoff->s3_resume) - return; - - timestamp_add_now(TS_START_VBOOT); - - vboot_handoff = cbmem_add(CBMEM_ID_VBOOT_HANDOFF, - sizeof(*vboot_handoff)); - - if (vboot_handoff == NULL) { - printk(BIOS_DEBUG, "Could not add vboot_handoff structure.\n"); - return; - } - - memset(vboot_handoff, 0, sizeof(*vboot_handoff)); - - vboot_invoke_wrapper(vboot_handoff); - - timestamp_add_now(TS_END_VBOOT); - - /* Take RO firmware path since no RW area was selected. */ - if (vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_A && - vboot_handoff->selected_firmware != VB_SELECT_FIRMWARE_B) { - printk(BIOS_DEBUG, "No RW firmware selected: 0x%08x\n", - vboot_handoff->selected_firmware); - return; - } - - /* Load ramstage from the vboot_handoff structure. */ - vboot_load_ramstage(vboot_handoff, handoff); -} +const struct ramstage_loader_ops vboot_ramstage_loader = { + .name = "VBOOT", + .load = vboot_load_ramstage, +}; |