prog_loaders: Remove prog_locate()
This patch rewrites the last few users of prog_locate() to access CBFS APIs directly and removes the call. This eliminates the double-meaning of prog_rdev() (referring to both the boot medium where the program is stored before loading, and the memory area where it is loaded after) and makes sure that programs are always located and loaded in a single operation. This makes CBFS verification easier to implement and secure because it avoids leaking a raw rdev of unverified data outside the CBFS core code. Signed-off-by: Julius Werner <jwerner@chromium.org> Change-Id: I7a5525f66e1d5f3a632e8f6f0ed9e116e3cebfcf Reviewed-on: https://review.coreboot.org/c/coreboot/+/49337 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#include <arch/romstage.h>
|
#include <arch/romstage.h>
|
||||||
#include <arch/symbols.h>
|
#include <arch/symbols.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <commonlib/helpers.h>
|
#include <commonlib/helpers.h>
|
||||||
#include <cpu/x86/mtrr.h>
|
#include <cpu/x86/mtrr.h>
|
||||||
#include <fsp/car.h>
|
#include <fsp/car.h>
|
||||||
#include <fsp/util.h>
|
#include <fsp/util.h>
|
||||||
#include <program_loading.h>
|
|
||||||
|
|
||||||
void fill_postcar_frame(struct postcar_frame *pcf)
|
void fill_postcar_frame(struct postcar_frame *pcf)
|
||||||
{
|
{
|
||||||
@ -27,14 +27,14 @@ void mainboard_romstage_entry(void)
|
|||||||
{
|
{
|
||||||
/* Need to locate the current FSP_INFO_HEADER. The cache-as-ram
|
/* Need to locate the current FSP_INFO_HEADER. The cache-as-ram
|
||||||
* is still enabled. We can directly access work buffer here. */
|
* is still enabled. We can directly access work buffer here. */
|
||||||
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");
|
void *fsp = cbfs_map("fsp.bin", NULL);
|
||||||
|
|
||||||
if (prog_locate(&fsp))
|
if (!fsp)
|
||||||
die_with_post_code(POST_INVALID_CBFS, "Unable to locate fsp.bin");
|
die_with_post_code(POST_INVALID_CBFS, "Unable to locate fsp.bin");
|
||||||
|
|
||||||
/* This leaks a mapping which this code assumes is benign as
|
/* This leaks a mapping which this code assumes is benign as
|
||||||
* the flash is memory mapped CPU's address space. */
|
* the flash is memory mapped CPU's address space. */
|
||||||
FSP_INFO_HEADER *fih = find_fsp((uintptr_t)rdev_mmap_full(prog_rdev(&fsp)));
|
FSP_INFO_HEADER *fih = find_fsp((uintptr_t)fsp);
|
||||||
|
|
||||||
if (!fih)
|
if (!fih)
|
||||||
die("Invalid FSP header\n");
|
die("Invalid FSP header\n");
|
||||||
|
@ -1,29 +1,24 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <commonlib/fsp.h>
|
#include <commonlib/fsp.h>
|
||||||
#include <fsp/util.h>
|
#include <fsp/util.h>
|
||||||
|
|
||||||
int fsp_relocate(struct prog *fsp_relocd, const struct region_device *fsp_src)
|
int fsp_relocate(struct prog *fsp_relocd)
|
||||||
{
|
{
|
||||||
void *new_loc;
|
|
||||||
void *fih;
|
void *fih;
|
||||||
ssize_t fih_offset;
|
ssize_t fih_offset;
|
||||||
size_t size = region_device_sz(fsp_src);
|
size_t size;
|
||||||
|
|
||||||
new_loc = cbmem_add(CBMEM_ID_REFCODE, size);
|
|
||||||
|
|
||||||
|
void *new_loc = cbfs_cbmem_alloc(prog_name(fsp_relocd),
|
||||||
|
CBMEM_ID_REFCODE, &size);
|
||||||
if (new_loc == NULL) {
|
if (new_loc == NULL) {
|
||||||
printk(BIOS_ERR, "ERROR: Unable to load FSP into memory.\n");
|
printk(BIOS_ERR, "ERROR: Unable to load FSP into memory.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdev_readat(fsp_src, new_loc, 0, size) != size) {
|
|
||||||
printk(BIOS_ERR, "ERROR: Can't read FSP's region device.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fih_offset = fsp1_1_relocate((uintptr_t)new_loc, new_loc, size);
|
fih_offset = fsp1_1_relocate((uintptr_t)new_loc, new_loc, size);
|
||||||
|
|
||||||
if (fih_offset <= 0) {
|
if (fih_offset <= 0) {
|
||||||
|
@ -40,10 +40,10 @@ static inline uint32_t fsp_version(FSP_INFO_HEADER *fih)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Relocate FSP entire binary into ram. Returns < 0 on error, 0 on success.
|
* Relocate FSP entire binary into ram. Returns < 0 on error, 0 on success.
|
||||||
* The FSP source is pointed to by region_device and the relocation information
|
* The CBFS file name of the FSP source and the relocation information
|
||||||
* is encoded in a struct prog with its entry point set to the FSP info header.
|
* is encoded in a struct prog with its entry point set to the FSP info header.
|
||||||
*/
|
*/
|
||||||
int fsp_relocate(struct prog *fsp_relocd, const struct region_device *fsp_src);
|
int fsp_relocate(struct prog *fsp_relocd);
|
||||||
|
|
||||||
/* Additional HOB types not included in the FSP:
|
/* Additional HOB types not included in the FSP:
|
||||||
* #define EFI_HOB_TYPE_HANDOFF 0x0001
|
* #define EFI_HOB_TYPE_HANDOFF 0x0001
|
||||||
|
@ -144,21 +144,6 @@ static void fsp_run_silicon_init(FSP_INFO_HEADER *fsp_info_header)
|
|||||||
soc_after_silicon_init();
|
soc_after_silicon_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsp_find_and_relocate(struct prog *fsp)
|
|
||||||
{
|
|
||||||
if (prog_locate(fsp)) {
|
|
||||||
printk(BIOS_ERR, "ERROR: Couldn't find %s\n", prog_name(fsp));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsp_relocate(fsp, prog_rdev(fsp))) {
|
|
||||||
printk(BIOS_ERR, "ERROR: FSP relocation failed.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsp_load(void)
|
static void fsp_load(void)
|
||||||
{
|
{
|
||||||
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");
|
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");
|
||||||
@ -166,7 +151,7 @@ static void fsp_load(void)
|
|||||||
if (resume_from_stage_cache()) {
|
if (resume_from_stage_cache()) {
|
||||||
stage_cache_load_stage(STAGE_REFCODE, &fsp);
|
stage_cache_load_stage(STAGE_REFCODE, &fsp);
|
||||||
} else {
|
} else {
|
||||||
fsp_find_and_relocate(&fsp);
|
fsp_relocate(&fsp);
|
||||||
|
|
||||||
if (prog_entry(&fsp))
|
if (prog_entry(&fsp))
|
||||||
stage_cache_add(STAGE_REFCODE, &fsp);
|
stage_cache_add(STAGE_REFCODE, &fsp);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <fsp/util.h>
|
#include <fsp/util.h>
|
||||||
|
|
||||||
@ -9,13 +10,13 @@ asmlinkage void chipset_teardown_car_main(void)
|
|||||||
FSP_INFO_HEADER *fih;
|
FSP_INFO_HEADER *fih;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
FSP_TEMP_RAM_EXIT temp_ram_exit;
|
FSP_TEMP_RAM_EXIT temp_ram_exit;
|
||||||
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");
|
|
||||||
|
|
||||||
/* CBMEM_ID_VBOOT_WORKBUF is used as vboot workbuffer.
|
/* CBMEM_ID_VBOOT_WORKBUF is used as vboot workbuffer.
|
||||||
* Init CBMEM before loading fsp, to have buffer available */
|
* Init CBMEM before loading fsp, to have buffer available */
|
||||||
cbmem_initialize();
|
cbmem_initialize();
|
||||||
|
|
||||||
if (prog_locate(&fsp)) {
|
void *fsp = cbfs_map("fsp.bin", NULL);
|
||||||
|
if (!fsp) {
|
||||||
die("Unable to locate fsp.bin\n");
|
die("Unable to locate fsp.bin\n");
|
||||||
} else {
|
} else {
|
||||||
/* This leaks a mapping which this code assumes is benign as
|
/* This leaks a mapping which this code assumes is benign as
|
||||||
@ -25,7 +26,7 @@ asmlinkage void chipset_teardown_car_main(void)
|
|||||||
as it casts error values to FSP_INFO_HEADER pointers.
|
as it casts error values to FSP_INFO_HEADER pointers.
|
||||||
Checking for return values can only be done sanely once
|
Checking for return values can only be done sanely once
|
||||||
that is fixed. */
|
that is fixed. */
|
||||||
fih = find_fsp((uintptr_t)rdev_mmap_full(prog_rdev(&fsp)));
|
fih = find_fsp((uintptr_t)fsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_ram_exit = (FSP_TEMP_RAM_EXIT)(fih->TempRamExitEntryOffset +
|
temp_ram_exit = (FSP_TEMP_RAM_EXIT)(fih->TempRamExitEntryOffset +
|
||||||
|
@ -41,8 +41,7 @@ void arch_segment_loaded(uintptr_t start, size_t size, int flags);
|
|||||||
|
|
||||||
/* Representation of a program. */
|
/* Representation of a program. */
|
||||||
struct prog {
|
struct prog {
|
||||||
/* The region_device is the source of program content to load. After
|
/* The region_device represents the memory region of the stages and
|
||||||
* loading program it represents the memory region of the stages and
|
|
||||||
* payload. For architectures that use a bounce buffer
|
* payload. For architectures that use a bounce buffer
|
||||||
* then it would represent the bounce buffer. */
|
* then it would represent the bounce buffer. */
|
||||||
enum prog_type type;
|
enum prog_type type;
|
||||||
@ -128,13 +127,10 @@ static inline void prog_set_arg(struct prog *prog, void *arg)
|
|||||||
prog->arg = arg;
|
prog->arg = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate the identified program to run. Return 0 on success. < 0 on error. */
|
|
||||||
int prog_locate(struct prog *prog);
|
|
||||||
/* The prog_locate_hook() is called prior to CBFS traversal. The hook can be
|
/* The prog_locate_hook() is called prior to CBFS traversal. The hook can be
|
||||||
* used to implement policy that allows or prohibits further progress through
|
* used to implement policy that allows or prohibits further program loading.
|
||||||
* prog_locate(). The type and name field within struct prog are the only valid
|
* The type and name field within struct prog are the only valid fields. A 0
|
||||||
* fields. A 0 return value allows further progress while a non-zero return
|
* return value allows loading while a non-zero return value prohibits it. */
|
||||||
* value prohibits further progress */
|
|
||||||
int prog_locate_hook(struct prog *prog);
|
int prog_locate_hook(struct prog *prog);
|
||||||
|
|
||||||
/* Run the program described by prog. */
|
/* Run the program described by prog. */
|
||||||
@ -147,17 +143,6 @@ 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;
|
|
||||||
/* Determine if the loader is the active one. If so returns 1 else 0
|
|
||||||
* or < 0 on error. */
|
|
||||||
int (*is_loader_active)(struct prog *prog);
|
|
||||||
/* Returns < 0 on error or 0 on success. This function locates
|
|
||||||
* the rdev representing the file data associated with the passed in
|
|
||||||
* prog. */
|
|
||||||
int (*locate)(struct prog *prog);
|
|
||||||
};
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
* ROMSTAGE LOADING *
|
* ROMSTAGE LOADING *
|
||||||
************************/
|
************************/
|
||||||
|
@ -20,23 +20,6 @@
|
|||||||
const struct mem_region_device addrspace_32bit =
|
const struct mem_region_device addrspace_32bit =
|
||||||
MEM_REGION_DEV_RO_INIT(0, ~0UL);
|
MEM_REGION_DEV_RO_INIT(0, ~0UL);
|
||||||
|
|
||||||
int prog_locate(struct prog *prog)
|
|
||||||
{
|
|
||||||
struct cbfsf file;
|
|
||||||
|
|
||||||
if (prog_locate_hook(prog))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (cbfs_boot_locate(&file, prog_name(prog), NULL))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
cbfsf_file_type(&file, &prog->cbfs_type);
|
|
||||||
|
|
||||||
cbfs_file_data(prog_rdev(prog), &file);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_romstage(void)
|
void run_romstage(void)
|
||||||
{
|
{
|
||||||
struct prog romstage =
|
struct prog romstage =
|
||||||
|
Reference in New Issue
Block a user