drivers/intel/fsp2_0: add option to compress FSP-M in cbfs
Allow the ability for chipset or mainboard to choose to compress FSP-M in cbfs using LZMA or LZ4 routines. However, only non-XIP platforms will support FSP-M compression. Since the main cbfs decompression paths are utilized add the appropriate checks for including compression algorithms under the FSP-M compression options. On picasso FSP-M (debug builds) the following savings were measured: no-compression: fspm.bin 720896 none FSP_COMPRESS_FSP_M_LZ4: fspm.bin 138379 LZ4 (720896 decompressed) -80% FSP_COMPRESS_FSP_M_LZMA: fspm.bin 98921 LZMA (720896 decompressed) -86% BUG=b:155322763,b:150746858,b:152909132 Change-Id: I5c88510c134b56a36ff1cd97a64b51ab2fea0ab0 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41450 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
parent
7729b29a58
commit
ecbfa99f64
|
@ -187,6 +187,19 @@ config FSP_COMPRESS_FSP_S_LZMA
|
||||||
config FSP_COMPRESS_FSP_S_LZ4
|
config FSP_COMPRESS_FSP_S_LZ4
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config FSP_COMPRESS_FSP_M_LZMA
|
||||||
|
bool
|
||||||
|
depends on !FSP_M_XIP
|
||||||
|
|
||||||
|
config FSP_COMPRESS_FSP_M_LZ4
|
||||||
|
bool
|
||||||
|
depends on !FSP_M_XIP
|
||||||
|
|
||||||
|
config FSP_M_ADDR
|
||||||
|
hex
|
||||||
|
help
|
||||||
|
The address FSP-M will be relocated to during build time
|
||||||
|
|
||||||
if FSP_PEIM_TO_PEIM_INTERFACE
|
if FSP_PEIM_TO_PEIM_INTERFACE
|
||||||
source "src/drivers/intel/fsp2_0/ppi/Kconfig"
|
source "src/drivers/intel/fsp2_0/ppi/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -52,6 +52,12 @@ $(FSP_M_CBFS)-type := fsp
|
||||||
ifeq ($(CONFIG_FSP_M_XIP),y)
|
ifeq ($(CONFIG_FSP_M_XIP),y)
|
||||||
$(FSP_M_CBFS)-options := --xip $(TXTIBB)
|
$(FSP_M_CBFS)-options := --xip $(TXTIBB)
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(CONFIG_FSP_COMPRESS_FSP_M_LZMA),y)
|
||||||
|
$(FSP_M_CBFS)-compression := LZMA
|
||||||
|
endif
|
||||||
|
ifeq ($(CONFIG_FSP_COMPRESS_FSP_M_LZ4),y)
|
||||||
|
$(FSP_M_CBFS)-compression := LZ4
|
||||||
|
endif
|
||||||
|
|
||||||
cbfs-files-$(CONFIG_ADD_FSP_BINARIES) += $(FSP_S_CBFS)
|
cbfs-files-$(CONFIG_ADD_FSP_BINARIES) += $(FSP_S_CBFS)
|
||||||
$(FSP_S_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_S_FILE))
|
$(FSP_S_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_S_FILE))
|
||||||
|
|
|
@ -89,6 +89,8 @@ struct fsp_load_descriptor {
|
||||||
int (*get_destination)(const struct fsp_load_descriptor *fspld,
|
int (*get_destination)(const struct fsp_load_descriptor *fspld,
|
||||||
void **dest, size_t final_load_size,
|
void **dest, size_t final_load_size,
|
||||||
const struct region_device *source);
|
const struct region_device *source);
|
||||||
|
/* Optional argument to be utilized by get_destination() callback. */
|
||||||
|
void *arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP
|
/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP
|
||||||
|
|
|
@ -254,14 +254,20 @@ static uint32_t fsp_memory_settings_version(const struct fsp_header *hdr)
|
||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake,
|
struct fspm_context {
|
||||||
const struct memranges *memmap)
|
struct fsp_header header;
|
||||||
|
struct memranges memmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)
|
||||||
{
|
{
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
fsp_memory_init_fn fsp_raminit;
|
fsp_memory_init_fn fsp_raminit;
|
||||||
FSPM_UPD fspm_upd, *upd;
|
FSPM_UPD fspm_upd, *upd;
|
||||||
FSPM_ARCH_UPD *arch_upd;
|
FSPM_ARCH_UPD *arch_upd;
|
||||||
uint32_t fsp_version;
|
uint32_t fsp_version;
|
||||||
|
const struct fsp_header *hdr = &context->header;
|
||||||
|
const struct memranges *memmap = &context->memmap;
|
||||||
|
|
||||||
post_code(POST_MEM_PREINIT_PREP_START);
|
post_code(POST_MEM_PREINIT_PREP_START);
|
||||||
|
|
||||||
|
@ -323,94 +329,69 @@ static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake,
|
||||||
fsp_debug_after_memory_init(status);
|
fsp_debug_after_memory_init(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the binary into the memory specified by the info header. */
|
static int fspm_get_dest(const struct fsp_load_descriptor *fspld, void **dest,
|
||||||
static enum cb_err load_fspm_mem(struct fsp_header *hdr,
|
size_t size, const struct region_device *source)
|
||||||
const struct region_device *rdev,
|
|
||||||
const struct memranges *memmap)
|
|
||||||
{
|
{
|
||||||
|
struct fspm_context *context = fspld->arg;
|
||||||
|
struct fsp_header *hdr = &context->header;
|
||||||
|
struct memranges *memmap = &context->memmap;
|
||||||
uintptr_t fspm_begin;
|
uintptr_t fspm_begin;
|
||||||
uintptr_t fspm_end;
|
uintptr_t fspm_end;
|
||||||
|
|
||||||
if (fsp_validate_component(hdr, rdev) != CB_SUCCESS)
|
if (CONFIG(FSP_M_XIP)) {
|
||||||
return CB_ERR;
|
if (fsp_validate_component(hdr, source) != CB_SUCCESS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
fspm_begin = hdr->image_base;
|
*dest = rdev_mmap_full(source);
|
||||||
fspm_end = fspm_begin + hdr->image_size;
|
if ((uintptr_t)*dest != hdr->image_base) {
|
||||||
|
printk(BIOS_CRIT, "FSPM XIP base does not match: %p vs %p\n",
|
||||||
if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) !=
|
(void *)(uintptr_t)hdr->image_base, *dest);
|
||||||
CB_SUCCESS)
|
return -1;
|
||||||
return CB_ERR;
|
}
|
||||||
|
/* Since the component is XIP it's already in the address space.
|
||||||
/* Load binary into memory at provided address. */
|
Thus, there's no need to rdev_munmap(). */
|
||||||
if (rdev_readat(rdev, (void *)fspm_begin, 0, fspm_end - fspm_begin) < 0)
|
return 0;
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
return CB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the case when FSPM is running XIP. */
|
|
||||||
static enum cb_err load_fspm_xip(struct fsp_header *hdr,
|
|
||||||
const struct region_device *rdev)
|
|
||||||
{
|
|
||||||
void *base;
|
|
||||||
|
|
||||||
if (fsp_validate_component(hdr, rdev) != CB_SUCCESS)
|
|
||||||
return CB_ERR;
|
|
||||||
|
|
||||||
base = rdev_mmap_full(rdev);
|
|
||||||
if ((uintptr_t)base != hdr->image_base) {
|
|
||||||
printk(BIOS_CRIT, "FSPM XIP base does not match: %p vs %p\n",
|
|
||||||
(void *)(uintptr_t)hdr->image_base, base);
|
|
||||||
return CB_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Non XIP FSP-M uses FSP-M address */
|
||||||
* Since the component is XIP it's already in the address space. Thus,
|
fspm_begin = (uintptr_t)CONFIG_FSP_M_ADDR;
|
||||||
* there's no need to rdev_munmap().
|
fspm_end = fspm_begin + size;
|
||||||
*/
|
|
||||||
return CB_SUCCESS;
|
if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != CB_SUCCESS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*dest = (void *)fspm_begin;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsp_memory_init(bool s3wake)
|
void fsp_memory_init(bool s3wake)
|
||||||
{
|
{
|
||||||
struct fsp_header hdr;
|
|
||||||
enum cb_err status;
|
|
||||||
struct cbfsf file_desc;
|
|
||||||
struct region_device file_data;
|
|
||||||
const char *name = CONFIG_FSP_M_CBFS;
|
|
||||||
struct memranges memmap;
|
|
||||||
struct range_entry prog_ranges[2];
|
struct range_entry prog_ranges[2];
|
||||||
|
struct fspm_context context;
|
||||||
|
struct fsp_load_descriptor fspld = {
|
||||||
|
.fsp_prog = PROG_INIT(PROG_REFCODE, CONFIG_FSP_M_CBFS),
|
||||||
|
.get_destination = fspm_get_dest,
|
||||||
|
.arg = &context,
|
||||||
|
};
|
||||||
|
struct fsp_header *hdr = &context.header;
|
||||||
|
struct memranges *memmap = &context.memmap;
|
||||||
|
|
||||||
elog_boot_notify(s3wake);
|
elog_boot_notify(s3wake);
|
||||||
|
|
||||||
if (cbfs_boot_locate(&file_desc, name, NULL)) {
|
|
||||||
printk(BIOS_CRIT, "Could not locate %s in CBFS\n", name);
|
|
||||||
die("FSPM not available!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
cbfs_file_data(&file_data, &file_desc);
|
|
||||||
|
|
||||||
/* Build up memory map of romstage address space including CAR. */
|
/* Build up memory map of romstage address space including CAR. */
|
||||||
memranges_init_empty(&memmap, &prog_ranges[0], ARRAY_SIZE(prog_ranges));
|
memranges_init_empty(memmap, &prog_ranges[0], ARRAY_SIZE(prog_ranges));
|
||||||
if (ENV_CACHE_AS_RAM)
|
if (ENV_CACHE_AS_RAM)
|
||||||
memranges_insert(&memmap, (uintptr_t)_car_region_start,
|
memranges_insert(memmap, (uintptr_t)_car_region_start,
|
||||||
_car_unallocated_start - _car_region_start, 0);
|
_car_unallocated_start - _car_region_start, 0);
|
||||||
memranges_insert(&memmap, (uintptr_t)_program, REGION_SIZE(program), 0);
|
memranges_insert(memmap, (uintptr_t)_program, REGION_SIZE(program), 0);
|
||||||
|
|
||||||
if (!CONFIG(FSP_M_XIP))
|
if (fsp_load_component(&fspld, hdr) != CB_SUCCESS)
|
||||||
status = load_fspm_mem(&hdr, &file_data, &memmap);
|
die("FSPM not available or failed to load!\n");
|
||||||
else
|
|
||||||
status = load_fspm_xip(&hdr, &file_data);
|
|
||||||
|
|
||||||
if (status != CB_SUCCESS)
|
|
||||||
die("Loading FSPM failed!\n");
|
|
||||||
|
|
||||||
/* Signal that FSP component has been loaded. */
|
|
||||||
prog_segment_loaded(hdr.image_base, hdr.image_size, SEG_FINAL);
|
|
||||||
|
|
||||||
timestamp_add_now(TS_BEFORE_INITRAM);
|
timestamp_add_now(TS_BEFORE_INITRAM);
|
||||||
|
|
||||||
do_fsp_memory_init(&hdr, s3wake, &memmap);
|
do_fsp_memory_init(&context, s3wake);
|
||||||
|
|
||||||
timestamp_add_now(TS_AFTER_INITRAM);
|
timestamp_add_now(TS_AFTER_INITRAM);
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,21 @@ void fsp_handle_reset(uint32_t status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool fspm_env(void)
|
||||||
|
{
|
||||||
|
if (ENV_ROMSTAGE)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool fspm_xip(void)
|
||||||
|
{
|
||||||
|
/* FSP-M is assumed to be loaded in romstage. */
|
||||||
|
if (fspm_env() && CONFIG(FSP_M_XIP))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void *fsp_get_dest_and_load(struct fsp_load_descriptor *fspld, size_t size,
|
static void *fsp_get_dest_and_load(struct fsp_load_descriptor *fspld, size_t size,
|
||||||
const struct region_device *source_rdev,
|
const struct region_device *source_rdev,
|
||||||
uint32_t compression_algo)
|
uint32_t compression_algo)
|
||||||
|
@ -130,12 +145,20 @@ static void *fsp_get_dest_and_load(struct fsp_load_descriptor *fspld, size_t siz
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't load when executing in place. */
|
||||||
|
if (fspm_xip())
|
||||||
|
return dest;
|
||||||
|
|
||||||
if (cbfs_load_and_decompress(source_rdev, 0, region_device_sz(source_rdev),
|
if (cbfs_load_and_decompress(source_rdev, 0, region_device_sz(source_rdev),
|
||||||
dest, size, compression_algo) != size) {
|
dest, size, compression_algo) != size) {
|
||||||
printk(BIOS_ERR, "Failed to load FSP component.\n");
|
printk(BIOS_ERR, "Failed to load FSP component.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't allow FSP-M relocation. */
|
||||||
|
if (fspm_env())
|
||||||
|
return dest;
|
||||||
|
|
||||||
if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) {
|
if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) {
|
||||||
printk(BIOS_ERR, "Unable to relocate FSP component!\n");
|
printk(BIOS_ERR, "Unable to relocate FSP component!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -99,10 +99,20 @@ static inline bool fsps_env(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool fspm_env(void)
|
||||||
|
{
|
||||||
|
/* FSP-M is assumed to be loaded in romstage. */
|
||||||
|
if (ENV_ROMSTAGE)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool cbfs_lz4_enabled(void)
|
static inline bool cbfs_lz4_enabled(void)
|
||||||
{
|
{
|
||||||
if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4))
|
if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4))
|
||||||
return true;
|
return true;
|
||||||
|
if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZ4))
|
||||||
|
return true;
|
||||||
|
|
||||||
if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES))
|
if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES))
|
||||||
return false;
|
return false;
|
||||||
|
@ -114,6 +124,8 @@ static inline bool cbfs_lzma_enabled(void)
|
||||||
{
|
{
|
||||||
if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA))
|
if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA))
|
||||||
return true;
|
return true;
|
||||||
|
if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZMA))
|
||||||
|
return true;
|
||||||
/* We assume here romstage and postcar are never compressed. */
|
/* We assume here romstage and postcar are never compressed. */
|
||||||
if (ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE)
|
if (ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE)
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue