program loading: unify on struct prog

Instead of having different structures for loading
ramstage and payload align to using struct prog.
This also removes arch_payload_run() in favor of
the prog_run() interface.

Change-Id: I31483096094eacc713a7433811cd69cc5621c43e
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/8849
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Tested-by: build bot (Jenkins)
Reviewed-by: Marc Jones <marc.jones@se-eng.com>
This commit is contained in:
Aaron Durbin 2015-03-20 16:37:12 -05:00 committed by Aaron Durbin
parent b3847e6424
commit ce9efe061a
11 changed files with 62 additions and 99 deletions

View File

@ -29,8 +29,3 @@ void arch_prog_run(struct prog *prog)
doit = prog_entry(prog); doit = prog_entry(prog);
doit(prog_entry_arg(prog)); doit(prog_entry_arg(prog));
} }
void arch_payload_run(struct payload *payload)
{
arch_prog_run(&payload->prog);
}

View File

@ -77,8 +77,3 @@ void arch_prog_run(struct prog *prog)
doit(prog_entry_arg(prog)); doit(prog_entry_arg(prog));
} }
void arch_payload_run(struct payload *payload)
{
arch_prog_run(&payload->prog);
}

View File

@ -24,8 +24,3 @@ void arch_prog_run(struct prog *prog)
{ {
stage_exit(prog_entry(prog)); stage_exit(prog_entry(prog));
} }
void arch_payload_run(struct payload *payload)
{
arch_prog_run(&payload->prog);
}

View File

@ -26,8 +26,3 @@ void arch_prog_run(struct prog *prog)
doit = prog_entry(prog); doit = prog_entry(prog);
doit(prog_entry_arg(prog)); doit(prog_entry_arg(prog));
} }
void arch_payload_run(struct payload *payload)
{
arch_prog_run(&payload->prog);
}

View File

@ -123,18 +123,22 @@ static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
); );
} }
void arch_payload_run(struct payload *payload) static void try_payload(struct prog *prog)
{ {
if (prog->type == PROG_PAYLOAD) {
if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)) if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
jmp_payload_no_bounce_buffer(prog_entry(&payload->prog)); jmp_payload_no_bounce_buffer(prog_entry(prog));
else else
jmp_payload(prog_entry(&payload->prog), jmp_payload(prog_entry(prog),
(uintptr_t)payload->bounce.data, (uintptr_t)prog_start(prog),
payload->bounce.size); prog_size(prog));
}
} }
void arch_prog_run(struct prog *prog) void arch_prog_run(struct prog *prog)
{ {
if (ENV_RAMSTAGE)
try_payload(prog);
__asm__ volatile ( __asm__ volatile (
"jmp *%%edi\n" "jmp *%%edi\n"
:: "D"(prog_entry(prog)) :: "D"(prog_entry(prog))

View File

@ -50,7 +50,8 @@ struct prog {
const char *name; const char *name;
/* The area can mean different things depending on what type the /* The area can mean different things depending on what type the
* program is. e.g. a payload prog uses this field for the backing * program is. e.g. a payload prog uses this field for the backing
* store of the payload_segments and data. */ * store of the payload_segments and data. After loading the segments
* area is updated to reflect the bounce buffer used. */
struct buffer_area area; struct buffer_area area;
/* Entry to program with optional argument. It's up to the architecture /* Entry to program with optional argument. It's up to the architecture
* to decide if argument is passed. */ * to decide if argument is passed. */
@ -100,6 +101,14 @@ void arch_prog_run(struct prog *prog);
* code it needs to that as well. */ * code it needs to that as well. */
void platform_prog_run(struct prog *prog); void platform_prog_run(struct prog *prog);
struct prog_loader_ops {
const char *name;
/* Returns < 0 on error or 0 on success. This function needs to do
* different things depending on the prog type. See definition
* of struct prog above. */
int (*prepare)(struct prog *prog);
};
/************************ /************************
* ROMSTAGE LOADING * * ROMSTAGE LOADING *
************************/ ************************/
@ -111,6 +120,9 @@ void run_romstage(void);
* RAMSTAGE LOADING * * RAMSTAGE LOADING *
************************/ ************************/
/* Run ramstage from romstage. */
void run_ramstage(void);
struct romstage_handoff; struct romstage_handoff;
#if IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE) #if IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)
/* Cache the loaded ramstage described by prog. */ /* Cache the loaded ramstage described by prog. */
@ -124,25 +136,10 @@ static inline void load_cached_ramstage(struct romstage_handoff *h,
struct prog *p) {} struct prog *p) {}
#endif #endif
/* Run ramstage from romstage. */
void run_ramstage(void);
struct ramstage_loader_ops {
const char *name;
/* Returns 0 on succes. < 0 on error. */
int (*load)(struct prog *ramstage);
};
/*********************** /***********************
* PAYLOAD LOADING * * PAYLOAD LOADING *
***********************/ ***********************/
struct payload {
struct prog prog;
/* Used when payload wants memory coreboot ramstage is running at. */
struct buffer_area bounce;
};
/* Load payload into memory in preparation to run. */ /* Load payload into memory in preparation to run. */
void payload_load(void); void payload_load(void);
@ -150,23 +147,9 @@ void payload_load(void);
void payload_run(void); void payload_run(void);
/* Mirror the payload to be loaded. */ /* Mirror the payload to be loaded. */
void mirror_payload(struct payload *payload); void mirror_payload(struct prog *payload);
/* architecture specific function to run payload. */
void arch_payload_run(struct payload *payload);
/* Payload loading operations. */
struct payload_loader_ops {
const char *name;
/*
* Fill in payload_backing_store structure. Return 0 on success, < 0
* on failure.
*/
int (*locate)(struct payload *payload);
};
/* Defined in src/lib/selfboot.c */ /* Defined in src/lib/selfboot.c */
void *selfload(struct payload *payload); void *selfload(struct prog *payload);
#endif /* PROGRAM_LOADING_H */ #endif /* PROGRAM_LOADING_H */

View File

@ -20,24 +20,24 @@
#include <cbfs.h> #include <cbfs.h>
#include <program_loading.h> #include <program_loading.h>
static int cbfs_locate_payload(struct payload *payload) static int cbfs_locate_payload(struct prog *payload)
{ {
void *buffer; void *buffer;
size_t size; size_t size;
const int type = CBFS_TYPE_PAYLOAD; const int type = CBFS_TYPE_PAYLOAD;
buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->prog.name, buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name,
type, &size); type, &size);
if (buffer == NULL) if (buffer == NULL)
return -1; return -1;
prog_set_area(&payload->prog, buffer, size); prog_set_area(payload, buffer, size);
return 0; return 0;
} }
const struct payload_loader_ops cbfs_payload_loader = { const struct prog_loader_ops cbfs_payload_loader = {
.name = "CBFS", .name = "CBFS",
.locate = cbfs_locate_payload, .prepare = cbfs_locate_payload,
}; };

View File

@ -54,7 +54,7 @@ static int cbfs_load_ramstage(struct prog *ramstage)
#endif /* CONFIG_RELOCATABLE_RAMSTAGE */ #endif /* CONFIG_RELOCATABLE_RAMSTAGE */
const struct ramstage_loader_ops cbfs_ramstage_loader = { const struct prog_loader_ops cbfs_ramstage_loader = {
.name = "CBFS", .name = "CBFS",
.load = cbfs_load_ramstage, .prepare = cbfs_load_ramstage,
}; };

View File

@ -26,24 +26,22 @@
#include <program_loading.h> #include <program_loading.h>
#include <timestamp.h> #include <timestamp.h>
extern const struct payload_loader_ops vboot_payload_loader; extern const struct prog_loader_ops vboot_payload_loader;
extern const struct payload_loader_ops cbfs_payload_loader; extern const struct prog_loader_ops cbfs_payload_loader;
static const struct payload_loader_ops *payload_ops[] = { static const struct prog_loader_ops *payload_ops[] = {
#if CONFIG_VBOOT_VERIFY_FIRMWARE #if CONFIG_VBOOT_VERIFY_FIRMWARE
&vboot_payload_loader, &vboot_payload_loader,
#endif #endif
&cbfs_payload_loader, &cbfs_payload_loader,
}; };
static struct payload global_payload = { static struct prog global_payload = {
.prog = {
.name = CONFIG_CBFS_PREFIX "/payload", .name = CONFIG_CBFS_PREFIX "/payload",
.type = PROG_PAYLOAD, .type = PROG_PAYLOAD,
},
}; };
void __attribute__((weak)) mirror_payload(struct payload *payload) void __attribute__((weak)) mirror_payload(struct prog *payload)
{ {
return; return;
} }
@ -51,19 +49,18 @@ void __attribute__((weak)) mirror_payload(struct payload *payload)
void payload_load(void) void payload_load(void)
{ {
int i; int i;
const struct payload_loader_ops *ops; const struct prog_loader_ops *ops;
struct payload *payload = &global_payload; struct prog *payload = &global_payload;
struct prog * prog = &payload->prog;
for (i = 0; i < ARRAY_SIZE(payload_ops); i++) { for (i = 0; i < ARRAY_SIZE(payload_ops); i++) {
ops = payload_ops[i]; ops = payload_ops[i];
if (ops->locate(payload) < 0) { if (ops->prepare(payload) < 0) {
printk(BIOS_DEBUG, "%s: could not locate payload.\n", printk(BIOS_DEBUG, "%s: could not locate payload.\n",
ops->name); ops->name);
continue; continue;
} }
printk(BIOS_DEBUG, "%s: located payload @ %p, %zu bytes.\n", printk(BIOS_DEBUG, "%s: located payload @ %p, %zu bytes.\n",
ops->name, prog_start(prog), prog_size(prog)); ops->name, prog_start(payload), prog_size(payload));
break; break;
} }
@ -73,23 +70,23 @@ void payload_load(void)
mirror_payload(payload); mirror_payload(payload);
/* Pass cbtables to payload if architecture desires it. */ /* Pass cbtables to payload if architecture desires it. */
prog_set_entry(&payload->prog, selfload(payload), prog_set_entry(payload, selfload(payload),
cbmem_find(CBMEM_ID_CBTABLE)); cbmem_find(CBMEM_ID_CBTABLE));
out: out:
if (prog_entry(&payload->prog) == NULL) if (prog_entry(payload) == NULL)
die("Payload not loaded.\n"); die("Payload not loaded.\n");
} }
void payload_run(void) void payload_run(void)
{ {
struct payload *payload = &global_payload; struct prog *payload = &global_payload;
/* Reset to booting from this image as late as possible */ /* Reset to booting from this image as late as possible */
boot_successful(); boot_successful();
printk(BIOS_DEBUG, "Jumping to boot code at %p(%p)\n", printk(BIOS_DEBUG, "Jumping to boot code at %p(%p)\n",
prog_entry(&payload->prog), prog_entry_arg(&payload->prog)); prog_entry(payload), prog_entry_arg(payload));
post_code(POST_ENTER_ELF_BOOT); post_code(POST_ENTER_ELF_BOOT);
timestamp_add_now(TS_SELFBOOT_JUMP); timestamp_add_now(TS_SELFBOOT_JUMP);
@ -99,5 +96,5 @@ void payload_run(void)
*/ */
checkstack(_estack, 0); checkstack(_estack, 0);
arch_payload_run(payload); prog_run(payload);
} }

View File

@ -25,10 +25,10 @@
#include <romstage_handoff.h> #include <romstage_handoff.h>
#include <timestamp.h> #include <timestamp.h>
extern const struct ramstage_loader_ops cbfs_ramstage_loader; extern const struct prog_loader_ops cbfs_ramstage_loader;
extern const struct ramstage_loader_ops vboot_ramstage_loader; extern const struct prog_loader_ops vboot_ramstage_loader;
static const struct ramstage_loader_ops *loaders[] = { static const struct prog_loader_ops *loaders[] = {
#if CONFIG_VBOOT_VERIFY_FIRMWARE #if CONFIG_VBOOT_VERIFY_FIRMWARE
&vboot_ramstage_loader, &vboot_ramstage_loader,
#endif #endif
@ -36,12 +36,12 @@ static const struct ramstage_loader_ops *loaders[] = {
}; };
static void static void
load_ramstage(const struct ramstage_loader_ops *ops, load_ramstage(const struct prog_loader_ops *ops,
struct romstage_handoff *handoff, struct prog *ramstage) struct romstage_handoff *handoff, struct prog *ramstage)
{ {
timestamp_add_now(TS_START_COPYRAM); timestamp_add_now(TS_START_COPYRAM);
if (ops->load(ramstage)) if (ops->prepare(ramstage))
return; return;
cache_loaded_ramstage(handoff, ramstage); cache_loaded_ramstage(handoff, ramstage);
@ -68,7 +68,7 @@ static void run_ramstage_from_resume(struct romstage_handoff *handoff,
void run_ramstage(void) void run_ramstage(void)
{ {
struct romstage_handoff *handoff; struct romstage_handoff *handoff;
const struct ramstage_loader_ops *ops; const struct prog_loader_ops *ops;
int i; int i;
struct prog ramstage = { struct prog ramstage = {
.name = CONFIG_CBFS_PREFIX "/ramstage", .name = CONFIG_CBFS_PREFIX "/ramstage",

View File

@ -214,13 +214,13 @@ static int relocate_segment(unsigned long buffer, struct segment *seg)
static int build_self_segment_list( static int build_self_segment_list(
struct segment *head, struct segment *head,
struct payload *payload, uintptr_t *entry) struct prog *payload, uintptr_t *entry)
{ {
struct segment *new; struct segment *new;
struct segment *ptr; struct segment *ptr;
struct cbfs_payload_segment *segment, *first_segment; struct cbfs_payload_segment *segment, *first_segment;
struct cbfs_payload *cbfs_payload; struct cbfs_payload *cbfs_payload;
cbfs_payload = prog_start(&payload->prog); cbfs_payload = prog_start(payload);
memset(head, 0, sizeof(*head)); memset(head, 0, sizeof(*head));
head->next = head->prev = head; head->next = head->prev = head;
first_segment = segment = &cbfs_payload->segments; first_segment = segment = &cbfs_payload->segments;
@ -311,7 +311,7 @@ static int build_self_segment_list(
static int load_self_segments( static int load_self_segments(
struct segment *head, struct segment *head,
struct payload *payload) struct prog *payload)
{ {
struct segment *ptr; struct segment *ptr;
struct segment *last_non_empty; struct segment *last_non_empty;
@ -365,10 +365,6 @@ static int load_self_segments(
return 0; return 0;
} }
/* Update the payload's bounce buffer data used when loading. */
payload->bounce.data = (void *)(uintptr_t)bounce_buffer;
payload->bounce.size = bounce_size;
for(ptr = head->next; ptr != head; ptr = ptr->next) { for(ptr = head->next; ptr != head; ptr = ptr->next) {
unsigned char *dest, *src; unsigned char *dest, *src;
printk(BIOS_DEBUG, "Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n", printk(BIOS_DEBUG, "Loading Segment: addr: 0x%016lx memsz: 0x%016lx filesz: 0x%016lx\n",
@ -454,10 +450,13 @@ static int load_self_segments(
} }
} }
/* Update the payload's area with the bounce buffer information. */
prog_set_area(payload, (void *)(uintptr_t)bounce_buffer, bounce_size);
return 1; return 1;
} }
void *selfload(struct payload *payload) void *selfload(struct prog *payload)
{ {
uintptr_t entry = 0; uintptr_t entry = 0;
struct segment head; struct segment head;