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
|
romstage-y += mem_pool.c
|
||||||
ramstage-y += mem_pool.c
|
ramstage-y += mem_pool.c
|
||||||
postcar-y += mem_pool.c
|
postcar-y += mem_pool.c
|
||||||
|
smm-y += mem_pool.c
|
||||||
|
|
||||||
bootblock-y += iobuf.c
|
bootblock-y += iobuf.c
|
||||||
verstage-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) \
|
MEM_REGION_DEV_INIT(base_, size_, &mem_rdev_rw_ops) \
|
||||||
|
|
||||||
struct mmap_helper_region_device {
|
struct mmap_helper_region_device {
|
||||||
struct mem_pool pool;
|
struct mem_pool *pool;
|
||||||
struct region_device rdev;
|
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_)), \
|
.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);
|
void *mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t);
|
||||||
int mmap_helper_rdev_munmap(const struct region_device *, void *);
|
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,
|
.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,
|
void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset,
|
||||||
size_t size)
|
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);
|
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)
|
if (mapping == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (rd->ops->readat(rd, mapping, offset, size) != size) {
|
if (rd->ops->readat(rd, mapping, offset, size) != size) {
|
||||||
mem_pool_free(&mdev->pool, mapping);
|
mem_pool_free(mdev->pool, mapping);
|
||||||
return NULL;
|
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);
|
mdev = container_of((void *)rd, __typeof__(*mdev), rdev);
|
||||||
|
|
||||||
mem_pool_free(&mdev->pool, mapping);
|
mem_pool_free(mdev->pool, mapping);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boot_device.h>
|
#include <boot_device.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <spi_flash.h>
|
#include <spi_flash.h>
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
|
@ -77,21 +78,7 @@ static const struct region_device_ops spi_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mmap_helper_region_device mdev =
|
static struct mmap_helper_region_device mdev =
|
||||||
MMAP_HELPER_REGION_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
|
MMAP_HELPER_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, &cbfs_cache);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
void boot_device_init(void)
|
void boot_device_init(void)
|
||||||
{
|
{
|
||||||
|
@ -105,8 +92,6 @@ void boot_device_init(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spi_flash_init_done = true;
|
spi_flash_init_done = true;
|
||||||
|
|
||||||
mmap_helper_device_init(&mdev, _cbfs_cache, REGION_SIZE(cbfs_cache));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the CBFS boot device. */
|
/* Return the CBFS boot device. */
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
#include <commonlib/cbfs.h>
|
#include <commonlib/cbfs.h>
|
||||||
|
#include <commonlib/mem_pool.h>
|
||||||
#include <program_loading.h>
|
#include <program_loading.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <vb2_sha.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
|
/* 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. */
|
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.
|
/* 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. */
|
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. */
|
/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
|
||||||
int cbfs_prog_stage_load(struct prog *prog);
|
int cbfs_prog_stage_load(struct prog *prog);
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
* BOOT DEVICE HELPER APIs *
|
* 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
|
* 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
|
* 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 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);
|
size_t in_size, void *buffer, size_t buffer_size, uint32_t compression);
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
* INTERNAL HELPERS FOR INLINES, DO NOT USE. *
|
* INTERNAL HELPERS FOR INLINES, DO NOT USE. *
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
|
@ -32,9 +32,9 @@ DECLARE_OPTIONAL_REGION(timestamp)
|
||||||
DECLARE_REGION(preram_cbmem_console)
|
DECLARE_REGION(preram_cbmem_console)
|
||||||
DECLARE_REGION(cbmem_init_hooks)
|
DECLARE_REGION(cbmem_init_hooks)
|
||||||
DECLARE_REGION(stack)
|
DECLARE_REGION(stack)
|
||||||
DECLARE_REGION(preram_cbfs_cache)
|
DECLARE_OPTIONAL_REGION(preram_cbfs_cache)
|
||||||
DECLARE_REGION(postram_cbfs_cache)
|
DECLARE_OPTIONAL_REGION(postram_cbfs_cache)
|
||||||
DECLARE_REGION(cbfs_cache)
|
DECLARE_OPTIONAL_REGION(cbfs_cache)
|
||||||
DECLARE_REGION(cbfs_mcache)
|
DECLARE_REGION(cbfs_mcache)
|
||||||
DECLARE_REGION(fmap_cache)
|
DECLARE_REGION(fmap_cache)
|
||||||
DECLARE_REGION(tpm_tcpa_log)
|
DECLARE_REGION(tpm_tcpa_log)
|
||||||
|
|
|
@ -18,6 +18,18 @@
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
#include <timestamp.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,
|
cb_err_t cbfs_boot_lookup(const char *name, bool force_ro,
|
||||||
union cbfs_mdata *mdata, struct region_device *rdev)
|
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)
|
if (size_out != NULL)
|
||||||
*size_out = region_device_sz(&rdev);
|
*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. */
|
* This is save to call with mappings that weren't allocated in the cache (e.g. x86
|
||||||
return rdev_munmap(boot_device_ro(), mapping);
|
* 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,
|
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))
|
if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (ENV_SMM)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +223,8 @@ static inline bool cbfs_lzma_enabled(void)
|
||||||
return false;
|
return false;
|
||||||
if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE))
|
if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE))
|
||||||
return false;
|
return false;
|
||||||
|
if (ENV_SMM)
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
#include <boot_device.h>
|
#include <boot_device.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <symbols.h>
|
#include <symbols.h>
|
||||||
#include <device/mmio.h>
|
#include <device/mmio.h>
|
||||||
#include <soc/addressmap.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 =
|
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)
|
const struct region_device *boot_device_ro(void)
|
||||||
{
|
{
|
||||||
|
@ -79,8 +80,6 @@ void boot_device_init(void)
|
||||||
}
|
}
|
||||||
if (MSEL_SPI2SD(m)) {
|
if (MSEL_SPI2SD(m)) {
|
||||||
spi_sdcard_init(&card, 2, 0);
|
spi_sdcard_init(&card, 2, 0);
|
||||||
mmap_helper_device_init(&sd_mdev,
|
|
||||||
_cbfs_cache, REGION_SIZE(cbfs_cache));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
die("Wrong configuration of MSEL\n");
|
die("Wrong configuration of MSEL\n");
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <device/mmio.h>
|
#include <device/mmio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <boot_device.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <commonlib/region.h>
|
#include <commonlib/region.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <soc/clk.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 =
|
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)
|
void exynos_init_spi_boot_device(void)
|
||||||
{
|
{
|
||||||
boot_slave_regs = (void *)EXYNOS5_SPI1_BASE;
|
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)
|
const struct region_device *exynos_spi_boot_device(void)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <device/mmio.h>
|
#include <device/mmio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <cbfs.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <soc/cpu.h>
|
#include <soc/cpu.h>
|
||||||
#include <soc/spi.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 =
|
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)
|
void exynos_init_spi_boot_device(void)
|
||||||
{
|
{
|
||||||
boot_slave = &exynos_spi_slaves[1];
|
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)
|
const struct region_device *exynos_spi_boot_device(void)
|
||||||
|
|
Loading…
Reference in New Issue