diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/program_loading.h | 7 | ||||
-rw-r--r-- | src/include/symbols.h | 1 | ||||
-rw-r--r-- | src/lib/Kconfig | 11 | ||||
-rw-r--r-- | src/lib/prog_loaders.c | 58 |
4 files changed, 71 insertions, 6 deletions
diff --git a/src/include/program_loading.h b/src/include/program_loading.h index 65a36b9b2a..5b9a94df06 100644 --- a/src/include/program_loading.h +++ b/src/include/program_loading.h @@ -154,6 +154,13 @@ void run_ramstage(void); int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size); +/* + * Asynchronously preloads the payload. + * + * This should be called early on to allow the payload to load before + * `payload_load` is called. + */ +void payload_preload(void); /* Load payload into memory in preparation to run. */ void payload_load(void); diff --git a/src/include/symbols.h b/src/include/symbols.h index 3e4694b90d..52624d4e4c 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -52,6 +52,7 @@ DECLARE_REGION(asan_shadow) /* Regions for execution units. */ +DECLARE_REGION(payload_preload_cache) DECLARE_REGION(payload) /* "program" always refers to the current execution unit. */ DECLARE_REGION(program) diff --git a/src/lib/Kconfig b/src/lib/Kconfig index 239f613470..0f651b346a 100644 --- a/src/lib/Kconfig +++ b/src/lib/Kconfig @@ -98,3 +98,14 @@ config NO_CBFS_MCACHE the associated CAR/SRAM size. In that case every single CBFS file lookup must re-read the same CBFS directory entries from flash to find the respective file. + +config PAYLOAD_PRELOAD + bool + depends on COOP_MULTITASKING + help + On some systems with SPI DMA controllers, it is possible to preload + the payload while ramstage is executing. This can be selected by the + SoC to enable payload preloading. + + The SoC needs to define a payload_preload_cache region where the + raw payload can be placed. diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c index 40f51ebf48..1a361ea3b9 100644 --- a/src/lib/prog_loaders.c +++ b/src/lib/prog_loaders.c @@ -13,6 +13,7 @@ #include <rmodule.h> #include <stage_cache.h> #include <symbols.h> +#include <thread.h> #include <timestamp.h> #include <security/vboot/vboot_common.h> @@ -126,27 +127,71 @@ fail: static struct prog global_payload = PROG_INIT(PROG_PAYLOAD, CONFIG_CBFS_PREFIX "/payload"); +static struct thread_handle payload_preload_handle; + +static enum cb_err payload_preload_thread_entry(void *arg) +{ + size_t size; + struct prog *payload = &global_payload; + + printk(BIOS_DEBUG, "Preloading payload\n"); + + payload->cbfs_type = CBFS_TYPE_QUERY; + + size = cbfs_type_load(prog_name(payload), _payload_preload_cache, + REGION_SIZE(payload_preload_cache), &payload->cbfs_type); + + if (!size) { + printk(BIOS_ERR, "ERROR: Preloading payload failed\n"); + return CB_ERR; + } + + printk(BIOS_DEBUG, "Preloading payload complete\n"); + + return CB_SUCCESS; +} + +void payload_preload(void) +{ + struct thread_handle *handle = &payload_preload_handle; + + if (!CONFIG(PAYLOAD_PRELOAD)) + return; + + if (thread_run(handle, payload_preload_thread_entry, NULL)) + printk(BIOS_ERR, "ERROR: Failed to start payload preload thread\n"); +} + void payload_load(void) { struct prog *payload = &global_payload; + struct thread_handle *handle = &payload_preload_handle; + void *mapping = NULL; + void *buffer; timestamp_add_now(TS_LOAD_PAYLOAD); if (prog_locate_hook(payload)) goto out; - payload->cbfs_type = CBFS_TYPE_QUERY; - void *mapping = cbfs_type_map(prog_name(payload), NULL, &payload->cbfs_type); - if (!mapping) + if (CONFIG(PAYLOAD_PRELOAD) && thread_join(handle) == CB_SUCCESS) { + buffer = _payload_preload_cache; + } else { + payload->cbfs_type = CBFS_TYPE_QUERY; + mapping = cbfs_type_map(prog_name(payload), NULL, &payload->cbfs_type); + buffer = mapping; + } + + if (!buffer) goto out; switch (prog_cbfs_type(payload)) { case CBFS_TYPE_SELF: /* Simple ELF */ - selfload_mapped(payload, mapping, BM_MEM_RAM); + selfload_mapped(payload, buffer, BM_MEM_RAM); break; case CBFS_TYPE_FIT: /* Flattened image tree */ if (CONFIG(PAYLOAD_FIT_SUPPORT)) { - fit_payload(payload, mapping); + fit_payload(payload, buffer); break; } /* else fall-through */ default: @@ -155,7 +200,8 @@ void payload_load(void) break; } - cbfs_unmap(mapping); + if (mapping) + cbfs_unmap(mapping); out: if (prog_entry(payload) == NULL) die_with_post_code(POST_INVALID_ROM, "Payload not loaded.\n"); |