lib/prog_loaders: Add payload_preload
This method will allow the SoC code to start loading the payload before it is required. BUG=b:177909625 TEST=Boot guybrush and see read/decompress drop by 23 ms. Signed-off-by: Raul E Rangel <rrangel@chromium.org> Change-Id: Ifa8f30a0f4f931ece803c2e8e022e4d33d3fe581 Reviewed-on: https://review.coreboot.org/c/coreboot/+/56051 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
parent
61f44127f0
commit
67798cfd80
|
@ -154,6 +154,13 @@ void run_ramstage(void);
|
||||||
|
|
||||||
int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size);
|
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. */
|
/* Load payload into memory in preparation to run. */
|
||||||
void payload_load(void);
|
void payload_load(void);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ DECLARE_REGION(asan_shadow)
|
||||||
|
|
||||||
/* Regions for execution units. */
|
/* Regions for execution units. */
|
||||||
|
|
||||||
|
DECLARE_REGION(payload_preload_cache)
|
||||||
DECLARE_REGION(payload)
|
DECLARE_REGION(payload)
|
||||||
/* "program" always refers to the current execution unit. */
|
/* "program" always refers to the current execution unit. */
|
||||||
DECLARE_REGION(program)
|
DECLARE_REGION(program)
|
||||||
|
|
|
@ -98,3 +98,14 @@ config NO_CBFS_MCACHE
|
||||||
the associated CAR/SRAM size. In that case every single CBFS file
|
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
|
lookup must re-read the same CBFS directory entries from flash to find
|
||||||
the respective file.
|
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.
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <rmodule.h>
|
#include <rmodule.h>
|
||||||
#include <stage_cache.h>
|
#include <stage_cache.h>
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
|
#include <thread.h>
|
||||||
#include <timestamp.h>
|
#include <timestamp.h>
|
||||||
#include <security/vboot/vboot_common.h>
|
#include <security/vboot/vboot_common.h>
|
||||||
|
|
||||||
|
@ -126,27 +127,71 @@ fail:
|
||||||
static struct prog global_payload =
|
static struct prog global_payload =
|
||||||
PROG_INIT(PROG_PAYLOAD, CONFIG_CBFS_PREFIX "/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)
|
void payload_load(void)
|
||||||
{
|
{
|
||||||
struct prog *payload = &global_payload;
|
struct prog *payload = &global_payload;
|
||||||
|
struct thread_handle *handle = &payload_preload_handle;
|
||||||
|
void *mapping = NULL;
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
timestamp_add_now(TS_LOAD_PAYLOAD);
|
timestamp_add_now(TS_LOAD_PAYLOAD);
|
||||||
|
|
||||||
if (prog_locate_hook(payload))
|
if (prog_locate_hook(payload))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
payload->cbfs_type = CBFS_TYPE_QUERY;
|
if (CONFIG(PAYLOAD_PRELOAD) && thread_join(handle) == CB_SUCCESS) {
|
||||||
void *mapping = cbfs_type_map(prog_name(payload), NULL, &payload->cbfs_type);
|
buffer = _payload_preload_cache;
|
||||||
if (!mapping)
|
} else {
|
||||||
|
payload->cbfs_type = CBFS_TYPE_QUERY;
|
||||||
|
mapping = cbfs_type_map(prog_name(payload), NULL, &payload->cbfs_type);
|
||||||
|
buffer = mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
switch (prog_cbfs_type(payload)) {
|
switch (prog_cbfs_type(payload)) {
|
||||||
case CBFS_TYPE_SELF: /* Simple ELF */
|
case CBFS_TYPE_SELF: /* Simple ELF */
|
||||||
selfload_mapped(payload, mapping, BM_MEM_RAM);
|
selfload_mapped(payload, buffer, BM_MEM_RAM);
|
||||||
break;
|
break;
|
||||||
case CBFS_TYPE_FIT: /* Flattened image tree */
|
case CBFS_TYPE_FIT: /* Flattened image tree */
|
||||||
if (CONFIG(PAYLOAD_FIT_SUPPORT)) {
|
if (CONFIG(PAYLOAD_FIT_SUPPORT)) {
|
||||||
fit_payload(payload, mapping);
|
fit_payload(payload, buffer);
|
||||||
break;
|
break;
|
||||||
} /* else fall-through */
|
} /* else fall-through */
|
||||||
default:
|
default:
|
||||||
|
@ -155,7 +200,8 @@ void payload_load(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cbfs_unmap(mapping);
|
if (mapping)
|
||||||
|
cbfs_unmap(mapping);
|
||||||
out:
|
out:
|
||||||
if (prog_entry(payload) == NULL)
|
if (prog_entry(payload) == NULL)
|
||||||
die_with_post_code(POST_INVALID_ROM, "Payload not loaded.\n");
|
die_with_post_code(POST_INVALID_ROM, "Payload not loaded.\n");
|
||||||
|
|
Loading…
Reference in New Issue