diff options
-rw-r--r-- | src/drivers/intel/fsp2_0/Kconfig | 6 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/Makefile.inc | 6 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/include/fsp/util.h | 16 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/silicon_init.c | 60 | ||||
-rw-r--r-- | src/drivers/intel/fsp2_0/util.c | 69 | ||||
-rw-r--r-- | src/lib/cbfs.c | 13 |
6 files changed, 131 insertions, 39 deletions
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index cad652b905..6c4344e472 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -181,6 +181,12 @@ config FSP2_0_LOGO_FILE_NAME depends on FSP2_0_DISPLAY_LOGO default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/logo.bmp" +config FSP_COMPRESS_FSP_S_LZMA + bool + +config FSP_COMPRESS_FSP_S_LZ4 + bool + 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 a46f9b88a2..6c82b28d21 100644 --- a/src/drivers/intel/fsp2_0/Makefile.inc +++ b/src/drivers/intel/fsp2_0/Makefile.inc @@ -56,6 +56,12 @@ endif cbfs-files-$(CONFIG_ADD_FSP_BINARIES) += $(FSP_S_CBFS) $(FSP_S_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_S_FILE)) $(FSP_S_CBFS)-type := fsp +ifeq ($(CONFIG_FSP_COMPRESS_FSP_S_LZMA),y) +$(FSP_S_CBFS)-compression := LZMA +endif +ifeq ($(CONFIG_FSP_COMPRESS_FSP_S_LZ4),y) +$(FSP_S_CBFS)-compression := LZ4 +endif ifeq ($(CONFIG_FSP_USE_REPO),y) $(obj)/Fsp_M.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH)) diff --git a/src/drivers/intel/fsp2_0/include/fsp/util.h b/src/drivers/intel/fsp2_0/include/fsp/util.h index ed2a2ae81d..f531e36bee 100644 --- a/src/drivers/intel/fsp2_0/include/fsp/util.h +++ b/src/drivers/intel/fsp2_0/include/fsp/util.h @@ -9,6 +9,7 @@ #include <fsp/api.h> #include <fsp/info_header.h> #include <memrange.h> +#include <program_loading.h> #include <types.h> struct hob_header { @@ -79,6 +80,21 @@ void fsp_find_bootloader_tolum(struct range_entry *re); enum cb_err fsp_validate_component(struct fsp_header *hdr, const struct region_device *rdev); +struct fsp_load_descriptor { + /* fsp_prog object will have region_device initialized to final + * load location in memory. */ + struct prog fsp_prog; + /* Fill in destination location given final load size. Return 0 on + * success, < 0 on error. */ + int (*get_destination)(const struct fsp_load_descriptor *fspld, + void **dest, size_t final_load_size, + const struct region_device *source); +}; + +/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP + * header object will be validated and filled in on successful load. */ +enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr); + /* Get igd framebuffer bar from SoC */ uintptr_t fsp_soc_get_igd_bar(void); diff --git a/src/drivers/intel/fsp2_0/silicon_init.c b/src/drivers/intel/fsp2_0/silicon_init.c index 6af445c19e..6f3781afaf 100644 --- a/src/drivers/intel/fsp2_0/silicon_init.c +++ b/src/drivers/intel/fsp2_0/silicon_init.c @@ -80,15 +80,24 @@ static void do_silicon_init(struct fsp_header *hdr) } } +static int fsps_get_dest(const struct fsp_load_descriptor *fspld, void **dest, + size_t size, const struct region_device *source) +{ + *dest = cbmem_add(CBMEM_ID_REFCODE, size); + + if (*dest == NULL) + return -1; + + return 0; +} + void fsps_load(bool s3wake) { - struct fsp_header *hdr = &fsps_hdr; - struct cbfsf file_desc; - struct region_device rdev; - const char *name = CONFIG_FSP_S_CBFS; - void *dest; - size_t size; - struct prog fsps = PROG_INIT(PROG_REFCODE, name); + struct fsp_load_descriptor fspld = { + .fsp_prog = PROG_INIT(PROG_REFCODE, CONFIG_FSP_S_CBFS), + .get_destination = fsps_get_dest, + }; + struct prog *fsps = &fspld.fsp_prog; static int load_done; if (load_done) @@ -96,45 +105,18 @@ void fsps_load(bool s3wake) if (s3wake && !CONFIG(NO_STAGE_CACHE)) { printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n"); - stage_cache_load_stage(STAGE_REFCODE, &fsps); - if (fsp_validate_component(hdr, prog_rdev(&fsps)) != CB_SUCCESS) + stage_cache_load_stage(STAGE_REFCODE, fsps); + if (fsp_validate_component(&fsps_hdr, prog_rdev(fsps)) != CB_SUCCESS) die("On resume fsps header is invalid\n"); load_done = 1; return; } - if (cbfs_boot_locate(&file_desc, name, NULL)) { - printk(BIOS_ERR, "Could not locate %s in CBFS\n", name); - die("FSPS not available!\n"); - } - - cbfs_file_data(&rdev, &file_desc); - - /* Load and relocate into CBMEM. */ - size = region_device_sz(&rdev); - dest = cbmem_add(CBMEM_ID_REFCODE, size); - - if (dest == NULL) - die("Could not add FSPS to CBMEM!\n"); - - if (rdev_readat(&rdev, dest, 0, size) < 0) - die("Failed to read FSPS!\n"); - - if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) - die("Unable to relocate FSPS!\n"); - - /* Create new region device in memory after relocation. */ - rdev_chain(&rdev, &addrspace_32bit.rdev, (uintptr_t)dest, size); - - if (fsp_validate_component(hdr, &rdev) != CB_SUCCESS) - die("Invalid FSPS header!\n"); - - prog_set_area(&fsps, dest, size); + if (fsp_load_component(&fspld, &fsps_hdr) != CB_SUCCESS) + die("FSP-S failed to load\n"); - stage_cache_add(STAGE_REFCODE, &fsps); + stage_cache_add(STAGE_REFCODE, fsps); - /* Signal that FSP component has been loaded. */ - prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL); load_done = 1; } diff --git a/src/drivers/intel/fsp2_0/util.c b/src/drivers/intel/fsp2_0/util.c index 4050862849..3b7516ab06 100644 --- a/src/drivers/intel/fsp2_0/util.c +++ b/src/drivers/intel/fsp2_0/util.c @@ -1,9 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include <device/mmio.h> +#include <cbfs.h> #include <cf9_reset.h> +#include <commonlib/bsd/compression.h> +#include <commonlib/fsp.h> #include <console/console.h> #include <fsp/util.h> +#include <lib.h> #include <string.h> #include <types.h> @@ -114,3 +118,68 @@ void fsp_handle_reset(uint32_t status) break; } } + +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) +{ + void *dest; + + if (fspld->get_destination(fspld, &dest, size, source_rdev) < 0) { + printk(BIOS_ERR, "FSP Destination not obtained.\n"); + return NULL; + } + + 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; + } + + if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) { + printk(BIOS_ERR, "Unable to relocate FSP component!\n"); + return NULL; + } + + return dest; +} + +/* Load the FSP component described by fsp_load_descriptor from cbfs. The FSP + * header object will be validated and filled in on successful load. */ +enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_header *hdr) +{ + struct cbfsf file_desc; + uint32_t compression_algo; + size_t output_size; + void *dest; + struct region_device source_rdev; + struct prog *fsp_prog = &fspld->fsp_prog; + + if (fspld->get_destination == NULL) + return CB_ERR; + + if (cbfs_boot_locate(&file_desc, prog_name(fsp_prog), &fsp_prog->cbfs_type) < 0) + return CB_ERR; + + if (cbfsf_decompression_info(&file_desc, &compression_algo, &output_size) < 0) + return CB_ERR; + + cbfs_file_data(&source_rdev, &file_desc); + + dest = fsp_get_dest_and_load(fspld, output_size, &source_rdev, compression_algo); + + if (dest == NULL) + return CB_ERR; + + prog_set_area(fsp_prog, dest, output_size); + + if (fsp_validate_component(hdr, prog_rdev(fsp_prog)) != CB_SUCCESS) { + printk(BIOS_ERR, "Invalid FSP header after load!\n"); + return CB_ERR; + } + + /* Signal that FSP component has been loaded. */ + prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL); + + return CB_SUCCESS; +} diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index e05ea801c8..ec5156c09c 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -91,8 +91,19 @@ int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, return ret; } +static inline bool fsps_env(void) +{ + /* FSP-S is assumed to be loaded in ramstage. */ + if (ENV_RAMSTAGE) + return true; + return false; +} + static inline bool cbfs_lz4_enabled(void) { + if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4)) + return true; + if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES)) return false; @@ -101,6 +112,8 @@ static inline bool cbfs_lz4_enabled(void) static inline bool cbfs_lzma_enabled(void) { + if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA)) + return true; /* We assume here romstage and postcar are never compressed. */ if (ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) return false; |