From ecbfa99f64c117f45dc6d1b0c50947f46daa3280 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Fri, 15 May 2020 17:01:58 -0600 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/41450 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh --- src/drivers/intel/fsp2_0/Kconfig | 13 ++++ src/drivers/intel/fsp2_0/Makefile.inc | 6 ++ src/drivers/intel/fsp2_0/include/fsp/util.h | 2 + src/drivers/intel/fsp2_0/memory_init.c | 113 ++++++++++++---------------- src/drivers/intel/fsp2_0/util.c | 23 ++++++ src/lib/cbfs.c | 12 +++ 6 files changed, 103 insertions(+), 66 deletions(-) diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 6c4344e472..0344116370 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -187,6 +187,19 @@ config FSP_COMPRESS_FSP_S_LZMA config FSP_COMPRESS_FSP_S_LZ4 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 source "src/drivers/intel/fsp2_0/ppi/Kconfig" endif diff --git a/src/drivers/intel/fsp2_0/Makefile.inc b/src/drivers/intel/fsp2_0/Makefile.inc index 6c82b28d21..e954a462a1 100644 --- a/src/drivers/intel/fsp2_0/Makefile.inc +++ b/src/drivers/intel/fsp2_0/Makefile.inc @@ -52,6 +52,12 @@ $(FSP_M_CBFS)-type := fsp ifeq ($(CONFIG_FSP_M_XIP),y) $(FSP_M_CBFS)-options := --xip $(TXTIBB) 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) $(FSP_S_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_S_FILE)) diff --git a/src/drivers/intel/fsp2_0/include/fsp/util.h b/src/drivers/intel/fsp2_0/include/fsp/util.h index f531e36bee..29c393b09c 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/util.h +++ b/src/drivers/intel/fsp2_0/include/fsp/util.h @@ -89,6 +89,8 @@ struct fsp_load_descriptor { int (*get_destination)(const struct fsp_load_descriptor *fspld, void **dest, size_t final_load_size, 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 diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c index ebd5213503..d90b181e78 100644 --- a/src/drivers/intel/fsp2_0/memory_init.c +++ b/src/drivers/intel/fsp2_0/memory_init.c @@ -254,14 +254,20 @@ static uint32_t fsp_memory_settings_version(const struct fsp_header *hdr) return ver; } -static void do_fsp_memory_init(struct fsp_header *hdr, bool s3wake, - const struct memranges *memmap) +struct fspm_context { + struct fsp_header header; + struct memranges memmap; +}; + +static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake) { uint32_t status; fsp_memory_init_fn fsp_raminit; FSPM_UPD fspm_upd, *upd; FSPM_ARCH_UPD *arch_upd; uint32_t fsp_version; + const struct fsp_header *hdr = &context->header; + const struct memranges *memmap = &context->memmap; 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); } -/* Load the binary into the memory specified by the info header. */ -static enum cb_err load_fspm_mem(struct fsp_header *hdr, - const struct region_device *rdev, - const struct memranges *memmap) +static int fspm_get_dest(const struct fsp_load_descriptor *fspld, void **dest, + size_t size, const struct region_device *source) { + struct fspm_context *context = fspld->arg; + struct fsp_header *hdr = &context->header; + struct memranges *memmap = &context->memmap; uintptr_t fspm_begin; uintptr_t fspm_end; - if (fsp_validate_component(hdr, rdev) != CB_SUCCESS) - return CB_ERR; - - fspm_begin = hdr->image_base; - fspm_end = fspm_begin + hdr->image_size; - - if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != - CB_SUCCESS) - return CB_ERR; - - /* Load binary into memory at provided address. */ - if (rdev_readat(rdev, (void *)fspm_begin, 0, fspm_end - fspm_begin) < 0) - return CB_ERR; + if (CONFIG(FSP_M_XIP)) { + if (fsp_validate_component(hdr, source) != CB_SUCCESS) + return -1; - return CB_SUCCESS; -} + *dest = rdev_mmap_full(source); + if ((uintptr_t)*dest != hdr->image_base) { + printk(BIOS_CRIT, "FSPM XIP base does not match: %p vs %p\n", + (void *)(uintptr_t)hdr->image_base, *dest); + return -1; + } + /* Since the component is XIP it's already in the address space. + Thus, there's no need to rdev_munmap(). */ + return 0; + } -/* 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; + /* Non XIP FSP-M uses FSP-M address */ + fspm_begin = (uintptr_t)CONFIG_FSP_M_ADDR; + fspm_end = fspm_begin + size; - if (fsp_validate_component(hdr, rdev) != CB_SUCCESS) - return CB_ERR; + if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != CB_SUCCESS) + return -1; - 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; - } + *dest = (void *)fspm_begin; - /* - * Since the component is XIP it's already in the address space. Thus, - * there's no need to rdev_munmap(). - */ - return CB_SUCCESS; + return 0; } 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 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); - 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. */ - 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) - memranges_insert(&memmap, (uintptr_t)_car_region_start, + memranges_insert(memmap, (uintptr_t)_car_region_start, _car_unallocated_start - _car_region_start, 0); - memranges_insert(&memmap, (uintptr_t)_program, REGION_SIZE(program), 0); - - if (!CONFIG(FSP_M_XIP)) - status = load_fspm_mem(&hdr, &file_data, &memmap); - else - status = load_fspm_xip(&hdr, &file_data); - - if (status != CB_SUCCESS) - die("Loading FSPM failed!\n"); + memranges_insert(memmap, (uintptr_t)_program, REGION_SIZE(program), 0); - /* Signal that FSP component has been loaded. */ - prog_segment_loaded(hdr.image_base, hdr.image_size, SEG_FINAL); + if (fsp_load_component(&fspld, hdr) != CB_SUCCESS) + die("FSPM not available or failed to load!\n"); 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); } diff --git a/src/drivers/intel/fsp2_0/util.c b/src/drivers/intel/fsp2_0/util.c index 3b7516ab06..a00b684624 100644 --- a/src/drivers/intel/fsp2_0/util.c +++ b/src/drivers/intel/fsp2_0/util.c @@ -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, const struct region_device *source_rdev, 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; } + /* 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), dest, size, compression_algo) != size) { printk(BIOS_ERR, "Failed to load FSP component.\n"); return NULL; } + /* Don't allow FSP-M relocation. */ + if (fspm_env()) + return dest; + if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) { printk(BIOS_ERR, "Unable to relocate FSP component!\n"); return NULL; diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index ec5156c09c..cb66f81d99 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -99,10 +99,20 @@ static inline bool fsps_env(void) 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) { if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4)) return true; + if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZ4)) + return true; if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES)) return false; @@ -114,6 +124,8 @@ static inline bool cbfs_lzma_enabled(void) { if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA)) return true; + if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZMA)) + return true; /* We assume here romstage and postcar are never compressed. */ if (ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) return false; -- cgit v1.2.3