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:
Aaron Durbin 2014-02-24 14:56:34 -06:00 committed by Aaron Durbin
parent 9cd96b4096
commit bdf913ab01
10 changed files with 222 additions and 40 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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,
};

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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