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,
|
||||
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);
|
||||
|
||||
/* Simple buffer for streaming media. */
|
||||
|
@ -75,11 +74,6 @@ void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer,
|
|||
// Utility functions
|
||||
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. */
|
||||
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"
|
||||
|
||||
#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__
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <reset.h>
|
||||
#include <boot/tables.h>
|
||||
#include <cbfs.h>
|
||||
#include <payload_loader.h>
|
||||
#include <lib.h>
|
||||
#if CONFIG_HAVE_ACPI_RESUME
|
||||
#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)
|
||||
{
|
||||
void *payload;
|
||||
void *entry;
|
||||
struct payload *payload;
|
||||
|
||||
timestamp_add_now(TS_LOAD_PAYLOAD);
|
||||
|
||||
payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
|
||||
CONFIG_CBFS_PREFIX "/payload");
|
||||
payload = payload_load();
|
||||
|
||||
if (! payload)
|
||||
die("Could not find a payload\n");
|
||||
|
||||
entry = selfload(get_lb_mem(), payload);
|
||||
|
||||
if (! entry)
|
||||
die("Could not load payload\n");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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");
|
||||
/* Returning from this state will fail because the following signals
|
||||
|
|
|
@ -19,3 +19,5 @@
|
|||
|
||||
romstage-y += cbfs_ramstage_loader.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
|
||||
#include <timestamp.h>
|
||||
#endif
|
||||
#include <payload_loader.h>
|
||||
|
||||
/* Maximum physical address we can use for the coreboot bounce buffer. */
|
||||
#ifndef MAX_ADDR
|
||||
|
|
|
@ -82,7 +82,9 @@ int recovery_mode_enabled(void)
|
|||
}
|
||||
|
||||
#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 firmware_component *fwc;
|
||||
|
@ -109,6 +111,27 @@ void *vboot_get_payload(size_t *len)
|
|||
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)
|
||||
{
|
||||
struct vboot_handoff *vboot_handoff;
|
||||
|
|
|
@ -47,7 +47,6 @@ int recovery_mode_enabled(void);
|
|||
void init_chromeos(int bootmode);
|
||||
|
||||
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
||||
void *vboot_get_payload(size_t *len);
|
||||
/* Returns 0 on success < 0 on error. */
|
||||
int vboot_get_handoff_info(void **addr, uint32_t *size);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue