summaryrefslogtreecommitdiff
path: root/src/drivers/intel/fsp2_0
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/intel/fsp2_0')
-rw-r--r--src/drivers/intel/fsp2_0/Kconfig6
-rw-r--r--src/drivers/intel/fsp2_0/Makefile.inc6
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/util.h16
-rw-r--r--src/drivers/intel/fsp2_0/silicon_init.c60
-rw-r--r--src/drivers/intel/fsp2_0/util.c69
5 files changed, 118 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;
+}