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>
This commit is contained in:
parent
11075fc80e
commit
9b1f3cc6fb
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,10 +39,21 @@ 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
|
||||
|
@ -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. *
|
||||
**********************************************************************************************/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue