diff options
author | Julius Werner <jwerner@chromium.org> | 2020-12-30 17:30:12 -0800 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2021-03-08 22:31:29 +0000 |
commit | 9b1f3cc6fb129789f1dd28160a83a1ea59dd123a (patch) | |
tree | 98347b2285d361fbcaa74892fa75a40a629d4b7f /src | |
parent | 11075fc80e00186cb5b488e8e0fd280cd4e97823 (diff) |
cbfs: Pull handling of the CBFS_CACHE mem_pool into CBFS core
This patch pulls control of the memory pool serving allocations from the
CBFS_CACHE memlayout area into cbfs.c and makes it a core part of the
CBFS API. Previously, platforms would independently instantiate this as
part of boot_device_ro() (mostly through cbfs_spi.c). The new cbfs_cache
pool is exported as a global so these platforms can still use it to
directly back rdev_mmap() on their boot device, but the cbfs_cache can
now also use it to directly make allocations itself. This is used to
allow transparent decompression support in cbfs_map().
Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: I0d52b6a8f582a81a19fd0fd663bb89eab55a49d9
Reviewed-on: https://review.coreboot.org/c/coreboot/+/49333
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/commonlib/Makefile.inc | 1 | ||||
-rw-r--r-- | src/commonlib/include/commonlib/region.h | 8 | ||||
-rw-r--r-- | src/commonlib/region.c | 12 | ||||
-rw-r--r-- | src/drivers/spi/cbfs_spi.c | 19 | ||||
-rw-r--r-- | src/include/cbfs.h | 15 | ||||
-rw-r--r-- | src/include/symbols.h | 6 | ||||
-rw-r--r-- | src/lib/cbfs.c | 61 | ||||
-rw-r--r-- | src/mainboard/sifive/hifive-unleashed/media.c | 5 | ||||
-rw-r--r-- | src/soc/samsung/exynos5250/spi.c | 6 | ||||
-rw-r--r-- | src/soc/samsung/exynos5420/spi.c | 5 |
10 files changed, 89 insertions, 49 deletions
diff --git a/src/commonlib/Makefile.inc b/src/commonlib/Makefile.inc index 1a38e4a89f..c5fa8ed85e 100644 --- a/src/commonlib/Makefile.inc +++ b/src/commonlib/Makefile.inc @@ -5,6 +5,7 @@ verstage-y += mem_pool.c romstage-y += mem_pool.c ramstage-y += mem_pool.c postcar-y += mem_pool.c +smm-y += mem_pool.c bootblock-y += iobuf.c verstage-y += iobuf.c diff --git a/src/commonlib/include/commonlib/region.h b/src/commonlib/include/commonlib/region.h index 4d095b731d..0080c441a5 100644 --- a/src/commonlib/include/commonlib/region.h +++ b/src/commonlib/include/commonlib/region.h @@ -196,18 +196,16 @@ extern const struct region_device_ops mem_rdev_rw_ops; MEM_REGION_DEV_INIT(base_, size_, &mem_rdev_rw_ops) \ struct mmap_helper_region_device { - struct mem_pool pool; + struct mem_pool *pool; struct region_device rdev; }; -#define MMAP_HELPER_REGION_INIT(ops_, offset_, size_) \ +#define MMAP_HELPER_DEV_INIT(ops_, offset_, size_, mpool_) \ { \ .rdev = REGION_DEV_INIT((ops_), (offset_), (size_)), \ + .pool = (mpool_), \ } -void mmap_helper_device_init(struct mmap_helper_region_device *mdev, - void *cache, size_t cache_size); - void *mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t); int mmap_helper_rdev_munmap(const struct region_device *, void *); diff --git a/src/commonlib/region.c b/src/commonlib/region.c index a10702a6c5..55c0679033 100644 --- a/src/commonlib/region.c +++ b/src/commonlib/region.c @@ -287,12 +287,6 @@ const struct region_device_ops mem_rdev_rw_ops = { .eraseat = mdev_eraseat, }; -void mmap_helper_device_init(struct mmap_helper_region_device *mdev, - void *cache, size_t cache_size) -{ - mem_pool_init(&mdev->pool, cache, cache_size); -} - void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset, size_t size) { @@ -301,13 +295,13 @@ void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset, mdev = container_of((void *)rd, __typeof__(*mdev), rdev); - mapping = mem_pool_alloc(&mdev->pool, size); + mapping = mem_pool_alloc(mdev->pool, size); if (mapping == NULL) return NULL; if (rd->ops->readat(rd, mapping, offset, size) != size) { - mem_pool_free(&mdev->pool, mapping); + mem_pool_free(mdev->pool, mapping); return NULL; } @@ -320,7 +314,7 @@ int mmap_helper_rdev_munmap(const struct region_device *rd, void *mapping) mdev = container_of((void *)rd, __typeof__(*mdev), rdev); - mem_pool_free(&mdev->pool, mapping); + mem_pool_free(mdev->pool, mapping); return 0; } diff --git a/src/drivers/spi/cbfs_spi.c b/src/drivers/spi/cbfs_spi.c index 0034460b98..7e648a34ce 100644 --- a/src/drivers/spi/cbfs_spi.c +++ b/src/drivers/spi/cbfs_spi.c @@ -7,6 +7,7 @@ */ #include <boot_device.h> +#include <cbfs.h> #include <console/console.h> #include <spi_flash.h> #include <symbols.h> @@ -77,21 +78,7 @@ static const struct region_device_ops spi_ops = { }; static struct mmap_helper_region_device mdev = - MMAP_HELPER_REGION_INIT(&spi_ops, 0, CONFIG_ROM_SIZE); - -static void switch_to_postram_cache(int unused) -{ - /* - * Call boot_device_init() to ensure spi_flash is initialized before - * backing mdev with postram cache. This prevents the mdev backing from - * being overwritten if spi_flash was not accessed before dram was up. - */ - boot_device_init(); - if (_preram_cbfs_cache != _postram_cbfs_cache) - mmap_helper_device_init(&mdev, _postram_cbfs_cache, - REGION_SIZE(postram_cbfs_cache)); -} -ROMSTAGE_CBMEM_INIT_HOOK(switch_to_postram_cache); + MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache); void boot_device_init(void) { @@ -105,8 +92,6 @@ void boot_device_init(void) return; spi_flash_init_done = true; - - mmap_helper_device_init(&mdev, _cbfs_cache, REGION_SIZE(cbfs_cache)); } /* Return the CBFS boot device. */ diff --git a/src/include/cbfs.h b/src/include/cbfs.h index e08af56399..426757d3f5 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -5,6 +5,7 @@ #include <cbmem.h> #include <commonlib/cbfs.h> +#include <commonlib/mem_pool.h> #include <program_loading.h> #include <types.h> #include <vb2_sha.h> @@ -26,7 +27,7 @@ static inline void *cbfs_ro_map(const char *name, size_t *size_out); /* Removes a previously allocated CBFS mapping. Should try to unmap mappings in strict LIFO order where possible, since mapping backends often don't support more complicated cases. */ -int cbfs_unmap(void *mapping); +void cbfs_unmap(void *mapping); /* Load a file from CBFS into a buffer. Returns amount of loaded bytes on success or 0 on error. File will get decompressed as necessary. */ @@ -38,11 +39,22 @@ static inline size_t cbfs_ro_load(const char *name, void *buf, size_t buf_size); /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ int cbfs_prog_stage_load(struct prog *prog); + /********************************************************************************************** * BOOT DEVICE HELPER APIs * **********************************************************************************************/ /* + * The shared memory pool for backing mapped CBFS files, and other CBFS allocation needs. + * On x86 platforms, this would only be needed to transparently map compressed files, but it + * would require a permanent CBMEM carveout to be safe to use during S3 resume. Since it's not + * clear whether this feature is necessary or worth the wasted memory, it is currently disabled + * but could be added behind a Kconfig later if desired. + */ +#define CBFS_CACHE_AVAILABLE (!CONFIG(ARCH_X86)) +extern struct mem_pool cbfs_cache; + +/* * Data structure that represents "a" CBFS boot device, with optional metadata cache. Generally * we only have one of these, or two (RO and RW) when CONFIG(VBOOT) is set. The region device * stored here must always be a subregion of boot_device_ro(). @@ -95,6 +107,7 @@ void *cbfs_boot_map_optionrom_revision(uint16_t vendor, uint16_t device, uint8_t size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, size_t in_size, void *buffer, size_t buffer_size, uint32_t compression); + /********************************************************************************************** * INTERNAL HELPERS FOR INLINES, DO NOT USE. * **********************************************************************************************/ diff --git a/src/include/symbols.h b/src/include/symbols.h index fe449d9b4f..3e4694b90d 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -32,9 +32,9 @@ DECLARE_OPTIONAL_REGION(timestamp) DECLARE_REGION(preram_cbmem_console) DECLARE_REGION(cbmem_init_hooks) DECLARE_REGION(stack) -DECLARE_REGION(preram_cbfs_cache) -DECLARE_REGION(postram_cbfs_cache) -DECLARE_REGION(cbfs_cache) +DECLARE_OPTIONAL_REGION(preram_cbfs_cache) +DECLARE_OPTIONAL_REGION(postram_cbfs_cache) +DECLARE_OPTIONAL_REGION(cbfs_cache) DECLARE_REGION(cbfs_mcache) DECLARE_REGION(fmap_cache) DECLARE_REGION(tpm_tcpa_log) diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index fa6c2e3021..93dbb681aa 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -18,6 +18,18 @@ #include <symbols.h> #include <timestamp.h> +#if CBFS_CACHE_AVAILABLE +struct mem_pool cbfs_cache = MEM_POOL_INIT(_cbfs_cache, REGION_SIZE(cbfs_cache)); + +static void switch_to_postram_cache(int unused) +{ + if (_preram_cbfs_cache != _postram_cbfs_cache) + mem_pool_init(&cbfs_cache, _postram_cbfs_cache, + REGION_SIZE(postram_cbfs_cache)); +} +ROMSTAGE_CBMEM_INIT_HOOK(switch_to_postram_cache); +#endif + cb_err_t cbfs_boot_lookup(const char *name, bool force_ro, union cbfs_mdata *mdata, struct region_device *rdev) { @@ -101,14 +113,48 @@ void *_cbfs_map(const char *name, size_t *size_out, bool force_ro) if (size_out != NULL) *size_out = region_device_sz(&rdev); - return rdev_mmap_full(&rdev); + uint32_t compression = CBFS_COMPRESS_NONE; + const struct cbfs_file_attr_compression *attr = cbfs_find_attr(&mdata, + CBFS_FILE_ATTR_TAG_COMPRESSION, sizeof(*attr)); + if (attr) + compression = be32toh(attr->compression); + + if (compression == CBFS_COMPRESS_NONE) + return rdev_mmap_full(&rdev); + + if (!CBFS_CACHE_AVAILABLE) { + ERROR("Cannot map compressed file %s on x86\n", mdata.h.filename); + return NULL; + } + + size_t size = be32toh(attr->decompressed_size); + void *buf = mem_pool_alloc(&cbfs_cache, size); + if (!buf) { + ERROR("CBFS cache out of memory when mapping %s\n", mdata.h.filename); + return NULL; + } + + size = cbfs_load_and_decompress(&rdev, 0, region_device_sz(&rdev), buf, size, + compression); + if (!size) + return NULL; + + if (size_out != NULL) + *size_out = size; + return buf; } -int cbfs_unmap(void *mapping) +void cbfs_unmap(void *mapping) { - /* This works because munmap() only works on the root rdev and never cares about which - chained subregion something was mapped from. */ - return rdev_munmap(boot_device_ro(), mapping); + /* + * This is save to call with mappings that weren't allocated in the cache (e.g. x86 + * direct mappings) -- mem_pool_free() just does nothing for addresses it doesn't + * recognize. This hardcodes the assumption that if platforms implement an rdev_mmap() + * that requires a free() for the boot_device, they need to implement it via the + * cbfs_cache mem_pool. + */ + if (CBFS_CACHE_AVAILABLE) + mem_pool_free(&cbfs_cache, mapping); } int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, @@ -158,6 +204,9 @@ static inline bool cbfs_lz4_enabled(void) if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES)) return false; + if (ENV_SMM) + return false; + return true; } @@ -174,6 +223,8 @@ static inline bool cbfs_lzma_enabled(void) return false; if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE)) return false; + if (ENV_SMM) + return false; return true; } diff --git a/src/mainboard/sifive/hifive-unleashed/media.c b/src/mainboard/sifive/hifive-unleashed/media.c index 2ff375ae29..f3dcf7f621 100644 --- a/src/mainboard/sifive/hifive-unleashed/media.c +++ b/src/mainboard/sifive/hifive-unleashed/media.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include <boot_device.h> +#include <cbfs.h> #include <symbols.h> #include <device/mmio.h> #include <soc/addressmap.h> @@ -42,7 +43,7 @@ static const struct region_device_ops unleashed_sd_ops = { }; static struct mmap_helper_region_device sd_mdev = - MMAP_HELPER_REGION_INIT(&unleashed_sd_ops, 0, CONFIG_ROM_SIZE); + MMAP_HELPER_DEV_INIT(&unleashed_sd_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache); const struct region_device *boot_device_ro(void) { @@ -79,8 +80,6 @@ void boot_device_init(void) } if (MSEL_SPI2SD(m)) { spi_sdcard_init(&card, 2, 0); - mmap_helper_device_init(&sd_mdev, - _cbfs_cache, REGION_SIZE(cbfs_cache)); return; } die("Wrong configuration of MSEL\n"); diff --git a/src/soc/samsung/exynos5250/spi.c b/src/soc/samsung/exynos5250/spi.c index e630090852..c7e07071c0 100644 --- a/src/soc/samsung/exynos5250/spi.c +++ b/src/soc/samsung/exynos5250/spi.c @@ -2,6 +2,8 @@ #include <device/mmio.h> #include <assert.h> +#include <boot_device.h> +#include <cbfs.h> #include <commonlib/region.h> #include <console/console.h> #include <soc/clk.h> @@ -160,13 +162,11 @@ static const struct region_device_ops exynos_spi_ops = { }; static struct mmap_helper_region_device mdev = - MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE); + MMAP_HELPER_DEV_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache); void exynos_init_spi_boot_device(void) { boot_slave_regs = (void *)EXYNOS5_SPI1_BASE; - - mmap_helper_device_init(&mdev, _cbfs_cache, REGION_SIZE(cbfs_cache)); } const struct region_device *exynos_spi_boot_device(void) diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c index 0a2f0275ac..2fe9d5cf18 100644 --- a/src/soc/samsung/exynos5420/spi.c +++ b/src/soc/samsung/exynos5420/spi.c @@ -2,6 +2,7 @@ #include <device/mmio.h> #include <assert.h> +#include <cbfs.h> #include <console/console.h> #include <soc/cpu.h> #include <soc/spi.h> @@ -268,13 +269,11 @@ static const struct region_device_ops exynos_spi_ops = { }; static struct mmap_helper_region_device mdev = - MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE); + MMAP_HELPER_DEV_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache); void exynos_init_spi_boot_device(void) { boot_slave = &exynos_spi_slaves[1]; - - mmap_helper_device_init(&mdev, _cbfs_cache, REGION_SIZE(cbfs_cache)); } const struct region_device *exynos_spi_boot_device(void) |