coreboot: unify infrastructure for loading payloads
A payload can be loaded either from a vboot region or from cbfs. Provide a common place for choosing where the payload is loaded from. Additionally, place the logic in the 'loaders' directory similarly to the ramstage loader infrastructure. Change-Id: I6b0034ea5ebd04a3d058151819ac77a126a6bfe2 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5296 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
9cd96b4096
commit
bdf913ab01
|
@ -54,7 +54,6 @@
|
||||||
|
|
||||||
void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
|
void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
|
||||||
uint16_t device, void * dest);
|
uint16_t device, void * dest);
|
||||||
void *cbfs_load_payload(struct cbfs_media *media, const char *name);
|
|
||||||
void *cbfs_load_stage(struct cbfs_media *media, const char *name);
|
void *cbfs_load_stage(struct cbfs_media *media, const char *name);
|
||||||
|
|
||||||
/* Simple buffer for streaming media. */
|
/* Simple buffer for streaming media. */
|
||||||
|
@ -75,11 +74,6 @@ void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer,
|
||||||
// Utility functions
|
// Utility functions
|
||||||
int run_address(void *f);
|
int run_address(void *f);
|
||||||
|
|
||||||
/* Defined in src/lib/selfboot.c */
|
|
||||||
struct lb_memory;
|
|
||||||
void *selfload(struct lb_memory *mem, struct cbfs_payload *payload);
|
|
||||||
void selfboot(void *entry);
|
|
||||||
|
|
||||||
/* Defined in individual arch / board implementation. */
|
/* Defined in individual arch / board implementation. */
|
||||||
int init_default_cbfs_media(struct cbfs_media *media);
|
int init_default_cbfs_media(struct cbfs_media *media);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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 PAYLOAD_LOADER_H
|
||||||
|
#define PAYLOAD_LOADER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct payload_backing_store {
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct payload {
|
||||||
|
const char *name;
|
||||||
|
struct payload_backing_store backing_store;
|
||||||
|
void *entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load payload into memory and return pointer to payload structure. Returns
|
||||||
|
* NULL on error.
|
||||||
|
*/
|
||||||
|
struct payload *payload_load(void);
|
||||||
|
|
||||||
|
/* Run the loaded payload. */
|
||||||
|
void payload_run(const 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 */
|
||||||
|
struct lb_memory;
|
||||||
|
struct cbfs_payload;
|
||||||
|
void *selfload(struct lb_memory *mem, struct cbfs_payload *payload);
|
||||||
|
void selfboot(void *entry);
|
||||||
|
|
||||||
|
#endif /* PAYLOAD_LOADER_H */
|
|
@ -65,12 +65,6 @@
|
||||||
|
|
||||||
#include "cbfs_core.c"
|
#include "cbfs_core.c"
|
||||||
|
|
||||||
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
|
||||||
#include <vendorcode/google/chromeos/chromeos.h>
|
|
||||||
#else
|
|
||||||
static inline void *vboot_get_payload(int *len) { return NULL; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __SMM__
|
#ifndef __SMM__
|
||||||
static inline int tohex4(unsigned int c)
|
static inline int tohex4(unsigned int c)
|
||||||
{
|
{
|
||||||
|
@ -160,19 +154,6 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
|
||||||
return (void *) entry;
|
return (void *) entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *cbfs_load_payload(struct cbfs_media *media, const char *name)
|
|
||||||
{
|
|
||||||
struct cbfs_payload *payload;
|
|
||||||
|
|
||||||
payload = vboot_get_payload(NULL);
|
|
||||||
if (payload != NULL)
|
|
||||||
return payload;
|
|
||||||
|
|
||||||
payload = (struct cbfs_payload *)cbfs_get_file_content(
|
|
||||||
media, name, CBFS_TYPE_PAYLOAD, NULL);
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Simple buffer */
|
/* Simple buffer */
|
||||||
|
|
||||||
void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
|
void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <reset.h>
|
#include <reset.h>
|
||||||
#include <boot/tables.h>
|
#include <boot/tables.h>
|
||||||
#include <cbfs.h>
|
#include <payload_loader.h>
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#if CONFIG_HAVE_ACPI_RESUME
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
#include <arch/acpi.h>
|
#include <arch/acpi.h>
|
||||||
|
@ -226,30 +226,26 @@ static boot_state_t bs_write_tables(void *arg)
|
||||||
|
|
||||||
static boot_state_t bs_payload_load(void *arg)
|
static boot_state_t bs_payload_load(void *arg)
|
||||||
{
|
{
|
||||||
void *payload;
|
struct payload *payload;
|
||||||
void *entry;
|
|
||||||
|
|
||||||
timestamp_add_now(TS_LOAD_PAYLOAD);
|
timestamp_add_now(TS_LOAD_PAYLOAD);
|
||||||
|
|
||||||
payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
|
payload = payload_load();
|
||||||
CONFIG_CBFS_PREFIX "/payload");
|
|
||||||
if (! payload)
|
if (! payload)
|
||||||
die("Could not find a payload\n");
|
|
||||||
|
|
||||||
entry = selfload(get_lb_mem(), payload);
|
|
||||||
|
|
||||||
if (! entry)
|
|
||||||
die("Could not load payload\n");
|
die("Could not load payload\n");
|
||||||
|
|
||||||
/* Pass the payload to the next state. */
|
/* Pass the payload to the next state. */
|
||||||
boot_states[BS_PAYLOAD_BOOT].arg = entry;
|
boot_states[BS_PAYLOAD_BOOT].arg = payload;
|
||||||
|
|
||||||
return BS_PAYLOAD_BOOT;
|
return BS_PAYLOAD_BOOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boot_state_t bs_payload_boot(void *entry)
|
static boot_state_t bs_payload_boot(void *arg)
|
||||||
{
|
{
|
||||||
selfboot(entry);
|
struct payload *payload = arg;
|
||||||
|
|
||||||
|
payload_run(payload);
|
||||||
|
|
||||||
printk(BIOS_EMERG, "Boot failed");
|
printk(BIOS_EMERG, "Boot failed");
|
||||||
/* Returning from this state will fail because the following signals
|
/* Returning from this state will fail because the following signals
|
||||||
|
|
|
@ -19,3 +19,5 @@
|
||||||
|
|
||||||
romstage-y += cbfs_ramstage_loader.c
|
romstage-y += cbfs_ramstage_loader.c
|
||||||
romstage-y += load_and_run_ramstage.c
|
romstage-y += load_and_run_ramstage.c
|
||||||
|
ramstage-y += cbfs_payload_loader.c
|
||||||
|
ramstage-y += load_and_run_payload.c
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 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 <cbfs.h>
|
||||||
|
#include <payload_loader.h>
|
||||||
|
|
||||||
|
static int cbfs_locate_payload(struct payload *payload)
|
||||||
|
{
|
||||||
|
void *buffer;
|
||||||
|
size_t size;
|
||||||
|
const int type = CBFS_TYPE_PAYLOAD;
|
||||||
|
|
||||||
|
buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name,
|
||||||
|
type, &size);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
payload->backing_store.data = buffer;
|
||||||
|
payload->backing_store.size = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct payload_loader_ops cbfs_payload_loader = {
|
||||||
|
.name = "CBFS",
|
||||||
|
.locate = cbfs_locate_payload,
|
||||||
|
};
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <boot/coreboot_tables.h>
|
||||||
|
#include <payload_loader.h>
|
||||||
|
|
||||||
|
extern const struct payload_loader_ops vboot_payload_loader;
|
||||||
|
extern const struct payload_loader_ops cbfs_payload_loader;
|
||||||
|
|
||||||
|
static const struct payload_loader_ops *payload_ops[] = {
|
||||||
|
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
||||||
|
&vboot_payload_loader,
|
||||||
|
#endif
|
||||||
|
&cbfs_payload_loader,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct payload global_payload = {
|
||||||
|
.name = CONFIG_CBFS_PREFIX "/payload",
|
||||||
|
};
|
||||||
|
|
||||||
|
struct payload *payload_load(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *entry;
|
||||||
|
struct lb_memory *mem;
|
||||||
|
const struct payload_loader_ops *ops;
|
||||||
|
struct payload *payload = &global_payload;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(payload_ops); i++) {
|
||||||
|
ops = payload_ops[i];
|
||||||
|
if (ops->locate(payload) < 0) {
|
||||||
|
printk(BIOS_DEBUG, "%s: could not locate payload.\n",
|
||||||
|
ops->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printk(BIOS_DEBUG, "%s: located payload @ %p, %zu bytes.\n",
|
||||||
|
ops->name, payload->backing_store.data,
|
||||||
|
payload->backing_store.size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(payload_ops))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mem = get_lb_mem();
|
||||||
|
entry = selfload(mem, payload->backing_store.data);
|
||||||
|
|
||||||
|
if (entry == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
payload->entry = entry;
|
||||||
|
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
void payload_run(const struct payload *payload)
|
||||||
|
{
|
||||||
|
if (payload == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selfboot(payload->entry);
|
||||||
|
}
|
|
@ -32,6 +32,7 @@
|
||||||
#if CONFIG_COLLECT_TIMESTAMPS
|
#if CONFIG_COLLECT_TIMESTAMPS
|
||||||
#include <timestamp.h>
|
#include <timestamp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <payload_loader.h>
|
||||||
|
|
||||||
/* Maximum physical address we can use for the coreboot bounce buffer. */
|
/* Maximum physical address we can use for the coreboot bounce buffer. */
|
||||||
#ifndef MAX_ADDR
|
#ifndef MAX_ADDR
|
||||||
|
|
|
@ -82,7 +82,9 @@ int recovery_mode_enabled(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
||||||
void *vboot_get_payload(size_t *len)
|
#include <payload_loader.h>
|
||||||
|
|
||||||
|
static void *vboot_get_payload(size_t *len)
|
||||||
{
|
{
|
||||||
struct vboot_handoff *vboot_handoff;
|
struct vboot_handoff *vboot_handoff;
|
||||||
struct firmware_component *fwc;
|
struct firmware_component *fwc;
|
||||||
|
@ -109,6 +111,27 @@ void *vboot_get_payload(size_t *len)
|
||||||
return (void *)fwc->address;
|
return (void *)fwc->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vboot_locate_payload(struct payload *payload)
|
||||||
|
{
|
||||||
|
void *buffer;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
buffer = vboot_get_payload(&size);
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
payload->backing_store.data = buffer;
|
||||||
|
payload->backing_store.size = size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct payload_loader_ops vboot_payload_loader = {
|
||||||
|
.name = "VBOOT",
|
||||||
|
.locate = vboot_locate_payload,
|
||||||
|
};
|
||||||
|
|
||||||
int vboot_get_handoff_info(void **addr, uint32_t *size)
|
int vboot_get_handoff_info(void **addr, uint32_t *size)
|
||||||
{
|
{
|
||||||
struct vboot_handoff *vboot_handoff;
|
struct vboot_handoff *vboot_handoff;
|
||||||
|
|
|
@ -47,7 +47,6 @@ int recovery_mode_enabled(void);
|
||||||
void init_chromeos(int bootmode);
|
void init_chromeos(int bootmode);
|
||||||
|
|
||||||
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
||||||
void *vboot_get_payload(size_t *len);
|
|
||||||
/* Returns 0 on success < 0 on error. */
|
/* Returns 0 on success < 0 on error. */
|
||||||
int vboot_get_handoff_info(void **addr, uint32_t *size);
|
int vboot_get_handoff_info(void **addr, uint32_t *size);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue