Julius Werner would like Aaron Durbin to review this change.

View Change

cbfs: Add metadata cache

This patch adds a new CBFS "mcache" (metadata cache) -- a memory buffer
that stores the headers of all CBFS files. Similar to the existing FMAP
cache, this cache should reduce the amount of SPI accesses we need to do
every boot: rather than having to re-read all CBFS headers from SPI
flash every time we're looking for a file, we can just walk the same
list in this in-memory copy and finally use it to directly access the
flash at the right position for the file data.

This patch adds the code to support the cache but doesn't enable it on
any platform. The next one will turn it on by default.

Change-Id: I5b1084bfdad1c6ab0ee1b143ed8dd796827f4c65
Signed-off-by: Julius Werner <jwerner@chromium.org>
---
M src/commonlib/Makefile.inc
A src/commonlib/bsd/cbfs_mcache.c
M src/commonlib/bsd/include/commonlib/bsd/cb_err.h
M src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h
M src/commonlib/include/commonlib/cbmem_id.h
M src/include/cbfs.h
M src/include/memlayout.h
M src/include/symbols.h
M src/lib/Kconfig
M src/lib/cbfs.c
M src/lib/coreboot_table.c
M src/security/vboot/vboot_common.h
M src/security/vboot/vboot_loader.c
13 files changed, 346 insertions(+), 31 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/23/38423/1
diff --git a/src/commonlib/Makefile.inc b/src/commonlib/Makefile.inc
index b2225cb..1a38e4a 100644
--- a/src/commonlib/Makefile.inc
+++ b/src/commonlib/Makefile.inc
@@ -37,6 +37,13 @@
ramstage-y += bsd/cbfs_private.c
smm-y += bsd/cbfs_private.c

+bootblock-y += bsd/cbfs_mcache.c
+verstage-y += bsd/cbfs_mcache.c
+romstage-y += bsd/cbfs_mcache.c
+postcar-y += bsd/cbfs_mcache.c
+ramstage-y += bsd/cbfs_mcache.c
+smm-y += bsd/cbfs_mcache.c
+
decompressor-y += bsd/lz4_wrapper.c
bootblock-y += bsd/lz4_wrapper.c
verstage-y += bsd/lz4_wrapper.c
diff --git a/src/commonlib/bsd/cbfs_mcache.c b/src/commonlib/bsd/cbfs_mcache.c
new file mode 100644
index 0000000..d97dcce
--- /dev/null
+++ b/src/commonlib/bsd/cbfs_mcache.c
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
+
+#include <commonlib/bsd/cbfs_private.h>
+
+#define MCACHE_TOKEN_MAGIC 0xd
+#define MCACHE_OFFSET_FULL 0
+#define MCACHE_OFFSET_END 1
+
+struct mcache_token {
+ uint32_t offset : 28;
+ uint32_t magic : 4;
+};
+
+struct cbfs_mcache_build_args {
+ void *mcache;
+ void *end;
+ size_t offset;
+ int count;
+};
+
+static void make_token(struct cbfs_mcache_build_args *args, size_t new_offset)
+{
+ struct mcache_token *token = args->mcache;
+
+ /* If there's no space for the token, lookup() will know the cache is full anyway. */
+ if (args->end - args->mcache < sizeof(*token))
+ return;
+
+ token->magic = MCACHE_TOKEN_MAGIC;
+ token->offset = new_offset;
+
+ args->mcache += sizeof(*token);
+}
+
+static cb_err_t build_walker(cbfs_dev_t dev, size_t offset, union cbfs_mdata *mdata,
+ bool do_hash, void *arg)
+{
+ struct cbfs_mcache_build_args *args = arg;
+ const uint32_t data_offset = be32toh(mdata->h.offset);
+ const uint32_t data_length = be32toh(mdata->h.len);
+
+ if (offset != args->offset)
+ make_token(args, offset);
+
+ if (args->end - args->mcache < data_offset) {
+ make_token(args, MCACHE_OFFSET_FULL);
+ return CB_CBFS_CACHE_FULL;
+ }
+
+ if (cbfs_copy_fill_metadata(args->mcache, mdata, dev, offset, do_hash) != CB_SUCCESS)
+ return CB_CBFS_IO;
+
+ args->mcache += data_offset;
+ args->offset = ALIGN_UP(offset + data_offset + data_length, CBFS_ALIGNMENT);
+ args->count++;
+
+ return CB_CBFS_NOT_FOUND;
+}
+
+cb_err_t cbfs_mcache_build(cbfs_dev_t dev, void *mcache, size_t size,
+ struct vb2_hash *master_hash)
+{
+ struct cbfs_mcache_build_args args = {
+ .mcache = mcache,
+ .end = mcache + size,
+ .offset = 0,
+ .count = 0,
+ };
+
+ cb_err_t ret = cbfs_walk(dev, build_walker, &args, master_hash, 0);
+ if (ret == CB_CBFS_CACHE_FULL)
+ ERROR("mcache overflow, should increase CBFS_MCACHE size!\n");
+ else if (ret != CB_CBFS_NOT_FOUND)
+ return ret;
+
+ make_token(&args, MCACHE_OFFSET_END);
+ LOG("mcache @%p built for %d files, used %#zx bytes\n",
+ mcache, args.count, args.mcache - mcache);
+ return CB_SUCCESS;
+}
+
+cb_err_t cbfs_mcache_lookup(cbfs_dev_t dev, void *mcache, size_t mcache_size, const char *name,
+ union cbfs_mdata *mdata_out, size_t *data_offset_out,
+ struct vb2_hash *master_hash)
+{
+ size_t namesize = strlen(name) + 1; /* Count trailing \0 so we can memcmp() it. */
+ void *end = mcache + mcache_size;
+ void *current = mcache;
+
+ size_t offset = 0;
+ while (end - current >= sizeof(struct mcache_token)) {
+ union cbfs_mdata *mdata = current;
+
+ if (memcmp(mdata->h.magic, CBFS_FILE_MAGIC, sizeof(mdata->h.magic)) != 0) {
+ struct mcache_token *token = current;
+ if (token->magic != MCACHE_TOKEN_MAGIC) {
+ ERROR("CBFS mcache corrupted at %p\n", token);
+ return CB_ERR;
+ }
+ if (token->offset == MCACHE_OFFSET_END)
+ return CB_CBFS_NOT_FOUND;
+ if (token->offset == MCACHE_OFFSET_FULL)
+ break;
+ offset = token->offset;
+ current += sizeof(*token);
+ continue;
+ }
+
+ const uint32_t data_offset = be32toh(mdata->h.offset);
+ const uint32_t data_length = be32toh(mdata->h.len);
+ if (namesize <= cbfs_filename_size(&mdata->h) &&
+ memcmp(name, mdata->filename, namesize) == 0) {
+ LOG("Found '%s' @%#zx size %#x in mcache @%p\n",
+ name, offset, data_length, current);
+ *data_offset_out = offset + data_offset;
+ memcpy(mdata_out, mdata, data_offset);
+ return CB_SUCCESS;
+ }
+
+ offset = ALIGN_UP(offset + data_offset + data_length, CBFS_ALIGNMENT);
+ current += data_offset;
+ }
+
+ return cbfs_lookup(dev, name, mdata_out, data_offset_out, master_hash);
+}
+
+size_t cbfs_mcache_real_size(void *mcache, size_t mcache_size)
+{
+ void *end = mcache + mcache_size;
+ void *current = mcache;
+
+ while (end - current >= sizeof(struct mcache_token)) {
+ union cbfs_mdata *mdata = current;
+
+ if (memcmp(mdata->h.magic, CBFS_FILE_MAGIC, sizeof(mdata->h.magic)) != 0) {
+ struct mcache_token *token = current;
+ current += sizeof(*token);
+ if (token->offset == MCACHE_OFFSET_END ||
+ token->offset == MCACHE_OFFSET_FULL)
+ break;
+ } else {
+ current += be32toh(mdata->h.offset);
+ }
+ }
+
+ return current - mcache;
+}
diff --git a/src/commonlib/bsd/include/commonlib/bsd/cb_err.h b/src/commonlib/bsd/include/commonlib/bsd/cb_err.h
index ab422e1..18aa4d7 100644
--- a/src/commonlib/bsd/include/commonlib/bsd/cb_err.h
+++ b/src/commonlib/bsd/include/commonlib/bsd/cb_err.h
@@ -39,6 +39,7 @@
CB_CBFS_IO = -400, /**< Underlying I/O error */
CB_CBFS_NOT_FOUND = -401, /**< File not found in directory */
CB_CBFS_HASH = -402, /**< Master hash validation failed */
+ CB_CBFS_CACHE_FULL = -403, /**< Metadata cache overflowed */
};

/* Don't typedef the enum directly, so the size is unambiguous for serialization. */
diff --git a/src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h b/src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h
index b4fc1c7..374a460 100644
--- a/src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h
+++ b/src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h
@@ -92,4 +92,22 @@
cb_err_t cbfs_lookup(cbfs_dev_t dev, const char *name, union cbfs_mdata *mdata_out,
size_t *data_offset_out, struct vb2_hash *master_hash);

+/* Build an in-memory CBFS metadata cache out of the CBFS on |dev| into a |mcache_size| bytes
+ * memory area at |mcache|. Also verify |master_hash| unless it is NULL. */
+cb_err_t cbfs_mcache_build(cbfs_dev_t dev, void *mcache, size_t mcache_size,
+ struct vb2_hash *master_hash);
+
+/*
+ * Find a file named |name| in a CBFS metadata cache and copy its metadata into |mdata_out|.
+ * Pass out offset to the file data (on the storage backend). May fall back to cbfs_lookup() if
+ * metadata cache was too small for CBFS. |dev| and |master_hash| must have the same values as
+ * originally passed to cbfs_mcache_build().
+ */
+cb_err_t cbfs_mcache_lookup(cbfs_dev_t dev, void *mcache, size_t mcache_size, const char *name,
+ union cbfs_mdata *mdata_out, size_t *data_offset_out,
+ struct vb2_hash *master_hash);
+
+/* Returns the amount of bytes actually used by the CBFS metadata cache in |mcache|. */
+size_t cbfs_mcache_real_size(void *mcache, size_t mcache_size);
+
#endif /* _COMMONLIB_BSD_CBFS_PRIVATE_H_ */
diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h
index b063cd1..8f4f7f3 100644
--- a/src/commonlib/include/commonlib/cbmem_id.h
+++ b/src/commonlib/include/commonlib/cbmem_id.h
@@ -79,6 +79,8 @@
#define CBMEM_ID_ROM2 0x524f4d32
#define CBMEM_ID_ROM3 0x524f4d33
#define CBMEM_ID_FMAP 0x464d4150
+#define CBMEM_ID_CBFS_RO_MCACHE 0x524d5346
+#define CBMEM_ID_CBFS_RW_MCACHE 0x574d5346
#define CBMEM_ID_FSP_LOGO 0x4c4f474f

#define CBMEM_ID_TO_NAME_TABLE \
@@ -141,5 +143,7 @@
{ CBMEM_ID_ROM1, "VGA ROM #1 "}, \
{ CBMEM_ID_ROM2, "VGA ROM #2 "}, \
{ CBMEM_ID_ROM3, "VGA ROM #3 "}, \
- { CBMEM_ID_FMAP, "FMAP "},
+ { CBMEM_ID_FMAP, "FMAP "}, \
+ { CBMEM_ID_CBFS_RO_MCACHE, "RO MCACHE "}, \
+ { CBMEM_ID_CBFS_RW_MCACHE, "RW MCACHE "}
#endif /* _CBMEM_ID_H_ */
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 2d16aa7..82c92d7 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -18,6 +18,7 @@

#include <commonlib/cbfs.h>
#include <program_loading.h>
+#include <types.h>

/***********************************************
* Perform CBFS operations on the boot device. *
@@ -59,8 +60,18 @@
/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
int cbfs_prog_stage_load(struct prog *prog);

-/* Returns the region device of the currently active CBFS.
- Return < 0 on error, 0 on success. */
-int cbfs_boot_region_device(struct region_device *rdev);
+struct cbfs_boot_device {
+ struct region_device rdev;
+ void *mcache;
+ size_t mcache_size;
+};
+
+/*
+ * Retrieves the currently active CBFS boot device. If |force_ro| is set, will
+ * always return the read-only CBFS instead (this only makes a difference when
+ * CONFIG_VBOOT is enabled). May perform certain CBFS initialization tasks.
+ * Returns NULL on error (e.g. boot device IO error).
+ */
+const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro);

#endif
diff --git a/src/include/memlayout.h b/src/include/memlayout.h
index e3aeec6..0d430dee 100644
--- a/src/include/memlayout.h
+++ b/src/include/memlayout.h
@@ -81,6 +81,9 @@
_ = ASSERT(sz >= FMAP_SIZE, \
STR(FMAP does not fit in FMAP_CACHE! (sz < FMAP_SIZE)));

+#define CBFS_MCACHE(addr, sz) \
+ REGION(cbfs_mcache, addr, sz, 8)
+
#if ENV_ROMSTAGE_OR_BEFORE
#define PRERAM_CBFS_CACHE(addr, size) \
REGION(preram_cbfs_cache, addr, size, 4) \
diff --git a/src/include/symbols.h b/src/include/symbols.h
index eec4701..a8e1a82 100644
--- a/src/include/symbols.h
+++ b/src/include/symbols.h
@@ -34,6 +34,7 @@
DECLARE_REGION(preram_cbfs_cache)
DECLARE_REGION(postram_cbfs_cache)
DECLARE_REGION(cbfs_cache)
+DECLARE_REGION(cbfs_mcache)
DECLARE_REGION(fmap_cache)
DECLARE_REGION(payload)

diff --git a/src/lib/Kconfig b/src/lib/Kconfig
index dd9974a..26bf0be 100644
--- a/src/lib/Kconfig
+++ b/src/lib/Kconfig
@@ -75,3 +75,24 @@
If your platform really doesn't want to use an FMAP cache (e.g. due to
space constraints), you can select this to disable warnings and save
a bit more code.
+
+config NO_CBFS_MCACHE
+ bool
+ default y
+ help
+ Disables the CBFS metadata cache. This means that your platform does
+ not need to provide a CBFS_MCACHE section in memlayout and can save
+ the associated CAR/SRAM size. In that case every single CBFS file
+ lookup must re-read the same CBFS directory entries from flash to find
+ the respective file.
+
+config CBFS_MCACHE_RW_PERCENTAGE
+ int
+ depends on VBOOT
+ default 25 if CHROMEOS # Chrome OS stores many L10n files in RO only
+ default 50
+ help
+ The amount of the CBFS_MCACHE area that's used for the RW CBFS, in
+ percent from 0 to 100. The remaining area will be used for the RO
+ CBFS. Default is an even 50/50 split. When VBOOT is disabled, this
+ will automatically be 0 (meaning the whole MCACHE is used for RO).
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index d6fb99c..40290fd 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -15,6 +15,7 @@
*/

#include <assert.h>
+#include <cbmem.h>
#include <console/console.h>
#include <string.h>
#include <stdlib.h>
@@ -30,30 +31,40 @@
#include <security/vboot/vboot_crtm.h>
#include <security/vboot/vboot_common.h>

+static cb_err_t cbfs_boot_lookup(const struct cbfs_boot_device *cbd,
+ const char *name, union cbfs_mdata *mdata, size_t *data_offset)
+{
+ if (CONFIG(NO_CBFS_MCACHE))
+ return cbfs_lookup(&cbd->rdev, name, mdata, data_offset, NULL);
+ else
+ return cbfs_mcache_lookup(&cbd->rdev,
+ cbd->mcache, cbd->mcache_size,
+ name, mdata, data_offset, NULL);
+}
+
int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
{
- struct region_device rdev;
-
- if (cbfs_boot_region_device(&rdev))
+ const struct cbfs_boot_device *cbd = cbfs_get_boot_device(false);
+ if (!cbd)
return -1;

union cbfs_mdata mdata;
size_t data_offset;
- cb_err_t err = cbfs_lookup(&rdev, name, &mdata, &data_offset, NULL);
+ cb_err_t err = cbfs_boot_lookup(cbd, name, &mdata, &data_offset);

if (CONFIG(VBOOT_ENABLE_CBFS_FALLBACK) && err == CB_CBFS_NOT_FOUND) {
printk(BIOS_INFO, "CBFS: Fall back to RO region for %s\n",
name);
- if (fmap_locate_area_as_rdev("COREBOOT", &rdev))
+ if (!(cbd = cbfs_get_boot_device(true)))
return -1;
- err = cbfs_lookup(&rdev, name, &mdata, &data_offset, NULL);
+ err = cbfs_boot_lookup(cbd, name, &mdata, &data_offset);
}
if (err)
return -1;

size_t msize = be32toh(mdata.h.offset);
- if (rdev_chain(&fh->metadata, &rdev, data_offset - msize, msize) ||
- rdev_chain(&fh->data, &rdev, data_offset, be32toh(mdata.h.len)))
+ if (rdev_chain(&fh->metadata, &cbd->rdev, data_offset - msize, msize) ||
+ rdev_chain(&fh->data, &cbd->rdev, data_offset, be32toh(mdata.h.len)))
return -1;
if (type) {
if (!*type)
@@ -280,9 +291,66 @@
return 0;
}

-int cbfs_boot_region_device(struct region_device *rdev)
+const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
{
+ static struct cbfs_boot_device ro;
+
+ if (!force_ro) {
+ const struct cbfs_boot_device *rw = vboot_get_cbfs_boot_device();
+ if (rw)
+ return rw;
+ }
+
+ if (region_device_sz(&ro.rdev))
+ return &ro;
+
+ if (!CONFIG(NO_CBFS_MCACHE)) {
+ const struct cbmem_entry *entry;
+ if (cbmem_possibly_online() &&
+ (entry = cbmem_entry_find(CBMEM_ID_CBFS_RO_MCACHE))) {
+ ro.mcache = cbmem_entry_start(entry);
+ ro.mcache_size = cbmem_entry_size(entry);
+ } else if (ENV_ROMSTAGE_OR_BEFORE) {
+ ro.mcache = _cbfs_mcache;
+ ro.mcache_size = REGION_SIZE(cbfs_mcache) *
+ (100 - CONFIG_CBFS_MCACHE_RW_PERCENTAGE) / 100;
+ }
+ }
+
boot_device_init();
- return vboot_locate_cbfs(rdev) &&
- fmap_locate_area_as_rdev("COREBOOT", rdev);
+ if (fmap_locate_area_as_rdev("COREBOOT", &ro.rdev))
+ return NULL;
+
+ if (!CONFIG(NO_CBFS_MCACHE) && ENV_BOOTBLOCK) {
+ static bool mcache_done = false;
+ if (!mcache_done && ro.mcache_size > 0 && cbfs_mcache_build(
+ &ro.rdev, ro.mcache, ro.mcache_size, NULL))
+ return NULL;
+ mcache_done = true;
+ }
+ return &ro;
}
+
+#if !CONFIG(NO_CBFS_MCACHE)
+static void mcache_to_cbmem(const struct cbfs_boot_device *cbd, u32 cbmem_id)
+{
+ if (!cbd)
+ return;
+
+ size_t real_size = cbfs_mcache_real_size(cbd->mcache, cbd->mcache_size);
+ void *cbmem_mcache = cbmem_add(cbmem_id, real_size);
+ if (!cbmem_mcache) {
+ printk(BIOS_ERR, "ERROR: Cannot allocate CBMEM mcache %#x (%#zx bytes)!\n",
+ cbmem_id, real_size);
+ return;
+ }
+ memcpy(cbmem_mcache, cbd->mcache, real_size);
+}
+
+static void cbfs_mcache_migrate(int unused)
+{
+ mcache_to_cbmem(vboot_get_cbfs_boot_device(), CBMEM_ID_CBFS_RW_MCACHE);
+ mcache_to_cbmem(cbfs_get_boot_device(true), CBMEM_ID_CBFS_RO_MCACHE);
+}
+ROMSTAGE_CBMEM_INIT_HOOK(cbfs_mcache_migrate)
+#endif
diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c
index e42cb3b..b46ca57 100644
--- a/src/lib/coreboot_table.c
+++ b/src/lib/coreboot_table.c
@@ -243,11 +243,8 @@
{
struct lb_boot_media_params *bmp;
const struct region_device *boot_dev;
- struct region_device cbfs_dev;
-
- boot_device_init();
-
- if (cbfs_boot_region_device(&cbfs_dev))
+ const struct cbfs_boot_device *cbd = cbfs_get_boot_device(false);
+ if (!cbd)
return;

boot_dev = boot_device_ro();
@@ -258,8 +255,8 @@
bmp->tag = LB_TAG_BOOT_MEDIA_PARAMS;
bmp->size = sizeof(*bmp);

- bmp->cbfs_offset = region_device_offset(&cbfs_dev);
- bmp->cbfs_size = region_device_sz(&cbfs_dev);
+ bmp->cbfs_offset = region_device_offset(&cbd->rdev);
+ bmp->cbfs_size = region_device_sz(&cbd->rdev);
bmp->boot_media_size = region_device_sz(boot_dev);

bmp->fmap_offset = get_fmap_flash_offset();
diff --git a/src/security/vboot/vboot_common.h b/src/security/vboot/vboot_common.h
index 976c26a..0ebefb6 100644
--- a/src/security/vboot/vboot_common.h
+++ b/src/security/vboot/vboot_common.h
@@ -16,6 +16,7 @@
#define __VBOOT_VBOOT_COMMON_H__

#include <commonlib/region.h>
+#include <cbfs.h>
#include <stdint.h>
#include <vboot_api.h>
#include <vboot_struct.h>
@@ -71,7 +72,7 @@
int vboot_recovery_mode_memory_retrain(void);
int vboot_can_enable_udc(void);
void vboot_run_logic(void);
-int vboot_locate_cbfs(struct region_device *rdev);
+const struct cbfs_boot_device *vboot_get_cbfs_boot_device(void);
#else /* !CONFIG_VBOOT */
static inline int vboot_developer_mode_enabled(void) { return 0; }
static inline int vboot_recovery_mode_enabled(void) { return 0; }
@@ -79,7 +80,7 @@
/* If VBOOT is not enabled, we are okay enabling USB device controller (UDC). */
static inline int vboot_can_enable_udc(void) { return 1; }
static inline void vboot_run_logic(void) {}
-static inline int vboot_locate_cbfs(struct region_device *rdev) { return -1; }
+const struct cbfs_boot_device *vboot_get_cbfs_boot_device(void) { return NULL; }
#endif

void vboot_save_nvdata_only(struct vb2_context *ctx);
diff --git a/src/security/vboot/vboot_loader.c b/src/security/vboot/vboot_loader.c
index 7e63775..a8db7a3 100644
--- a/src/security/vboot/vboot_loader.c
+++ b/src/security/vboot/vboot_loader.c
@@ -13,7 +13,10 @@
* GNU General Public License for more details.
*/

+#include <boot_device.h>
#include <cbfs.h>
+#include <cbmem.h>
+#include <commonlib/bsd/cbfs_private.h>
#include <console/console.h>
#include <ec/google/chromeec/ec.h>
#include <rmodule.h>
@@ -34,12 +37,26 @@

int vboot_executed;

+static void build_rw_mcache(void)
+{
+ if (CONFIG(NO_CBFS_MCACHE))
+ return;
+
+ if (vboot_get_context()->flags & VB2_CONTEXT_RECOVERY_MODE)
+ return; /* No RW mcache if we're staying in RO. */
+
+ const struct cbfs_boot_device *cbd = vboot_get_cbfs_boot_device();
+ if (cbfs_mcache_build(&cbd->rdev, cbd->mcache, cbd->mcache_size, NULL))
+ die("Failed to build RW mcache."); /* TODO: -> recovery? */
+}
+
void vboot_run_logic(void)
{
if (verification_should_run()) {
/* Note: this path is not used for VBOOT_RETURN_FROM_VERSTAGE */
verstage_main();
vboot_executed = 1;
+ build_rw_mcache();
} else if (verstage_should_load()) {
struct cbfsf file;
struct prog verstage =
@@ -67,21 +84,40 @@
return;

vboot_executed = 1;
+ build_rw_mcache();
}
}

-int vboot_locate_cbfs(struct region_device *rdev)
+const struct cbfs_boot_device *vboot_get_cbfs_boot_device(void)
{
- struct vb2_context *ctx;
-
/* Don't honor vboot results until the vboot logic has run. */
if (!vboot_logic_executed())
- return -1;
+ return NULL;

- ctx = vboot_get_context();
+ static struct cbfs_boot_device cbd;
+ if (region_device_sz(&cbd.rdev))
+ return &cbd;

+ struct vb2_context *ctx = vboot_get_context();
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
- return -1;
+ return NULL;

- return vboot_locate_firmware(ctx, rdev);
+ boot_device_init();
+ if (vboot_locate_firmware(ctx, &cbd.rdev))
+ return NULL;
+
+ if (!CONFIG(NO_CBFS_MCACHE)) {
+ const struct cbmem_entry *entry;
+ if (cbmem_possibly_online() &&
+ (entry = cbmem_entry_find(CBMEM_ID_CBFS_RW_MCACHE))) {
+ cbd.mcache = cbmem_entry_start(entry);
+ cbd.mcache_size = cbmem_entry_size(entry);
+ } else if (ENV_ROMSTAGE_OR_BEFORE) {
+ cbd.mcache_size = REGION_SIZE(cbfs_mcache) *
+ CONFIG_CBFS_MCACHE_RW_PERCENTAGE / 100;
+ cbd.mcache = _ecbfs_mcache - cbd.mcache_size;
+ }
+ }
+
+ return &cbd;
}

To view, visit change 38423. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I5b1084bfdad1c6ab0ee1b143ed8dd796827f4c65
Gerrit-Change-Number: 38423
Gerrit-PatchSet: 1
Gerrit-Owner: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Aaron Durbin <adurbin@chromium.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange