Brenton Dong (brenton.m.dong@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17064
-gerrit
commit 6536e470676da1e0d9b8f6529f84cc11ed3bcd1c Author: Brenton Dong brenton.m.dong@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 Leaf Hill 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 Dong brenton.m.dong@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 | 44 +++++++++ src/soc/intel/apollolake/romstage.c | 108 ++++++++++++++++++++++ 14 files changed, 429 insertions(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc index 127f372..9e25883 100644 --- 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 index 782ca63..fc7eb5c 100644 --- 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 175e20c..02558b4 100644 --- a/src/drivers/intel/fsp2_0/Makefile.inc +++ b/src/drivers/intel/fsp2_0/Makefile.inc @@ -46,6 +46,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) + cbfs-files-$(CONFIG_FSP_CAR) += $(CONFIG_FSP_T_CBFS) $(CONFIG_FSP_T_CBFS)-file := $(call strip_quotes,$(CONFIG_FSP_T_FILE)) $(CONFIG_FSP_T_CBFS)-type := fsp @@ -53,6 +55,9 @@ $(CONFIG_FSP_T_CBFS)-type := fsp 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 index 6c178c3..eeba42a 100644 --- 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 9ae5569..c3b3ebf 100644 --- 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 index 28a9128..22a4d44 100644 --- 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 index d722992..0a184eb 100644 --- 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 100644 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@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 100644 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@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 100644 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 index bf2e5b9..994f7b8 100644 --- 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 100644 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@intel.com for Intel Corp.) + * (Written by Alexandru Gagniuc alexandrux.gagniuc@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 new file mode 100644 index 0000000..7c24fe9 --- /dev/null +++ b/src/soc/intel/apollolake/postcar.c @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Alexandru Gagniuc alexandrux.gagniuc@intel.com for Intel Corp.) + * (Written by Andrey Petrov andrey.petrov@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 <string.h> +#include <cbmem.h> +#include <arch/cpu.h> +#include <arch/stages.h> +#include <fsp/util.h> +#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(); + + copy_and_run(); +} diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c index 1f6a38f..69d7273 100644 --- 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))