drivers/intel/fsp2_0: add option to compress FSP-S in cbfs

Allow the ability for chipset or mainboard to choose to
compress FSP-S in cbfs using LZMA or LZ4 routines. To accomplish
this fsp_load_component() is added as an assist for performing
the necessary logic and allow the caller to provide the destination
selection. Since the main cbfs decompression paths are utilized add
the appropriate checks for including compression algorithms under
the FSP-S compression options.

On picasso FSP-S (debug builds) the following savings were measured:

no-compression:
	fsps.bin	327680	none
FSP_COMPRESS_FSP_S_LZ4:
	fsps.bin	98339	LZ4 (327680 decompressed)	-70%
FSP_COMPRESS_FSP_S_LZMA:
	fsps.bin	71275 	LZMA (327680 decompressed)	-78%

BUG=b:155322763,b:150746858,b:152909132

Change-Id: I8aa5d8c1cbaf4d08f38a918a9031a2570bc5247e
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41449
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Aaron Durbin 2020-05-15 15:09:10 -06:00
parent 84f394e9c0
commit a85febcb1c
6 changed files with 131 additions and 39 deletions

View File

@ -181,6 +181,12 @@ config FSP2_0_LOGO_FILE_NAME
depends on FSP2_0_DISPLAY_LOGO depends on FSP2_0_DISPLAY_LOGO
default "3rdparty/blobs/mainboard/$(MAINBOARDDIR)/logo.bmp" 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 if FSP_PEIM_TO_PEIM_INTERFACE
source "src/drivers/intel/fsp2_0/ppi/Kconfig" source "src/drivers/intel/fsp2_0/ppi/Kconfig"
endif endif

View File

@ -56,6 +56,12 @@ 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))
$(FSP_S_CBFS)-type := fsp $(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) ifeq ($(CONFIG_FSP_USE_REPO),y)
$(obj)/Fsp_M.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH)) $(obj)/Fsp_M.fd: $(call strip_quotes,$(CONFIG_FSP_FD_PATH))

View File

@ -9,6 +9,7 @@
#include <fsp/api.h> #include <fsp/api.h>
#include <fsp/info_header.h> #include <fsp/info_header.h>
#include <memrange.h> #include <memrange.h>
#include <program_loading.h>
#include <types.h> #include <types.h>
struct hob_header { 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, enum cb_err fsp_validate_component(struct fsp_header *hdr,
const struct region_device *rdev); 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 */ /* Get igd framebuffer bar from SoC */
uintptr_t fsp_soc_get_igd_bar(void); uintptr_t fsp_soc_get_igd_bar(void);

View File

@ -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) void fsps_load(bool s3wake)
{ {
struct fsp_header *hdr = &fsps_hdr; struct fsp_load_descriptor fspld = {
struct cbfsf file_desc; .fsp_prog = PROG_INIT(PROG_REFCODE, CONFIG_FSP_S_CBFS),
struct region_device rdev; .get_destination = fsps_get_dest,
const char *name = CONFIG_FSP_S_CBFS; };
void *dest; struct prog *fsps = &fspld.fsp_prog;
size_t size;
struct prog fsps = PROG_INIT(PROG_REFCODE, name);
static int load_done; static int load_done;
if (load_done) if (load_done)
@ -96,45 +105,18 @@ void fsps_load(bool s3wake)
if (s3wake && !CONFIG(NO_STAGE_CACHE)) { if (s3wake && !CONFIG(NO_STAGE_CACHE)) {
printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n"); printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n");
stage_cache_load_stage(STAGE_REFCODE, &fsps); stage_cache_load_stage(STAGE_REFCODE, fsps);
if (fsp_validate_component(hdr, prog_rdev(&fsps)) != CB_SUCCESS) if (fsp_validate_component(&fsps_hdr, prog_rdev(fsps)) != CB_SUCCESS)
die("On resume fsps header is invalid\n"); die("On resume fsps header is invalid\n");
load_done = 1; load_done = 1;
return; return;
} }
if (cbfs_boot_locate(&file_desc, name, NULL)) { if (fsp_load_component(&fspld, &fsps_hdr) != CB_SUCCESS)
printk(BIOS_ERR, "Could not locate %s in CBFS\n", name); die("FSP-S failed to load\n");
die("FSPS not available!\n");
}
cbfs_file_data(&rdev, &file_desc); stage_cache_add(STAGE_REFCODE, fsps);
/* 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);
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; load_done = 1;
} }

View File

@ -1,9 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
#include <device/mmio.h> #include <device/mmio.h>
#include <cbfs.h>
#include <cf9_reset.h> #include <cf9_reset.h>
#include <commonlib/bsd/compression.h>
#include <commonlib/fsp.h>
#include <console/console.h> #include <console/console.h>
#include <fsp/util.h> #include <fsp/util.h>
#include <lib.h>
#include <string.h> #include <string.h>
#include <types.h> #include <types.h>
@ -114,3 +118,68 @@ void fsp_handle_reset(uint32_t status)
break; 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;
}

View File

@ -91,8 +91,19 @@ int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
return ret; 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) 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)) if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES))
return false; return false;
@ -101,6 +112,8 @@ static inline bool cbfs_lz4_enabled(void)
static inline bool cbfs_lzma_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. */ /* 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;