[coreboot-gerrit] New patch to review for coreboot: drivers/intel/fsp2_0: handle XIP and non-XIP for FSPM component

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Mon Jul 18 19:48:42 CEST 2016


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15741

-gerrit

commit 791532af75990af6bdfe23773d117826e9df58cf
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Sun Jul 17 23:23:59 2016 -0500

    drivers/intel/fsp2_0: handle XIP and non-XIP for FSPM component
    
    The previously implementation for loading the FSPM component didn't
    handle platforms which expects FSPM to be XIP. For the non-XIP case,
    romstage's address space wasn't fully being checked for overlaps.
    Lastly, fixup the API as the range_entry isn't needed any longer.
    This API change requires a apollolake to be updated as well.
    
    BUG=chrome-os-partner:52679
    
    Change-Id: I24d0c7d123d12f15a8477e1025bf0901e2d702e7
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/drivers/intel/fsp2_0/include/fsp/api.h |  5 +-
 src/drivers/intel/fsp2_0/memory_init.c     | 88 +++++++++++++++++++++++++++++-
 src/soc/intel/apollolake/romstage.c        |  7 +--
 3 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/src/drivers/intel/fsp2_0/include/fsp/api.h b/src/drivers/intel/fsp2_0/include/fsp/api.h
index 9f8aae7..510163d 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/api.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/api.h
@@ -58,7 +58,7 @@ enum fsp_notify_phase {
 
 
 /* Main FSP stages */
-enum fsp_status fsp_memory_init(struct range_entry *r, bool s3wake);
+enum fsp_status fsp_memory_init(bool s3wake);
 enum fsp_status fsp_silicon_init(struct range_entry *r);
 enum fsp_status fsp_notify(enum fsp_notify_phase phase);
 
@@ -74,14 +74,13 @@ void platform_fsp_silicon_init_params_cb(struct FSPS_UPD *supd);
  * points and map 1:1 to the FSP entry points of the same name.
  *
  * ### fsp_memory_init():
- *     - r: memory range that the binary is allowed to be loaded into
  *     - s3wake: boolean indicating if the system is waking from resume
  *
  * This function is responsible for loading and executing the memory
  * initialization code from the FSP-M binary. It expects this binary to reside
  * in cbfs as FSP_M_FILE.
  *
- * The function takes two parameters, which are described above, but does not
+ * The function takes one parameter, which is described above, but does not
  * take in memory parameters as an argument. The memory parameters can be filled
  * in with platform_fsp_memory_init_params_cb(). This is a callback symbol
  * that fsp_memory_init() will call. The platform must provide this symbol.
diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c
index 700d40f..497a5de 100644
--- a/src/drivers/intel/fsp2_0/memory_init.c
+++ b/src/drivers/intel/fsp2_0/memory_init.c
@@ -14,15 +14,18 @@
 #include <arch/io.h>
 #include <arch/cpu.h>
 #include <arch/symbols.h>
+#include <cbfs.h>
 #include <cbmem.h>
 #include <console/console.h>
 #include <fsp/api.h>
 #include <fsp/util.h>
 #include <memrange.h>
+#include <program_loading.h>
 #include <reset.h>
 #include <romstage_handoff.h>
 #include <soc/intel/common/mrc_cache.h>
 #include <string.h>
+#include <symbols.h>
 #include <timestamp.h>
 
 typedef asmlinkage enum fsp_status (*fsp_memory_init_fn)
@@ -153,12 +156,93 @@ static enum fsp_status do_fsp_memory_init(struct fsp_header *hdr, bool s3wake)
 	return do_fsp_post_memory_init(hob_list_ptr, s3wake);
 }
 
-enum fsp_status fsp_memory_init(struct range_entry *range, bool s3wake)
+/* 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)
+{
+	struct memranges ranges;
+	struct range_entry freeranges[2];
+	const struct range_entry *r;
+	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;
+
+	/* Build up memory map of romstage address space including CAR. */
+	memranges_init_empty(&ranges, &freeranges[0], ARRAY_SIZE(freeranges));
+	memranges_insert(&ranges, (uintptr_t)_car_region_start,
+		_car_relocatable_data_end - _car_region_start, 0);
+	memranges_insert(&ranges, (uintptr_t)_program, _program_size, 0);
+	memranges_each_entry(r, &ranges) {
+		if (fspm_end <= range_entry_base(r))
+			continue;
+		if (fspm_begin >= range_entry_end(r))
+			continue;
+		printk(BIOS_ERR, "FSPM overlaps currently running program.\n");
+		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;
+
+	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_ERR, "FSPM XIP base does not match: %p vs %p\n",
+			(void *)(uintptr_t)hdr->image_base, base);
+		return CB_ERR;
+	}
+
+	/*
+	 * Since the component is XIP it's already in the address space. Thus,
+	 * there's no need to rdev_munmap().
+	 */
+	return CB_SUCCESS;
+}
+
+enum fsp_status 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;
 
-	if (fsp_load_binary(&hdr, CONFIG_FSP_M_CBFS, range) != CB_SUCCESS)
+	if (cbfs_boot_locate(&file_desc, name, NULL)) {
+		printk(BIOS_ERR, "Could not locate %s in CBFS\n", name);
 		return FSP_NOT_FOUND;
+	}
+
+	cbfs_file_data(&file_data, &file_desc);
+
+	if (IS_ENABLED(CONFIG_NO_XIP_EARLY_STAGES))
+		status = load_fspm_mem(&hdr, &file_data);
+	else
+		status = load_fspm_xip(&hdr, &file_data);
+
+	if (status != CB_SUCCESS) {
+		printk(BIOS_ERR, "Loading FSPM failed.\n");
+		return FSP_NOT_FOUND;
+	}
+
+	/* Signal that FSP component has been loaded. */
+	prog_segment_loaded(hdr.image_base, hdr.image_size, SEG_FINAL);
 
 	return do_fsp_memory_init(&hdr, s3wake);
 }
diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c
index 464d5b8..da7fcf1 100644
--- a/src/soc/intel/apollolake/romstage.c
+++ b/src/soc/intel/apollolake/romstage.c
@@ -101,7 +101,6 @@ ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state);
 
 asmlinkage void car_stage_entry(void)
 {
-	struct range_entry reg_car;
 	struct postcar_frame pcf;
 	uintptr_t top_of_ram;
 	bool s3wake;
@@ -116,11 +115,7 @@ asmlinkage void car_stage_entry(void)
 
 	s3wake = fill_power_state(ps) == ACPI_S3;
 
-	/* Make sure the blob does not override our data in CAR */
-	range_entry_init(&reg_car, (uintptr_t)_car_relocatable_data_end,
-			(uintptr_t)_car_region_end, 0);
-
-	if (fsp_memory_init(&reg_car, s3wake) != FSP_SUCCESS) {
+	if (fsp_memory_init(s3wake) != FSP_SUCCESS) {
 		die("FSP memory init failed. Giving up.");
 	}
 



More information about the coreboot-gerrit mailing list