diff options
author | Aaron Durbin <adurbin@chromium.org> | 2015-05-20 12:08:55 -0500 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-06-02 14:10:08 +0200 |
commit | ac12c66cf91343153ea90a6f33977a13e10b21d0 (patch) | |
tree | 2864de25bb12ed2d5c7ec8d691ec753f146c5e57 /src/lib | |
parent | 6a452eff90411176f9f2cad0ca0c665a31c032ee (diff) |
assets: abstract away the firmware assets used for booting
As there can be more than one source of firmware assets this
patch generalizes the notion of locating a particular asset.
struct asset is added along with some helper functions for
working on assets as a first class citizen.
Change-Id: I2ce575d1e5259aed4c34c3dcfd438abe9db1d7b9
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/10264
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Makefile.inc | 4 | ||||
-rw-r--r-- | src/lib/assets.c | 93 | ||||
-rw-r--r-- | src/lib/cbfs.c | 8 | ||||
-rw-r--r-- | src/lib/prog_loaders.c | 90 | ||||
-rw-r--r-- | src/lib/rmodule.c | 6 | ||||
-rw-r--r-- | src/lib/selfboot.c | 9 |
6 files changed, 115 insertions, 95 deletions
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index ebb3076e63..557cd66846 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -18,6 +18,7 @@ # subdirs-y += loaders +bootblock-y += assets.c bootblock-y += prog_loaders.c bootblock-y += prog_ops.c bootblock-y += cbfs.c @@ -36,6 +37,7 @@ bootblock-y += region.c bootblock-y += boot_device.c bootblock-y += fmap.c +verstage-y += assets.c verstage-y += prog_loaders.c verstage-y += prog_ops.c verstage-y += delay.c @@ -60,6 +62,7 @@ verstage-$(CONFIG_GENERIC_UDELAY) += timer.c verstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c verstage-y += mem_pool.c +romstage-y += assets.c romstage-y += prog_loaders.c romstage-y += prog_ops.c romstage-y += memchr.c @@ -92,6 +95,7 @@ endif romstage-$(CONFIG_GENERIC_UDELAY) += timer.c +ramstage-y += assets.c ramstage-y += prog_loaders.c ramstage-y += prog_ops.c ramstage-y += hardwaremain.c diff --git a/src/lib/assets.c b/src/lib/assets.c new file mode 100644 index 0000000000..656f0b1e2b --- /dev/null +++ b/src/lib/assets.c @@ -0,0 +1,93 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 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. + */ + + +#include <assets.h> +#include <boot_device.h> +#include <cbfs.h> +#include <console/console.h> +#include <rules.h> +#include <stdlib.h> + +#define DEFAULT_CBFS_PROVIDER_PRESENT \ + (!ENV_VERSTAGE || (ENV_VERSTAGE && !CONFIG_RETURN_FROM_VERSTAGE)) + +#if DEFAULT_CBFS_PROVIDER_PRESENT +static int cbfs_boot_asset_locate(struct asset *asset) +{ + return cbfs_boot_locate(&asset->rdev, asset->name, NULL); +} + +static const struct asset_provider cbfs_default_provider = { + .name = "CBFS", + .locate = cbfs_boot_asset_locate, +}; +#endif + +extern const struct asset_provider vboot_provider; + +static const struct asset_provider *providers[] = { +#if CONFIG_VBOOT_VERIFY_FIRMWARE + &vboot_provider, +#endif +#if DEFAULT_CBFS_PROVIDER_PRESENT + &cbfs_default_provider, +#endif +}; + +int asset_locate(struct asset *asset) +{ + int i; + + boot_device_init(); + + for (i = 0; i < ARRAY_SIZE(providers); i++) { + /* Default provider state is active. */ + int ret = 1; + const struct asset_provider *ops; + + ops = providers[i]; + + if (ops->is_active != NULL) + ret = ops->is_active(asset); + + if (ret == 0) { + printk(BIOS_DEBUG, "%s provider inactive.\n", + ops->name); + continue; + } else if (ret < 0) { + printk(BIOS_DEBUG, "%s provider failure.\n", + ops->name); + continue; + } + + printk(BIOS_DEBUG, "%s provider active.\n", ops->name); + + if (ops->locate(asset)) + continue; + + printk(BIOS_DEBUG, "'%s' located at offset: %zx size: %zx\n", + asset->name, region_device_offset(&asset->rdev), + region_device_sz(&asset->rdev)); + + return 0; + } + + return -1; +} diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index 23dfee70c9..3e83765bf3 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -188,12 +188,10 @@ void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device) void *cbfs_boot_load_stage_by_name(const char *name) { - struct prog stage = { - .name = name, - }; + struct prog stage = PROG_INIT(ASSET_UNKNOWN, name); uint32_t type = CBFS_TYPE_STAGE; - if (cbfs_boot_locate(&stage.rdev, name, &type)) + if (cbfs_boot_locate(&stage.asset.rdev, name, &type)) return NULL; if (cbfs_prog_stage_load(&stage)) @@ -209,7 +207,7 @@ int cbfs_prog_stage_load(struct prog *pstage) void *entry; size_t fsize; size_t foffset; - const struct region_device *fh = &pstage->rdev; + const struct region_device *fh = &pstage->asset.rdev; if (rdev_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage)) return 0; diff --git a/src/lib/prog_loaders.c b/src/lib/prog_loaders.c index 77999945d1..ec5eeb8693 100644 --- a/src/lib/prog_loaders.c +++ b/src/lib/prog_loaders.c @@ -20,7 +20,6 @@ #include <stdlib.h> #include <arch/stages.h> -#include <boot_device.h> #include <cbfs.h> #include <cbmem.h> #include <console/console.h> @@ -38,83 +37,10 @@ /* Only can represent up to 1 byte less than size_t. */ const struct mem_region_device addrspace_32bit = MEM_REGION_DEV_INIT(0, ~0UL); -#define DEFAULT_CBFS_LOADER_PRESENT \ - (!ENV_VERSTAGE || (ENV_VERSTAGE && !CONFIG_RETURN_FROM_VERSTAGE)) - -#if DEFAULT_CBFS_LOADER_PRESENT -static int cbfs_boot_prog_locate(struct prog *prog) -{ - return cbfs_boot_locate(&prog->rdev, prog->name, NULL); -} - -static const struct prog_loader_ops cbfs_default_loader = { - .locate = cbfs_boot_prog_locate, -}; -#endif - -extern const struct prog_loader_ops vboot_loader; - -static const struct prog_loader_ops *loaders[] = { -#if CONFIG_VBOOT_VERIFY_FIRMWARE - &vboot_loader, -#endif -#if DEFAULT_CBFS_LOADER_PRESENT - &cbfs_default_loader, -#endif -}; - -int prog_locate(struct prog *prog) -{ - int i; - - boot_device_init(); - - for (i = 0; i < ARRAY_SIZE(loaders); i++) { - /* Default loader state is active. */ - int ret = 1; - const struct prog_loader_ops *ops; - - ops = loaders[i]; - - if (ops->is_loader_active != NULL) - ret = ops->is_loader_active(prog); - - if (ret == 0) { - printk(BIOS_DEBUG, "%s loader inactive.\n", - ops->name); - continue; - } else if (ret < 0) { - printk(BIOS_DEBUG, "%s loader failure.\n", - ops->name); - continue; - } - - printk(BIOS_DEBUG, "%s loader active.\n", ops->name); - - if (ops->locate(prog)) - continue; - - printk(BIOS_DEBUG, "'%s' located at offset: %zx size: %zx\n", - prog->name, region_device_offset(&prog->rdev), - region_device_sz(&prog->rdev)); - - return 0; - } - - return -1; -} - void run_romstage(void) { - struct prog romstage = { - .name = CONFIG_CBFS_PREFIX "/romstage", - .type = PROG_ROMSTAGE, - }; - - /* The only time the default CBFS loader isn't present is during - * VERSTAGE in which it returns back to the calling stage. */ - if (!DEFAULT_CBFS_LOADER_PRESENT) - return; + struct prog romstage = + PROG_INIT(ASSET_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage"); if (prog_locate(&romstage)) goto fail; @@ -166,10 +92,8 @@ static int load_relocatable_ramstage(struct prog *ramstage) void run_ramstage(void) { - struct prog ramstage = { - .name = CONFIG_CBFS_PREFIX "/ramstage", - .type = PROG_RAMSTAGE, - }; + struct prog ramstage = + PROG_INIT(ASSET_RAMSTAGE, CONFIG_CBFS_PREFIX "/ramstage"); /* Only x86 systems currently take the same firmware path on resume. */ if (IS_ENABLED(CONFIG_ARCH_X86) && IS_ENABLED(CONFIG_EARLY_CBMEM_INIT)) @@ -197,10 +121,8 @@ fail: die("Ramstage was not loaded!\n"); } -static struct prog global_payload = { - .name = CONFIG_CBFS_PREFIX "/payload", - .type = PROG_PAYLOAD, -}; +static struct prog global_payload = + PROG_INIT(ASSET_PAYLOAD, CONFIG_CBFS_PREFIX "/payload"); void __attribute__((weak)) mirror_payload(struct prog *payload) { diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c index 35893d9d96..c17c7a5a2c 100644 --- a/src/lib/rmodule.c +++ b/src/lib/rmodule.c @@ -264,10 +264,10 @@ int rmodule_stage_load(struct rmod_stage_load *rsl) void *rmod_loc; struct region_device *fh; - if (rsl->prog == NULL || rsl->prog->name == NULL) + if (rsl->prog == NULL || prog_name(rsl->prog) == NULL) return -1; - fh = &rsl->prog->rdev; + fh = prog_rdev(rsl->prog); if (rdev_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage)) return -1; @@ -284,7 +284,7 @@ int rmodule_stage_load(struct rmod_stage_load *rsl) rmod_loc = &stage_region[rmodule_offset]; printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n", - rsl->prog->name, rmod_loc, stage.memlen); + prog_name(rsl->prog), rmod_loc, stage.memlen); if (stage.compression == CBFS_COMPRESS_NONE) { if (rdev_readat(fh, rmod_loc, sizeof(stage), stage.len) != diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index 3f8cc6fb18..94a75bef2e 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -454,7 +454,7 @@ void *selfload(struct prog *payload) struct segment head; void *data; - data = rdev_mmap_full(&payload->rdev); + data = rdev_mmap_full(prog_rdev(payload)); if (data == NULL) return NULL; @@ -469,7 +469,10 @@ void *selfload(struct prog *payload) printk(BIOS_SPEW, "Loaded segments\n"); - rdev_munmap(&payload->rdev, data); + rdev_munmap(prog_rdev(payload), data); + + /* Update the payload's area with the bounce buffer information. */ + prog_set_area(payload, (void *)(uintptr_t)bounce_buffer, bounce_size); /* Update the payload's area with the bounce buffer information. */ prog_set_area(payload, (void *)(uintptr_t)bounce_buffer, bounce_size); @@ -477,6 +480,6 @@ void *selfload(struct prog *payload) return (void *)entry; out: - rdev_munmap(&payload->rdev, data); + rdev_munmap(prog_rdev(payload), data); return NULL; } |