[coreboot-gerrit] New patch to review for coreboot: soc/intel/apollolake: add Multiple FMAP build

Brenton Dong (brenton.m.dong@intel.com) gerrit at coreboot.org
Wed Oct 19 23:51:47 CEST 2016


Brenton Dong (brenton.m.dong at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17064

-gerrit

commit f12eabf318f9969df36e91bf15707303ade03667
Author: brenton <brenton.m.dong at intel.com>
Date:   Wed Oct 19 14:21:12 2016 -0700

    soc/intel/apollolake: add Multiple FMAP build
    
    Multiple coreboot binaries with separate FMAPs and separate CBFSs
    allow coreboot to run separate stages from different regions (SRAM,
    CAR, Mem)
    
    When enabling Multiple FMAP, 3 Coreboot Images will be created.
    IBBL: Contains bootblock, CAR init (FSP-T) and hands off to IBBM
    IBBM: Contains romstage, Mem Init (FSP-M) and postcar
    OBB:  Contains ramstage, Silicon Init (FSP-S), and the rest of the
    components in the original single coreboot.rom file.  This is the same
    image as the original coreboot.rom minus the components moved to
    the IBBL and IBBM
    
    Add functions to select which region cbfs files will be loaded from
    
    Verified on Intel LeafHill CRB and confirmed that the coreboot builds
    3 separate coreboot files which can be loaded and booted.  Verified
    that other ApolloLake projects can build correctly with this option
    disabled.
    
    Change-Id: Iab3c353b65e1e0fc9d04fcee6a82a330927db41e
    Signed-off-by: brenton <brenton.m.dong at intel.com>
---
 Makefile.inc                                      |  47 ++++++++++
 src/arch/x86/Makefile.inc                         |   2 +
 src/drivers/intel/fsp2_0/Makefile.inc             |   5 +
 src/soc/intel/apollolake/Kconfig                  |   6 ++
 src/soc/intel/apollolake/Makefile.inc             |   4 +
 src/soc/intel/apollolake/bootblock/bootblock.c    |  57 ++++++++++++
 src/soc/intel/apollolake/chip.c                   |   9 +-
 src/soc/intel/apollolake/include/soc/bootregion.h |  28 ++++++
 src/soc/intel/apollolake/include/soc/cse.h        |  30 ++++++
 src/soc/intel/apollolake/include/soc/mmio.h       |  35 +++++++
 src/soc/intel/apollolake/mmap_boot.c              |   2 +
 src/soc/intel/apollolake/mmap_boot_cse.c          |  53 +++++++++++
 src/soc/intel/apollolake/postcar.c                |  10 ++
 src/soc/intel/apollolake/romstage.c               | 108 ++++++++++++++++++++++
 14 files changed, 395 insertions(+), 1 deletion(-)

diff --git a/Makefile.inc b/Makefile.inc
old mode 100644
new mode 100755
index 127f372..9e25883
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -826,11 +826,13 @@ ifneq ($(CONFIG_UPDATE_IMAGE),y)
 $(obj)/coreboot.pre: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL) $$(cpu_ucode_cbfs_file) $(obj)/fmap.fmap $(obj)/fmap.desc
 	$(CBFSTOOL) $@.tmp create -M $(obj)/fmap.fmap -r $(shell cat $(obj)/fmap.desc)
 ifeq ($(CONFIG_ARCH_X86),y)
+ifneq ($(CONFIG_MULTIPLE_FMAP),y)
 	$(CBFSTOOL) $@.tmp add \
 		-f $(objcbfs)/bootblock.bin \
 		-n bootblock \
 		-t bootblock \
 		-b -$(call file-size,$(objcbfs)/bootblock.bin) $(cbfs-autogen-attributes)
+endif  # ifeq ($(CONFIG_MULTIPLE_FMAP),y)
 else # ifeq ($(CONFIG_ARCH_X86),y)
 	$(CBFSTOOL) $@.tmp write -u \
 		-r BOOTBLOCK \
@@ -865,6 +867,49 @@ $(REFCODE_BLOB): $(RMODTOOL)
 	$(RMODTOOL) -i $(CONFIG_REFCODE_BLOB_FILE) -o $@
 endif
 
+
+ifeq ($(CONFIG_MULTIPLE_FMAP),y)
+
+.PHONY:$(obj)/coreboot_ibbl.rom
+$(obj)/coreboot_ibbl.rom: $(call strip_quotes,$(CONFIG_FSP_T_FILE)) $(obj)/ibbl_fmap.desc $(CBFSTOOL) $$(INTERMEDIATE)
+	$(CBFSTOOL) $@.tmp create -M $(obj)/ibbl_fmap.fmap -r $(shell cat $(obj)/ibbl_fmap.desc)
+	$(CBFSTOOL) $@.tmp add \
+		-f $(objcbfs)/bootblock.bin \
+		-n bootblock \
+		-t bootblock \
+		-b -$(call file-size,$(objcbfs)/bootblock.bin) $(cbfs-autogen-attributes)
+	$(CBFSTOOL) $@.tmp add-master-header
+	$(CBFSTOOL) $@.tmp add \
+		-f $(call strip_quotes,$(CONFIG_FSP_T_FILE)) \
+		-n blobs/fspt.bin -t fsp -y -b 0xC0
+	mv $@.tmp $@
+	@printf "\ncoreboot IBBL image size is 0x%x\n" `stat -L -c %s $@`
+	$(CBFSTOOL) $@ print
+
+.PHONY:$(obj)/coreboot_ibbm.rom
+$(obj)/coreboot_ibbm.rom: $(call strip_quotes,$(CONFIG_FSP_M_FILE)) $(objcbfs)/romstage.elf \
+                          $(objcbfs)/postcar.elf \
+                          $(obj)/ibbm_fmap.desc $(CBFSTOOL) $$(INTERMEDIATE)
+	$(CBFSTOOL) $@.tmp create -M $(obj)/ibbm_fmap.fmap -r $(shell cat $(obj)/ibbm_fmap.desc)
+	$(CBFSTOOL) $@.tmp add-master-header
+	$(CBFSTOOL) $@.tmp add-stage \
+		-f $(objcbfs)/romstage.elf \
+		-n $(CONFIG_CBFS_PREFIX)/romstage -c none \
+		$(CBFSTOOL_PRE_OPTS) -b 0
+	$(CBFSTOOL) $@.tmp add \
+		-f $(call strip_quotes,$(CONFIG_FSP_M_FILE)) \
+		-n blobs/fspm.bin -t fsp -y
+	$(CBFSTOOL)  $@.tmp add-stage \
+		-f $(objcbfs)/postcar.elf \
+		-n $(CONFIG_CBFS_PREFIX)/postcar
+	mv $@.tmp $@
+	@printf "\ncoreboot IBBM image size is 0x%x\n" `stat -L -c %s $@`
+	$(CBFSTOOL) $@ print
+
+coreboot: $(obj)/coreboot_ibbl.rom $(obj)/coreboot_ibbm.rom
+
+endif # ifneq ($(CONFIG_MULTIPLE_FMAP),y)
+
 $(obj)/coreboot.rom: $(obj)/coreboot.pre $(objcbfs)/ramstage.elf $(CBFSTOOL) $$(INTERMEDIATE)
 	@printf "    CBFS       $(subst $(obj)/,,$(@))\n"
 # The full ROM may be larger than the CBFS part, so create an empty
@@ -892,6 +937,7 @@ endif
 	@printf "    CBFSPRINT  $(subst $(obj)/,,$(@))\n\n"
 	$(CBFSTOOL) $@ print -r $(subst $(spc),$(comma),$(all-regions))
 
+ifneq ($(CONFIG_MULTIPLE_FMAP),y)
 cbfs-files-y += $(CONFIG_CBFS_PREFIX)/romstage
 $(CONFIG_CBFS_PREFIX)/romstage-file := $(objcbfs)/romstage.elf
 $(CONFIG_CBFS_PREFIX)/romstage-type := stage
@@ -924,6 +970,7 @@ endif    # CONFIG_NO_FIXED_XIP_ROM_SIZE
 
 endif   # CONFIG_NO_XIP_EARLY_STAGES
 endif   # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
+endif    # CONFIG_MULTIPLE_FMAP
 
 cbfs-files-y += $(CONFIG_CBFS_PREFIX)/ramstage
 $(CONFIG_CBFS_PREFIX)/ramstage-file := $(objcbfs)/ramstage.elf
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
old mode 100644
new mode 100755
index 782ca63..fc7eb5c
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -300,10 +300,12 @@ $(objcbfs)/postcar.elf: $(objcbfs)/postcar.debug.rmod
 	cp $< $@
 
 # Add postcar to CBFS
+ifneq ($(CONFIG_MULTIPLE_FMAP),y)
 cbfs-files-$(CONFIG_POSTCAR_STAGE)  += $(CONFIG_CBFS_PREFIX)/postcar
 $(CONFIG_CBFS_PREFIX)/postcar-file := $(objcbfs)/postcar.elf
 $(CONFIG_CBFS_PREFIX)/postcar-type := stage
 $(CONFIG_CBFS_PREFIX)/postcar-compression := none
+endif #CONFIG_MULTIPLE_FMAP
 
 ###############################################################################
 # ramstage
diff --git a/src/drivers/intel/fsp2_0/Makefile.inc b/src/drivers/intel/fsp2_0/Makefile.inc
index 87d2be5..7d14d02 100755
--- a/src/drivers/intel/fsp2_0/Makefile.inc
+++ b/src/drivers/intel/fsp2_0/Makefile.inc
@@ -45,6 +45,8 @@ CPPFLAGS_common += -I$(src)/drivers/intel/fsp2_0/include
 
 # Add FSP blobs into cbfs. SoC code may supply  additional options with
 # -options, e.g --xip or -b
+ifneq ($(CONFIG_MULTIPLE_FMAP),y)
+
 ifeq ($(CONFIG_FSP_CAR),y)
 cbfs-files-$(CONFIG_ADD_FSP_BINARIES) += $(CONFIG_FSP_T_CBFS)
 $(CONFIG_FSP_T_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_T_FILE))
@@ -57,6 +59,9 @@ endif # CONFIG_FSP_CAR
 cbfs-files-$(CONFIG_ADD_FSP_BINARIES) += $(CONFIG_FSP_M_CBFS)
 $(CONFIG_FSP_M_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_M_FILE))
 $(CONFIG_FSP_M_CBFS)-type := fsp
+
+endif #CONFIG_MULTIPLE_FMAP
+
 ifeq ($(CONFIG_FSP_M_XIP),y)
 $(CONFIG_FSP_M_CBFS)-options := --xip
 endif
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
old mode 100644
new mode 100755
index 6c178c3..eeba42a
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -81,6 +81,12 @@ config TPM_ON_FAST_SPI
 	 TPM part is conntected on Fast SPI interface, but the LPC MMIO
 	 TPM transactions are decoded and serialized over the SPI interface.
 
+config MULTIPLE_FMAP
+	depends on FSP_CAR
+	bool
+	help
+	  Enable build with mulitple coreboot images and each will has its own fmap.
+
 config SOC_INTEL_COMMON_RESET
 	bool
 	default y
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index c2bbc11..b73f532 100755
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -15,6 +15,7 @@ bootblock-y += gpio.c
 bootblock-y += heci.c
 bootblock-y += itss.c
 bootblock-y += lpc_lib.c
+bootblock-$(CONFIG_MULTIPLE_FMAP) += mmap_boot_cse.c
 bootblock-y += mmap_boot.c
 bootblock-y += pmutil.c
 bootblock-y += spi.c
@@ -37,6 +38,7 @@ romstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
 romstage-y += lpc_lib.c
 romstage-y += memmap.c
 romstage-y += meminit.c
+romstage-$(CONFIG_MULTIPLE_FMAP) += mmap_boot_cse.c
 romstage-y += mmap_boot.c
 romstage-y += tsc_freq.c
 romstage-y += pmutil.c
@@ -65,6 +67,7 @@ ramstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
 ramstage-y += lpc.c
 ramstage-y += lpc_lib.c
 ramstage-y += memmap.c
+ramstage-$(CONFIG_MULTIPLE_FMAP) += mmap_boot_cse.c
 ramstage-y += mmap_boot.c
 ramstage-y += p2sb.c
 ramstage-y += uart.c
@@ -81,6 +84,7 @@ ramstage-y += spi.c
 ramstage-y += xhci.c
 
 postcar-y += memmap.c
+postcar-$(CONFIG_MULTIPLE_FMAP) += mmap_boot_cse.c
 postcar-y += mmap_boot.c
 postcar-y += spi.c
 postcar-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c
old mode 100644
new mode 100755
index 28a9128..22a4d44
--- a/src/soc/intel/apollolake/bootblock/bootblock.c
+++ b/src/soc/intel/apollolake/bootblock/bootblock.c
@@ -14,6 +14,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include <string.h>
 #include <arch/cpu.h>
 #include <bootblock_common.h>
 #include <cpu/x86/mtrr.h>
@@ -31,6 +32,53 @@
 #include <spi-generic.h>
 #include <timestamp.h>
 
+#if CONFIG_MULTIPLE_FMAP
+#include <soc/cse.h>
+#include <soc/bootregion.h>
+#endif //CONFIG_MULTIPLE_FMAP
+
+#if CONFIG_MULTIPLE_FMAP
+static void load_ibbm0(uint32_t ibbm_base, uint32_t ibbm_size)
+{
+	uint32_t     host_to_cse;
+	uint32_t     cse_to_host;
+	uint32_t     chunk_num;
+	uint32_t     state;
+	msr_t        msr;
+
+	/* Request data from CSE */
+	host_to_cse  = (ibbm_size << 4) | 0xC0000000;
+	CSE_HOST2CSE = host_to_cse;
+
+	/* Wait for response */
+	do {
+		cse_to_host  = CSE_CSE2HOST;
+		chunk_num   = (cse_to_host >> 28) & 3;
+	} while (!chunk_num);
+
+	/* Check whether there is ring buffer ready to copy */
+	state = (cse_to_host ^ host_to_cse) & 0x0F;
+	while (state == 0) {
+		cse_to_host  = CSE_CSE2HOST;
+		state = (cse_to_host ^ host_to_cse) & 0x0F;
+	}
+
+	/*
+	* The 1st 128K should have been loaded into SRAM now
+	* However, since the top 32K IBBL is still cached, we can only read
+	* (128-32)K at this moment.  The remaining will be read in romstage.
+	*/
+	memcpy((void *)ibbm_base,  (void *)(~CSE_IBB_SRAM_SIZE + 1),
+		CSE_IBB_SRAM_SIZE - CONFIG_IBBL_ROM_SIZE);
+
+	/* Set BIT8 in MSR 0x120 to allow IBB to be executed from
+	the temporary memory */
+	msr = rdmsr(0x120);
+	msr.lo |= (1<<8);
+	wrmsr(0x120, msr);
+}
+#endif //CONFIG_MULTIPLE_FMAP
+
 static const struct pad_config tpm_spi_configs[] = {
 	PAD_CFG_NF(GPIO_106, NATIVE, DEEP, NF3),	/* FST_SPI_CS2_N */
 };
@@ -92,6 +140,15 @@ void asmlinkage bootblock_c_entry(uint64_t base_timestamp)
 
 	enable_cmos_upper_bank();
 
+#if CONFIG_MULTIPLE_FMAP
+	/* Loading IBBM into CAR */
+	load_ibbm0(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE
+				- CONFIG_IBBM_ROM_SIZE,	CONFIG_IBBM_ROM_SIZE);
+
+	/* Switch to new boot device in CAR */
+	set_boot_region(BOOT_REGION_IBBM);
+#endif //CONFIG_MULTIPLE_FMAP
+
 	/* Call lib/bootblock.c main */
 	bootblock_main_with_timestamp(base_timestamp);
 }
diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
old mode 100644
new mode 100755
index d722992..0a184eb
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -35,9 +35,12 @@
 #include <soc/pm.h>
 #include <soc/p2sb.h>
 #include <soc/northbridge.h>
-
 #include "chip.h"
 
+#if CONFIG_MULTIPLE_FMAP
+#include <soc/bootregion.h>
+#endif /* CONFIG_MULTIPLE_FMAP */
+
 static void *vbt;
 static struct region_device vbt_rdev;
 
@@ -267,6 +270,10 @@ static void soc_init(void *data)
 	 * default policy that doesn't honor boards' requirements. */
 	itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
 
+#if CONFIG_MULTIPLE_FMAP
+	set_boot_region(BOOT_REGION_OBB);
+#endif //CONFIG_MULTIPLE_FMAP
+
 	fsp_silicon_init();
 
 	/* Restore GPIO IRQ polarities back to previous settings. */
diff --git a/src/soc/intel/apollolake/include/soc/bootregion.h b/src/soc/intel/apollolake/include/soc/bootregion.h
new file mode 100755
index 0000000..dde562a
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/bootregion.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_LEAFHILL_BOOT_RGN_H_
+#define _SOC_LEAFHILL_BOOT_RGN_H_
+
+#define  BOOT_REGION_IBBL  0
+#define  BOOT_REGION_IBBM  1
+#define  BOOT_REGION_OBB   2
+
+/* Set current active boot region  */
+void set_boot_region(int region_id);
+
+#endif /* _SOC_LEAFHILL_BOOT_RGN_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/cse.h b/src/soc/intel/apollolake/include/soc/cse.h
new file mode 100755
index 0000000..ed2b136
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/cse.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_LEAFHILL_CSE_H_
+#define _SOC_LEAFHILL_CSE_H_
+
+#define  HOST2CSE               0x70
+#define  CSE2HOST               0x60
+#define  CSE_IBB_SRAM_SIZE      0x20000
+
+#define  CSE_CFG_BASE           (CONFIG_MMCONF_BASE_ADDRESS + 0x78000)
+#define  CSE_VIDDID             (*(volatile int32_t *)CSE_CFG_BASE)
+#define  CSE_HOST2CSE           (*(volatile int32_t *)(CSE_CFG_BASE + HOST2CSE))
+#define  CSE_CSE2HOST           (*(volatile int32_t *)(CSE_CFG_BASE + CSE2HOST))
+
+#endif /* _SOC_LEAFHILL_CSE_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/mmio.h b/src/soc/intel/apollolake/include/soc/mmio.h
new file mode 100755
index 0000000..674e071
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/mmio.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SOC_MMIO_H_
+#define _SOC_MMIO_H_
+
+
+#define MmioRead32(x)		(*(volatile uint32_t *)(unsigned int)(x))
+#define MmioWrite32(x, y)	(*(volatile uint32_t *)(unsigned int)(x) = y)
+#define MmioRead16(x)		(*(volatile uint16_t *)(unsigned int)(x))
+#define MmioWrite16(x, y)	(*(volatile uint16_t *)(unsigned int)(x) = y)
+#define MmioRead8(x)		(*(volatile uint8_t  *)(unsigned int)(x))
+#define MmioWrite8(x, y)	(*(volatile uint8_t  *)(unsigned int)(x) = y)
+
+#define PCIE_MMIO(Bus, Device, Function, Register) \
+				((unsigned int)CONFIG_MMCONF_BASE_ADDRESS + \
+				(unsigned int)(Bus << 20) + \
+				(unsigned int)(Device << 15) + \
+				(unsigned int)(Function << 12) + \
+				(unsigned int)(Register) \
+				)
+
+#endif
diff --git a/src/soc/intel/apollolake/mmap_boot.c b/src/soc/intel/apollolake/mmap_boot.c
old mode 100644
new mode 100755
index bf2e5b9..994f7b8
--- a/src/soc/intel/apollolake/mmap_boot.c
+++ b/src/soc/intel/apollolake/mmap_boot.c
@@ -113,6 +113,7 @@ static void bios_mmap_init(void)
 	car_set_var(bios_size, size);
 }
 
+#if !CONFIG_MULTIPLE_FMAP
 const struct region_device *boot_device_ro(void)
 {
 	bios_mmap_init();
@@ -122,6 +123,7 @@ const struct region_device *boot_device_ro(void)
 
 	return &real_dev_ptr->rdev;
 }
+#endif //CONFIG_MULTIPLE_FMAP
 
 static int iafw_boot_region_properties(struct cbfs_props *props)
 {
diff --git a/src/soc/intel/apollolake/mmap_boot_cse.c b/src/soc/intel/apollolake/mmap_boot_cse.c
new file mode 100755
index 0000000..d5b4526
--- /dev/null
+++ b/src/soc/intel/apollolake/mmap_boot_cse.c
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <boot_device.h>
+#include <cbfs.h>
+#include <commonlib/region.h>
+#include <console/console.h>
+#include <fmap.h>
+#include <soc/bootregion.h>
+#include <soc/intel/common/nvm.h>
+#include <arch/early_variables.h>
+
+/* The ROM is memory mapped just below 4GiB. Form a pointer for the base. */
+#define rom_base(x)    (void *)(uintptr_t)(-(int32_t)(x))
+#define IBBL_ROM_BASE  rom_base(CONFIG_IBBL_ROM_SIZE)
+#define IBBM_ROM_BASE  (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE \
+						- CONFIG_IBBM_ROM_SIZE)
+
+static int curr_boot_region CAR_GLOBAL;
+
+static const struct mem_region_device boot_dev[] = {
+	MEM_REGION_DEV_RO_INIT(IBBL_ROM_BASE, CONFIG_IBBL_ROM_SIZE),
+	MEM_REGION_DEV_RO_INIT(IBBM_ROM_BASE, CONFIG_IBBM_ROM_SIZE),
+	MEM_REGION_DEV_RO_INIT(CONFIG_RAMTOP, CONFIG_ROM_SIZE)
+};
+
+#if CONFIG_MULTIPLE_FMAP
+const struct region_device *boot_device_ro(void)
+{
+	return &boot_dev[car_get_var(curr_boot_region)].rdev;
+}
+#endif //CONFIG_MULTIPLE_FMAP
+
+void set_boot_region(int rgn_idx)
+{
+	if (rgn_idx < sizeof(boot_dev)/sizeof(boot_dev[0]))
+		car_set_var(curr_boot_region, rgn_idx);
+}
diff --git a/src/soc/intel/apollolake/postcar.c b/src/soc/intel/apollolake/postcar.c
index 0b0e4ca..7c24fe9 100755
--- a/src/soc/intel/apollolake/postcar.c
+++ b/src/soc/intel/apollolake/postcar.c
@@ -23,9 +23,19 @@
 #include <soc/postcar.h>
 #include <boot_device.h>
 
+#if CONFIG_MULTIPLE_FMAP
+#include <soc/bootregion.h>
+#endif
+
 void post_car_main(void)
 {
+#if CONFIG_MULTIPLE_FMAP
+	set_boot_region(BOOT_REGION_IBBM);
+	temp_ram_exit();
+	set_boot_region(BOOT_REGION_OBB);
+#else
 	temp_ram_exit();
+#endif
 
 	/* Recover cbmem so infrastruture using it is functional. */
 	cbmem_initialize();
diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c
old mode 100644
new mode 100755
index 1f6a38f..69d7273
--- a/src/soc/intel/apollolake/romstage.c
+++ b/src/soc/intel/apollolake/romstage.c
@@ -41,6 +41,12 @@
 #include <string.h>
 #include <timestamp.h>
 
+#if CONFIG_MULTIPLE_FMAP
+#include <cpu/x86/msr.h>
+#include <soc/cse.h>
+#include <soc/bootregion.h>
+#endif //CONFIG_MULTIPLE_FMAP
+
 static struct chipset_power_state power_state CAR_GLOBAL;
 
 /* High Performance Event Timer Configuration */
@@ -100,6 +106,92 @@ static void migrate_power_state(int is_recovery)
 }
 ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state);
 
+#if CONFIG_MULTIPLE_FMAP
+static void load_ibbm1(uint32_t ibbm_base, uint32_t ibbm_size)
+{
+	uint32_t     state;
+	uint32_t     size;
+	uint8_t      ring_idx;
+	uint32_t     host_to_cse;
+	uint32_t     cse_to_host;
+	uint32_t     chunk_idx;
+	uint32_t     chunk_size;
+	uint32_t     chunk_num;
+	uint32_t     ibb_remaining;
+	uint8_t     *src;
+	uint8_t     *dst;
+	uint8_t     *ptr;
+	msr_t        msr;
+
+	/* Set IBBL cache to UC */
+	msr = rdmsr(0x202);
+	msr.lo &= ~0x0f;
+	wrmsr(0x202, msr);
+
+	/* Init variables */
+	size =  CONFIG_IBBL_ROM_SIZE;
+	dst  =  (uint8_t *)ibbm_base;
+	src  =  (uint8_t *)(~CONFIG_IBBL_ROM_SIZE + 1);
+	memcpy(dst, src, size);
+
+	cse_to_host = CSE_CSE2HOST;
+	host_to_cse = CSE_HOST2CSE;
+	chunk_num   = (cse_to_host >> 28) & 3;
+	if (chunk_num == 3)
+		chunk_num = 4;
+	chunk_size = CSE_IBB_SRAM_SIZE / chunk_num;
+	chunk_idx  = chunk_num;
+
+	/* Send ACK to CSE */
+	ptr  = (uint8_t *)&host_to_cse;
+	*ptr = ((*ptr) & ~0x0f) | (cse_to_host & 0x0f);
+	CSE_HOST2CSE = host_to_cse;
+
+	ibb_remaining = ibbm_size - size;
+	while (ibb_remaining > 0) {
+
+		/* Check whether there is ring buffer ready to copy */
+		state = (cse_to_host ^ host_to_cse) & 0x0F;
+		while (state == 0) {
+			cse_to_host  = CSE_CSE2HOST;
+			state = (cse_to_host ^ host_to_cse) & 0x0F;
+		}
+
+		/* Calculate ring index */
+		ring_idx = (uint8_t)(chunk_idx % chunk_num);
+		if (state & (1 << ring_idx)) {
+			/* Calculate source and dest. address in ring buffer */
+			src += chunk_size;
+			dst += chunk_size;
+			if (src == 0)
+				src  =  (uint8_t *)(~CSE_IBB_SRAM_SIZE + 1);
+			if (ibb_remaining < chunk_size)
+				size = ibb_remaining;
+			else
+				size = chunk_size;
+
+			/* Move data from SRAM into temporary memory */
+			memcpy(dst, src, size);
+			ibb_remaining   -= size;
+
+			/* Send ACK to CSE */
+			ptr  = (uint8_t *)&host_to_cse;
+			*ptr = ((*ptr) & ~(1 << ring_idx)) |
+					(cse_to_host & (1 << ring_idx));
+			CSE_HOST2CSE = host_to_cse;
+
+			chunk_idx++;
+		}
+	}
+	/* Set BIT8 in MSR 0x120 to allow IBB to be executed from
+	* the temporary memory
+	*/
+	msr = rdmsr(0x120);
+	msr.lo |= (1<<8);
+	wrmsr(0x120, msr);
+}
+#endif //CONFIG_MULTIPLE_FMAP
+
 asmlinkage void car_stage_entry(void)
 {
 	struct postcar_frame pcf;
@@ -109,6 +201,10 @@ asmlinkage void car_stage_entry(void)
 	void *smm_base;
 	size_t smm_size;
 	uintptr_t tseg_base;
+#if CONFIG_MULTIPLE_FMAP
+	uint32_t  ibbm_base;
+	uint32_t  ibbm_loaded;
+#endif //CONFIG_MULTIPLE_FMAP
 
 	timestamp_add_now(TS_START_ROMSTAGE);
 
@@ -117,6 +213,18 @@ asmlinkage void car_stage_entry(void)
 
 	console_init();
 
+#if CONFIG_MULTIPLE_FMAP
+	/* Switch to new boot device in CAR */
+	set_boot_region(BOOT_REGION_IBBM);
+
+	/*  load the remaining IBBM */
+	ibbm_loaded = CSE_IBB_SRAM_SIZE - CONFIG_IBBL_ROM_SIZE;
+	ibbm_base   = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE
+		- CONFIG_IBBM_ROM_SIZE;
+	load_ibbm1(ibbm_base + ibbm_loaded,
+				CONFIG_IBBM_ROM_SIZE - ibbm_loaded);
+#endif //CONFIG_MULTIPLE_FMAP
+
 	s3wake = fill_power_state(ps) == ACPI_S3;
 	fsp_memory_init(s3wake);
 	if (postcar_frame_init(&pcf, 1*KiB))



More information about the coreboot-gerrit mailing list