aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Kconfig21
-rw-r--r--src/lib/cbfs.c112
-rw-r--r--src/lib/coreboot_table.c11
3 files changed, 126 insertions, 18 deletions
diff --git a/src/lib/Kconfig b/src/lib/Kconfig
index d6e7e51d5c..ab2b9c59b9 100644
--- a/src/lib/Kconfig
+++ b/src/lib/Kconfig
@@ -80,3 +80,24 @@ config ESPI_DEBUG
help
This option enables eSPI library helper functions for displaying debug
information.
+
+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 && !NO_CBFS_MCACHE
+ 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 447d91f1be..3b7d4292d0 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <boot_device.h>
#include <cbfs.h>
+#include <cbmem.h>
#include <commonlib/bsd/cbfs_private.h>
#include <commonlib/bsd/compression.h>
#include <commonlib/endian.h>
@@ -16,22 +17,33 @@
#include <symbols.h>
#include <timestamp.h>
-int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
+static cb_err_t cbfs_boot_lookup(const struct cbfs_boot_device *cbd,
+ const char *name, union cbfs_mdata *mdata, size_t *data_offset)
{
- struct region_device rdev;
+ cb_err_t err = CB_CBFS_CACHE_FULL;
+ if (!CONFIG(NO_CBFS_MCACHE) && !ENV_SMM)
+ err = cbfs_mcache_lookup(cbd->mcache, cbd->mcache_size,
+ name, mdata, data_offset);
+ if (err == CB_CBFS_CACHE_FULL)
+ err = cbfs_lookup(&cbd->rdev, name, mdata, data_offset, NULL);
+ return err;
+}
- if (cbfs_boot_region_device(&rdev))
+int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
+{
+ const struct cbfs_boot_device *cbd = cbfs_get_boot_device(false);
+ if (!cbd)
return -1;
size_t data_offset;
- cb_err_t err = cbfs_lookup(&rdev, name, &fh->mdata, &data_offset, NULL);
+ cb_err_t err = cbfs_boot_lookup(cbd, name, &fh->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, &fh->mdata, &data_offset, NULL);
+ err = cbfs_boot_lookup(cbd, name, &fh->mdata, &data_offset);
}
if (err)
return -1;
@@ -39,7 +51,8 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
size_t msize = be32toh(fh->mdata.h.offset);
if (rdev_chain(&fh->metadata, &addrspace_32bit.rdev,
(uintptr_t)&fh->mdata, msize) ||
- rdev_chain(&fh->data, &rdev, data_offset, be32toh(fh->mdata.h.len)))
+ rdev_chain(&fh->data, &cbd->rdev, data_offset,
+ be32toh(fh->mdata.h.len)))
return -1;
if (type) {
if (!*type)
@@ -333,9 +346,86 @@ out:
return 0;
}
-int cbfs_boot_region_device(struct region_device *rdev)
+void cbfs_boot_device_find_mcache(struct cbfs_boot_device *cbd, uint32_t id)
+{
+ if (CONFIG(NO_CBFS_MCACHE) || ENV_SMM)
+ return;
+
+ const struct cbmem_entry *entry;
+ if (cbmem_possibly_online() &&
+ (entry = cbmem_entry_find(id))) {
+ cbd->mcache = cbmem_entry_start(entry);
+ cbd->mcache_size = cbmem_entry_size(entry);
+ } else if (ENV_ROMSTAGE_OR_BEFORE) {
+ u8 *boundary = _ecbfs_mcache - REGION_SIZE(cbfs_mcache) *
+ CONFIG_CBFS_MCACHE_RW_PERCENTAGE / 100;
+ boundary = (u8 *)ALIGN_DOWN((uintptr_t)boundary,
+ CBFS_MCACHE_ALIGNMENT);
+ if (id == CBMEM_ID_CBFS_RO_MCACHE) {
+ cbd->mcache = _cbfs_mcache;
+ cbd->mcache_size = boundary - _cbfs_mcache;
+ } else if (id == CBMEM_ID_CBFS_RW_MCACHE) {
+ cbd->mcache = boundary;
+ cbd->mcache_size = _ecbfs_mcache - boundary;
+ }
+ }
+}
+
+const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
+{
+ static struct cbfs_boot_device ro;
+
+ /* Ensure we always init RO mcache, even if first file is from RW.
+ Otherwise it may not be available when needed in later stages. */
+ if (ENV_INITIAL_STAGE && !force_ro && !region_device_sz(&ro.rdev))
+ cbfs_get_boot_device(true);
+
+ if (!force_ro) {
+ const struct cbfs_boot_device *rw = vboot_get_cbfs_boot_device();
+ /* This will return NULL if vboot isn't enabled, didn't run yet
+ or decided to boot into recovery mode. */
+ if (rw)
+ return rw;
+ }
+
+ if (region_device_sz(&ro.rdev))
+ return &ro;
+
+ if (fmap_locate_area_as_rdev("COREBOOT", &ro.rdev))
+ return NULL;
+
+ cbfs_boot_device_find_mcache(&ro, CBMEM_ID_CBFS_RO_MCACHE);
+
+ if (ENV_INITIAL_STAGE && !CONFIG(NO_CBFS_MCACHE)) {
+ cb_err_t err = cbfs_mcache_build(&ro.rdev, ro.mcache,
+ ro.mcache_size, NULL);
+ if (err && err != CB_CBFS_CACHE_FULL)
+ die("Failed to build RO mcache");
+ }
+
+ 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)
{
- boot_device_init();
- return vboot_locate_cbfs(rdev) &&
- fmap_locate_area_as_rdev("COREBOOT", rdev);
+ 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 69ded3c700..4cbf3c742e 100644
--- a/src/lib/coreboot_table.c
+++ b/src/lib/coreboot_table.c
@@ -220,11 +220,8 @@ static void lb_boot_media_params(struct lb_header *header)
{
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();
@@ -235,8 +232,8 @@ static void lb_boot_media_params(struct lb_header *header)
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();