the following patch was just integrated into master:
commit 375570e617b04ac967315661098b58231f1dc0cf
Author: Patrick Georgi <pgeorgi(a)google.com>
Date: Mon May 11 19:25:21 2015 +0200
vboot2: Use the right set of compiler flags for building vboot libraries
This make it pass through -fno-stack-protector, and also uses
libverstage fields consistently.
verstage is for 'stage' stuff, libverstage for all the vboot logic.
Change-Id: I3032e072414bed52effd2dc5057896781ad562c6
Signed-off-by: Patrick Georgi <pgeorgi(a)google.com>
Reviewed-on: http://review.coreboot.org/10174
Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
Tested-by: build bot (Jenkins)
See http://review.coreboot.org/10174 for details.
-gerrit
Patrick Georgi (pgeorgi(a)google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10174
-gerrit
commit 97fbf7d2781c85370e83e118af6a4e135fae36cc
Author: Patrick Georgi <pgeorgi(a)google.com>
Date: Mon May 11 19:25:21 2015 +0200
vboot2: Use the right set of compiler flags for building vboot libraries
This make it pass through -fno-stack-protector, and also uses
libverstage fields consistently.
verstage is for 'stage' stuff, libverstage for all the vboot logic.
Change-Id: I3032e072414bed52effd2dc5057896781ad562c6
Signed-off-by: Patrick Georgi <pgeorgi(a)google.com>
---
src/vendorcode/google/chromeos/vboot2/Makefile.inc | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/vendorcode/google/chromeos/vboot2/Makefile.inc b/src/vendorcode/google/chromeos/vboot2/Makefile.inc
index e9377b2..fe1d237 100644
--- a/src/vendorcode/google/chromeos/vboot2/Makefile.inc
+++ b/src/vendorcode/google/chromeos/vboot2/Makefile.inc
@@ -50,7 +50,8 @@ endif
endif # CONFIG_SEPARATE_VERSTAGE
VB2_LIB = $(obj)/external/vboot_reference/vboot_fw20.a
-VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CPPFLAGS_verstage)))
+VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CPPFLAGS_libverstage)))
+VBOOT_CFLAGS += $(CFLAGS_libverstage)
VBOOT_CFLAGS += $(libverstage-c-ccopts)
VBOOT_CFLAGS += -include $(top)/src/include/kconfig.h -Wno-missing-prototypes
VBOOT_CFLAGS += -DVBOOT_DEBUG
Leroy P Leahy (leroy.p.leahy(a)intel.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10116
-gerrit
commit f081dbc59f1dd035fa8cc76a502af9089186a6a7
Author: Lee Leahy <leroy.p.leahy(a)intel.com>
Date: Tue May 5 11:14:02 2015 -0700
FSP 1.1 Comparison Base
Add FSP 1.0 source for comparison with FSP 1.1.
BRANCH=none
BUG=None
TEST=None
Change-Id: I8df349f97acfa74f4de3607d49633da3d4884546
Signed-off-by: Lee Leahy <leroy.p.leahy(a)intel.com>
---
src/drivers/intel/fsp1_1/Kconfig | 145 ++++++++++++
src/drivers/intel/fsp1_1/Makefile.inc | 49 +++++
src/drivers/intel/fsp1_1/cache_as_ram.inc | 177 +++++++++++++++
src/drivers/intel/fsp1_1/fastboot_cache.c | 254 +++++++++++++++++++++
src/drivers/intel/fsp1_1/fsp_util.c | 352 ++++++++++++++++++++++++++++++
src/drivers/intel/fsp1_1/fsp_util.h | 135 ++++++++++++
src/drivers/intel/fsp1_1/fsp_values.h | 41 ++++
src/drivers/intel/fsp1_1/hob.c | 269 +++++++++++++++++++++++
8 files changed, 1422 insertions(+)
diff --git a/src/drivers/intel/fsp1_1/Kconfig b/src/drivers/intel/fsp1_1/Kconfig
new file mode 100644
index 0000000..26ff3e3
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/Kconfig
@@ -0,0 +1,145 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 Sage Electronic Engineering, LLC.
+##
+## 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.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+if PLATFORM_USES_FSP1_1
+
+comment "Intel FSP"
+
+config HAVE_FSP_BIN
+ bool "Use Intel Firmware Support Package"
+ help
+ Select this option to add an Intel FSP binary to
+ the resulting coreboot image.
+
+ Note: Without this binary, coreboot builds relying on the FSP
+ will not boot
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfef00000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x4000
+
+if HAVE_FSP_BIN
+
+config FSP_FILE
+ string "Intel FSP binary path and filename"
+ help
+ The path and filename of the Intel FSP binary for this platform.
+
+config FSP_LOC
+ hex "Intel FSP Binary location in CBFS"
+ help
+ The location in CBFS that the FSP is located. This must match the
+ value that is set in the FSP binary. If the FSP needs to be moved,
+ rebase the FSP with Intel's BCT (tool).
+
+config ENABLE_FSP_FAST_BOOT
+ bool "Enable Fast Boot"
+ select ENABLE_MRC_CACHE
+ default n
+ help
+ Enabling this feature will force the MRC data to be cached in NV
+ storage to be used for speeding up boot time on future reboots
+ and/or power cycles.
+
+config ENABLE_MRC_CACHE
+ bool
+ default y if HAVE_ACPI_RESUME
+ default n
+ help
+ Enabling this feature will cause MRC data to be cached in NV storage.
+ This can either be used for fast boot, or just because the FSP wants
+ it to be saved.
+
+config MRC_CACHE_SIZE
+ hex "Fast Boot Data Cache Size"
+ default 0x10000
+ depends on ENABLE_MRC_CACHE
+ help
+ This is the amount of space in NV storage that is reserved for the
+ fast boot data cache storage.
+
+ WARNING: Because this area will be erased and re-written, the size
+ should be a full sector of the flash ROM chip and nothing else should
+ be included in CBFS in any sector that the fast boot cache data is in.
+
+config OVERRIDE_CACHE_CACHE_LOC
+ bool
+ help
+ Selected by the platform to set a new default location for the
+ MRC/fast boot cache.
+
+config MRC_CACHE_LOC_OVERRIDE
+ hex
+ help
+ Sets the override CBFS location of the MRC/fast boot cache.
+
+config MRC_CACHE_LOC
+ hex "Fast Boot Data Cache location in CBFS"
+ default MRC_CACHE_LOC_OVERRIDE if OVERRIDE_CACHE_CACHE_LOC
+ default 0xfff50000
+ depends on ENABLE_MRC_CACHE
+ help
+ The location in CBFS for the MRC data to be cached.
+
+ WARNING: This should be on a sector boundary of the BIOS ROM chip
+ and nothing else should be included in that sector, or IT WILL BE
+ ERASED.
+
+config VIRTUAL_ROM_SIZE
+ hex "Virtual ROM Size"
+ default ROM_SIZE
+ depends on ENABLE_MRC_CACHE
+ help
+ This is used to calculate the offset of the MRC data cache in NV
+ Storage for fast boot. If in doubt, leave this set to the default
+ which sets the virtual size equal to the ROM size.
+
+ Example: Cougar Canyon 2 has two 8 MB SPI ROMs. When the SPI ROMs are
+ loaded with a 4 MB coreboot image, the virtual ROM size is 8 MB. When
+ the SPI ROMs are loaded with an 8 MB coreboot image, the virtual ROM
+ size is 16 MB.
+
+endif #HAVE_FSP_BIN
+
+config CACHE_ROM_SIZE_OVERRIDE
+ hex "Cache ROM Size"
+ default CBFS_SIZE
+ help
+ This is the size of the cachable area that is passed into the FSP in
+ the early initialization. Typically this should be the size of the CBFS
+ area, but the size must be a power of 2 whereas the CBFS size does not
+ have this limitation.
+
+config USE_GENERIC_FSP_CAR_INC
+ bool
+ default n
+ help
+ The chipset can select this to use a generic cache_as_ram.inc file
+ that should be good for all FSP based platforms.
+
+config FSP_USES_UPD
+ bool
+ default n
+ help
+ If this FSP uses UPD/VPD data regions, select this in the chipset Kconfig.
+endif #PLATFORM_USES_FSP1_1
diff --git a/src/drivers/intel/fsp1_1/Makefile.inc b/src/drivers/intel/fsp1_1/Makefile.inc
new file mode 100644
index 0000000..4931cb7
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/Makefile.inc
@@ -0,0 +1,49 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2014 Sage Electronic Engineering, LLC.
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+ramstage-y += fsp_util.c hob.c
+romstage-y += fsp_util.c hob.c
+
+ramstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+romstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+
+CPPFLAGS_common += -Isrc/drivers/intel/fsp1_0
+
+ifeq ($(CONFIG_USE_GENERIC_FSP_CAR_INC),y)
+cpu_incs += $(src)/drivers/intel/fsp1_0/cache_as_ram.inc
+endif
+
+ifeq ($(CONFIG_HAVE_FSP_BIN),y)
+cbfs-files-y += fsp.bin
+fsp.bin-file := $(call strip_quotes,$(CONFIG_FSP_FILE))
+fsp.bin-position := $(CONFIG_FSP_LOC)
+fsp.bin-type := fsp
+endif
+
+ifeq ($(CONFIG_ENABLE_MRC_CACHE),y)
+$(obj)/mrc.cache:
+ dd if=/dev/zero count=1 \
+ bs=$(shell printf "%d" $(CONFIG_MRC_CACHE_SIZE) ) | \
+ tr '\000' '\377' > $@
+
+cbfs-files-y += mrc.cache
+mrc.cache-file := $(obj)/mrc.cache
+mrc.cache-position := $(CONFIG_MRC_CACHE_LOC)
+mrc.cache-type := mrc_cache
+endif
diff --git a/src/drivers/intel/fsp1_1/cache_as_ram.inc b/src/drivers/intel/fsp1_1/cache_as_ram.inc
new file mode 100644
index 0000000..8604c3b
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/cache_as_ram.inc
@@ -0,0 +1,177 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich(a)gmail.com>
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/post_code.h>
+#include <microcode_size.h>
+#include <cbmem.h>
+
+#ifndef CONFIG_FSP_LOC
+# error "CONFIG_FSP_LOC must be set."
+#endif
+
+#ifndef CONFIG_POST_IO
+# error "CONFIG_POST_IO must be set."
+#endif
+
+#if CONFIG_POST_IO
+# ifndef CONFIG_POST_IO_PORT
+# error "CONFIG_POST_IO_PORT must be set."
+# endif
+#endif
+
+#ifndef CONFIG_CPU_MICROCODE_CBFS_LOC
+# error "CONFIG_CPU_MICROCODE_CBFS_LOC must be set."
+#endif
+
+#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */
+
+ cmp $0, %eax
+ jne bisthalt
+
+cache_as_ram:
+ post_code(0x20)
+
+ /*
+ * Find the FSP binary in cbfs.
+ * Make a fake stack that has the return value back to this code.
+ */
+ lea fake_fsp_stack, %esp
+ jmp find_fsp
+find_fsp_ret:
+ /* Save the FSP location */
+ mov %eax, %ebp
+ cmp $CONFIG_FSP_LOC, %eax
+ jb halt1
+
+ post_code(0x22)
+
+ /* Calculate entry into FSP */
+ mov 0x30(%ebp), %eax /* Load TempRamInitEntry */
+ add 0x1c(%ebp), %eax /* add in the offset for the FSP base address */
+
+ /*
+ * Pass early init variables on a fake stack (no memory yet)
+ * as well as the return location
+ */
+ lea CAR_init_stack, %esp
+
+ /* call FSP binary to setup temporary stack */
+ jmp *%eax
+
+CAR_init_done:
+ addl $4, %esp
+ cmp $0, %eax
+ jne halt2
+
+ /* Save FSP_INFO_HEADER location in ebx */
+ mov %ebp, %ebx
+
+ /*
+ * set up bootloader stack
+ * ecx: stack base
+ * edx: stack top
+ */
+ mov %edx, %esp
+ movl %esp, %ebp
+
+ /* Clear the cbmem CAR memory region. */
+ movl %ecx, %edi
+ movl %edx, %ecx
+ sub %edi, %ecx
+ shr $2, %ecx
+ xorl %eax, %eax
+ rep stosl
+
+before_romstage:
+ post_code(0x23)
+
+ /* Call romstage.c main function. */
+ pushl %ebx /* main takes FSP_INFO_HEADER as its argument */
+ call main /* does not return */
+ movb $0xB8, %ah
+ jmp .Lhlt
+
+bisthalt:
+ movb $0xB9, %ah
+ jmp .Lhlt
+
+halt1:
+ /*
+ * Failures for postcode 0xBA - failed in find_fsp()
+ *
+ * Values are:
+ * 0x01 - FV signature, "_FVH" not present
+ * 0x02 - FFS GUID not present
+ * 0x03 - FSP INFO Header not found
+ * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased to
+ * a different location, or does it need to be?
+ * 0x05 - FSP INFO Header signature "FSPH" not found
+ * 0x06 - FSP Image ID is not the expected ID.
+ */
+ movb $0xBA, %ah
+ jmp .Lhlt
+
+halt2:
+ /*
+ * Failures for postcode 0xBB - failed in the FSP:
+ *
+ * 0x00 - FSP_SUCCESS: Temp RAM was initialized successfully.
+ * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid.
+ * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode region.
+ * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met.
+ * 0x07 - FSP_DEVICE_ERROR: Temp RAM initialization failed
+ * 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked
+ */
+ movb $0xBB, %ah
+
+.Lhlt:
+ xchg %al, %ah
+#if CONFIG_POST_IO
+ outb %al, $CONFIG_POST_IO_PORT
+#else
+ post_code(POST_DEAD_CODE)
+#endif
+ movl $LHLT_DELAY, %ecx
+.Lhlt_Delay:
+ outb %al, $0xED
+ loop .Lhlt_Delay
+ jmp .Lhlt
+
+/*
+ * esp is set to this location so that the call into and return from the FSP
+ * in find_fsp will work.
+ */
+ .align 4
+fake_fsp_stack:
+ .long find_fsp_ret
+
+CAR_init_params:
+ .long CONFIG_CPU_MICROCODE_CBFS_LOC
+ .long MICROCODE_REGION_LENGTH
+ .long 0xFFFFFFFF - CACHE_ROM_SIZE + 1 /* Firmware Location */
+ .long CACHE_ROM_SIZE /* Total Firmware Length */
+
+CAR_init_stack:
+ .long CAR_init_done
+ .long CAR_init_params
+
diff --git a/src/drivers/intel/fsp1_1/fastboot_cache.c b/src/drivers/intel/fsp1_1/fastboot_cache.c
new file mode 100644
index 0000000..e8651bb
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fastboot_cache.c
@@ -0,0 +1,254 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <bootstate.h>
+#include <console/console.h>
+#include <cbfs.h>
+#include <ip_checksum.h>
+#include <device/device.h>
+#include <cbmem.h>
+#include <spi-generic.h>
+#include <spi_flash.h>
+#include <lib.h> // hexdump
+#include "fsp_util.h"
+
+#ifndef CONFIG_VIRTUAL_ROM_SIZE
+#error "CONFIG_VIRTUAL_ROM_SIZE must be set."
+#endif
+
+/* convert a pointer to flash area into the offset inside the flash */
+static inline u32 to_flash_offset(void *p) {
+ return ((u32)p + CONFIG_VIRTUAL_ROM_SIZE);
+}
+
+static struct mrc_data_container *next_mrc_block(
+ struct mrc_data_container *mrc_cache)
+{
+ /* MRC data blocks are aligned within the region */
+ u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->mrc_data_size;
+ if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
+ mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
+ mrc_size += MRC_DATA_ALIGN;
+ }
+
+ u8 *region_ptr = (u8*)mrc_cache;
+ region_ptr += mrc_size;
+ return (struct mrc_data_container *)region_ptr;
+}
+
+static int is_mrc_cache(struct mrc_data_container *mrc_cache)
+{
+ return (!!mrc_cache) && (mrc_cache->mrc_signature == MRC_DATA_SIGNATURE);
+}
+
+static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
+{
+ size_t region_size;
+ *mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
+ "mrc.cache",
+ CBFS_TYPE_MRC_CACHE,
+ ®ion_size);
+
+ return region_size;
+}
+
+/*
+ * Find the largest index block in the MRC cache. Return NULL if none is
+ * found.
+ */
+static struct mrc_data_container *find_current_mrc_cache_local
+ (struct mrc_data_container *mrc_cache, u32 region_size)
+{
+ u32 region_end;
+ u32 entry_id = 0;
+ struct mrc_data_container *mrc_next = mrc_cache;
+
+ region_end = (u32) mrc_cache + region_size;
+
+ /* Search for the last filled entry in the region */
+ while (is_mrc_cache(mrc_next)) {
+ entry_id++;
+ mrc_cache = mrc_next;
+ mrc_next = next_mrc_block(mrc_next);
+ if ((u32)mrc_next >= region_end) {
+ /* Stay in the MRC data region */
+ break;
+ }
+ }
+
+ if (entry_id == 0) {
+ printk(BIOS_ERR, "%s: No valid fast boot cache found.\n", __func__);
+ return NULL;
+ }
+
+ /* Verify checksum */
+ if (mrc_cache->mrc_checksum !=
+ compute_ip_checksum(mrc_cache->mrc_data,
+ mrc_cache->mrc_data_size)) {
+ printk(BIOS_ERR, "%s: fast boot cache checksum mismatch\n", __func__);
+ return NULL;
+ }
+
+ printk(BIOS_DEBUG, "%s: picked entry %u from cache block\n", __func__,
+ entry_id - 1);
+
+ return mrc_cache;
+}
+
+/* SPI code needs malloc/free.
+ * Also unknown if writing flash from XIP-flash code is a good idea
+ */
+#if !defined(__PRE_RAM__)
+/* find the first empty block in the MRC cache area.
+ * If there's none, return NULL.
+ *
+ * @mrc_cache_base - base address of the MRC cache area
+ * @mrc_cache - current entry (for which we need to find next)
+ * @region_size - total size of the MRC cache area
+ */
+static struct mrc_data_container *find_next_mrc_cache
+ (struct mrc_data_container *mrc_cache_base,
+ struct mrc_data_container *mrc_cache,
+ u32 region_size)
+{
+ u32 region_end = (u32) mrc_cache_base + region_size;
+ u32 mrc_data_size = mrc_cache->mrc_data_size;
+
+ mrc_cache = next_mrc_block(mrc_cache);
+ if (((u32)mrc_cache + mrc_data_size) >= region_end) {
+ /* Crossed the boundary */
+ mrc_cache = NULL;
+ printk(BIOS_DEBUG, "%s: no available entries found\n",
+ __func__);
+ } else {
+ printk(BIOS_DEBUG,
+ "%s: picked next entry from cache block at %p\n",
+ __func__, mrc_cache);
+ }
+
+ return mrc_cache;
+}
+
+void update_mrc_cache(void *unused)
+{
+ printk(BIOS_DEBUG, "Updating fast boot cache data.\n");
+ struct mrc_data_container *current = cbmem_find(CBMEM_ID_MRCDATA);
+ struct mrc_data_container *cache, *cache_base;
+ u32 cache_size;
+
+ if (!current) {
+ printk(BIOS_ERR, "No fast boot cache in cbmem. Can't update flash.\n");
+ return;
+ }
+ if (current->mrc_data_size == -1) {
+ printk(BIOS_ERR, "Fast boot cache data in cbmem invalid.\n");
+ return;
+ }
+
+ cache_size = get_mrc_cache_region(&cache_base);
+ if (cache_base == NULL) {
+ printk(BIOS_ERR, "%s: could not find fast boot cache area\n",
+ __func__);
+ return;
+ }
+
+ /*
+ * we need to:
+ * 0. compare MRC data to last mrc-cache block (exit if same)
+ */
+ cache = find_current_mrc_cache_local(cache_base, cache_size);
+
+ if (cache && (cache->mrc_data_size == current->mrc_data_size) &&
+ (memcmp(cache, current, cache->mrc_data_size) == 0)) {
+ printk(BIOS_DEBUG,
+ "MRC data in flash is up to date. No update.\n");
+ return;
+ }
+
+ /* 1. use spi_flash_probe() to find the flash, then... */
+ spi_init();
+ struct spi_flash *flash = spi_flash_probe(0, 0);
+ if (!flash) {
+ printk(BIOS_DEBUG, "Could not find SPI device\n");
+ return;
+ }
+
+ /* 2. look up the first unused block */
+ if (cache)
+ cache = find_next_mrc_cache(cache_base, cache, cache_size);
+
+ /*
+ * 3. if no such place exists, erase entire mrc-cache range & use
+ * block 0. First time around the erase is not needed, but this is a
+ * small overhead for simpler code.
+ */
+ if (!cache) {
+ printk(BIOS_DEBUG,
+ "Need to erase the MRC cache region of %d bytes at %p\n",
+ cache_size, cache_base);
+
+ flash->erase(flash, to_flash_offset(cache_base), cache_size);
+
+ /* we will start at the beginning again */
+ cache = cache_base;
+ }
+ /* 4. write mrc data with flash->write() */
+ printk(BIOS_DEBUG, "Write MRC cache update to flash at %p\n",
+ cache);
+ flash->write(flash, to_flash_offset(cache),
+ current->mrc_data_size + sizeof(*current), current);
+}
+
+#endif /* !defined(__PRE_RAM__) */
+
+void * find_and_set_fastboot_cache(void)
+{
+ struct mrc_data_container *mrc_cache = NULL;
+ if (((mrc_cache = find_current_mrc_cache()) == NULL) ||
+ (mrc_cache->mrc_data_size == -1UL)) {
+ printk(BIOS_DEBUG, "FSP MRC cache not present.\n");
+ return NULL;
+ }
+ printk(BIOS_DEBUG, "FSP MRC cache present at %x.\n", (u32)mrc_cache);
+ printk(BIOS_SPEW, "Saved MRC data:\n");
+ hexdump32(BIOS_SPEW, (void *)mrc_cache->mrc_data, (mrc_cache->mrc_data_size) / 4);
+ return (void *) mrc_cache->mrc_data;
+}
+
+struct mrc_data_container *find_current_mrc_cache(void)
+{
+ struct mrc_data_container *cache_base;
+ u32 cache_size;
+
+ cache_size = get_mrc_cache_region(&cache_base);
+ if (cache_base == NULL) {
+ printk(BIOS_ERR, "%s: could not find fast boot cache area\n",
+ __func__);
+ return NULL;
+ }
+
+ /*
+ * we need to:
+ * 0. compare MRC data to last mrc-cache block (exit if same)
+ */
+ return find_current_mrc_cache_local(cache_base, cache_size);
+}
diff --git a/src/drivers/intel/fsp1_1/fsp_util.c b/src/drivers/intel/fsp1_1/fsp_util.c
new file mode 100644
index 0000000..3147b67
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_util.c
@@ -0,0 +1,352 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <bootstate.h>
+#include <cbmem.h>
+#include "fsp_util.h"
+#include <lib.h> // hexdump
+#include <ip_checksum.h>
+#include <timestamp.h>
+
+#ifndef __PRE_RAM__
+/* Globals pointers for FSP structures */
+void *FspHobListPtr = NULL;
+FSP_INFO_HEADER *fsp_header_ptr = NULL;
+
+void FspNotify (u32 Phase)
+{
+ FSP_NOTFY_PHASE NotifyPhaseProc;
+ NOTIFY_PHASE_PARAMS NotifyPhaseParams;
+ EFI_STATUS Status;
+
+ if (fsp_header_ptr == NULL) {
+ fsp_header_ptr = (void *)find_fsp();
+ if ((u32)fsp_header_ptr < 0xff) {
+ post_code(0x4F); /* output something in case there is no serial */
+ die("Can't find the FSP!\n");
+ }
+ }
+
+ /* call FSP PEI to Notify PostPciEnumeration */
+ NotifyPhaseProc = (FSP_NOTFY_PHASE)(fsp_header_ptr->ImageBase +
+ fsp_header_ptr->NotifyPhaseEntry);
+ NotifyPhaseParams.Phase = Phase;
+
+ timestamp_add_now(Phase == EnumInitPhaseReadyToBoot ?
+ TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
+
+ Status = NotifyPhaseProc (&NotifyPhaseParams);
+
+ timestamp_add_now(Phase == EnumInitPhaseReadyToBoot ?
+ TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
+
+ if (Status != 0)
+ printk(BIOS_ERR,"FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n", Phase, Status);
+}
+#endif /* #ifndef __PRE_RAM__ */
+
+#ifdef __PRE_RAM__
+
+/*
+ * Call the FSP to do memory init. The FSP doesn't return to this function.
+ * The FSP returns to the romstage_main_continue().
+ */
+void __attribute__ ((noreturn)) fsp_early_init (FSP_INFO_HEADER *fsp_ptr)
+{
+ FSP_FSP_INIT FspInitApi;
+ FSP_INIT_PARAMS FspInitParams;
+ FSP_INIT_RT_BUFFER FspRtBuffer;
+#if IS_ENABLED(CONFIG_FSP_USES_UPD)
+ UPD_DATA_REGION fsp_upd_data;
+#endif
+
+ memset((void*)&FspRtBuffer, 0, sizeof(FSP_INIT_RT_BUFFER));
+ FspRtBuffer.Common.StackTop = (u32 *)CONFIG_RAMTOP;
+ FspInitParams.NvsBufferPtr = NULL;
+
+#if IS_ENABLED(CONFIG_FSP_USES_UPD)
+ FspRtBuffer.Common.UpdDataRgnPtr = &fsp_upd_data;
+#endif
+ FspInitParams.RtBufferPtr = (FSP_INIT_RT_BUFFER *)&FspRtBuffer;
+ FspInitParams.ContinuationFunc = (CONTINUATION_PROC)ChipsetFspReturnPoint;
+ FspInitApi = (FSP_FSP_INIT)(fsp_ptr->ImageBase + fsp_ptr->FspInitEntry);
+
+ /* Call the chipset code to fill in the chipset specific structures */
+ chipset_fsp_early_init(&FspInitParams, fsp_ptr);
+
+ /* Call back to romstage for board specific changes */
+ romstage_fsp_rt_buffer_callback(&FspRtBuffer);
+
+ FspInitApi(&FspInitParams);
+
+ /* Should never return. Control will continue from ContinuationFunc */
+ die("Uh Oh! FspInitApi returned");
+}
+#endif /* __PRE_RAM__ */
+
+volatile u8 * find_fsp ()
+{
+
+#ifdef __PRE_RAM__
+ volatile register u8 *fsp_ptr asm ("eax");
+
+ /* Entry point for CAR assembly routine */
+ __asm__ __volatile__ (
+ ".global find_fsp\n\t"
+ "find_fsp:\n\t"
+ );
+#else
+ volatile u8 *fsp_ptr;
+#endif /* __PRE_RAM__ */
+
+#ifndef CONFIG_FSP_LOC
+#error "CONFIG_FSP_LOC must be set."
+#endif
+
+ /* The FSP is stored in CBFS */
+ fsp_ptr = (u8 *) CONFIG_FSP_LOC;
+
+ /* Check the FV signature, _FVH */
+ if (((EFI_FIRMWARE_VOLUME_HEADER *)fsp_ptr)->Signature == 0x4856465F) {
+ /* Go to the end of the FV header and align the address. */
+ fsp_ptr += ((EFI_FIRMWARE_VOLUME_HEADER *)fsp_ptr)->ExtHeaderOffset;
+ fsp_ptr += ((EFI_FIRMWARE_VOLUME_EXT_HEADER *)fsp_ptr)->ExtHeaderSize;
+ fsp_ptr = (u8 *)(((u32)fsp_ptr + 7) & 0xFFFFFFF8);
+ } else {
+ fsp_ptr = (u8*)ERROR_NO_FV_SIG;
+ }
+
+ /* Check the FFS GUID */
+ if (((u32)fsp_ptr > 0xff) &&
+ (((u32 *)&(((EFI_FFS_FILE_HEADER *)fsp_ptr)->Name))[0] == 0x912740BE) &&
+ (((u32 *)&(((EFI_FFS_FILE_HEADER *)fsp_ptr)->Name))[1] == 0x47342284) &&
+ (((u32 *)&(((EFI_FFS_FILE_HEADER *)fsp_ptr)->Name))[2] == 0xB08471B9) &&
+ (((u32 *)&(((EFI_FFS_FILE_HEADER *)fsp_ptr)->Name))[3] == 0x0C3F3527)) {
+ /* Add the FFS Header size to the base to find the Raw section Header */
+ fsp_ptr += sizeof(EFI_FFS_FILE_HEADER);
+ } else {
+ fsp_ptr = (u8 *)ERROR_NO_FFS_GUID;
+ }
+
+ if (((u32)fsp_ptr > 0xff) &&
+ ((EFI_RAW_SECTION *)fsp_ptr)->Type == EFI_SECTION_RAW) {
+ /* Add the Raw Header size to the base to find the FSP INFO Header */
+ fsp_ptr += sizeof(EFI_RAW_SECTION);
+ } else {
+ fsp_ptr = (u8 *)ERROR_NO_INFO_HEADER;
+ }
+
+ /* Verify that the FSP is set to the base address we're expecting.*/
+ if (((u32)fsp_ptr > 0xff) &&
+ (*(u32*)(fsp_ptr + FSP_IMAGE_BASE_LOC) != CONFIG_FSP_LOC)) {
+ fsp_ptr = (u8 *)ERROR_IMAGEBASE_MISMATCH;
+ }
+
+ /* Verify the FSP Signature */
+ if (((u32)fsp_ptr > 0xff) &&
+ (*(u32*)(fsp_ptr + FSP_IMAGE_SIG_LOC) != FSP_SIG)){
+ fsp_ptr = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
+ }
+
+ /* Verify the FSP ID */
+ if (((u32)fsp_ptr > 0xff) &&
+ ((*(u32 *)(fsp_ptr + FSP_IMAGE_ID_LOC) != FSP_IMAGE_ID_DWORD0) ||
+ (*(u32 *)(fsp_ptr + (FSP_IMAGE_ID_LOC + 4)) != FSP_IMAGE_ID_DWORD1))) {
+ fsp_ptr = (u8 *)ERROR_FSP_SIG_MISMATCH;
+ }
+
+ return (fsp_ptr);
+}
+
+/** finds the saved temporary memory information in the FSP HOB list
+ *
+ * @param hob_list_ptr pointer to the start of the hob list
+ * @return pointer to saved CAR MEM or NULL if not found.
+ */
+void * find_saved_temp_mem(void *hob_list_ptr)
+{
+ EFI_GUID temp_hob_guid = FSP_BOOTLOADER_TEMPORARY_MEMORY_HOB_GUID;
+ EFI_HOB_GUID_TYPE *saved_mem_hob =
+ (EFI_HOB_GUID_TYPE *) find_hob_by_guid(
+ hob_list_ptr, &temp_hob_guid);
+
+ if (saved_mem_hob == NULL)
+ return NULL;
+
+ return (void *) ((char *) saved_mem_hob + sizeof(EFI_HOB_GUID_TYPE));
+}
+
+#ifndef FSP_RESERVE_MEMORY_SIZE
+/** @brief locates the HOB containing the location of the fsp reserved mem area
+ *
+ * @param hob_list_ptr pointer to the start of the hob list
+ * @return pointer to the start of the FSP reserved memory or NULL if not found.
+ */
+void * find_fsp_reserved_mem(void *hob_list_ptr)
+{
+ EFI_GUID fsp_reserved_guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
+ EFI_HOB_RESOURCE_DESCRIPTOR *fsp_reserved_mem =
+ (EFI_HOB_RESOURCE_DESCRIPTOR *) find_hob_by_guid(
+ hob_list_ptr, &fsp_reserved_guid);
+
+ if (fsp_reserved_mem == NULL)
+ return NULL;
+
+ return (void *)((uintptr_t)fsp_reserved_mem->PhysicalStart);
+}
+#endif /* FSP_RESERVE_MEMORY_SIZE */
+
+#ifndef __PRE_RAM__ /* Only parse HOB data in ramstage */
+
+void print_fsp_info(void) {
+
+ if (fsp_header_ptr == NULL)
+ fsp_header_ptr = (void *)find_fsp();
+ if ((u32)fsp_header_ptr < 0xff) {
+ post_code(0x4F); /* output something in case there is no serial */
+ die("Can't find the FSP!\n");
+ }
+
+ if (FspHobListPtr == NULL) {
+ FspHobListPtr = (void*)*((u32*) cbmem_find(CBMEM_ID_HOB_POINTER));
+ }
+
+ printk(BIOS_SPEW,"fsp_header_ptr: %p\n", fsp_header_ptr);
+ printk(BIOS_INFO,"FSP Header Version: %d\n", fsp_header_ptr->HeaderRevision);
+ printk(BIOS_INFO,"FSP Revision: %d.%d\n",
+ (u8)((fsp_header_ptr->ImageRevision >> 8) & 0xff),
+ (u8)(fsp_header_ptr->ImageRevision & 0xff));
+}
+
+
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+/**
+ * Save the FSP memory HOB (mrc data) to the MRC area in CBMEM
+ */
+int save_mrc_data(void *hob_start)
+{
+ u32 *mrc_hob;
+ u32 *mrc_hob_data;
+ u32 mrc_hob_size;
+ struct mrc_data_container *mrc_data;
+ int output_len;
+ const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
+
+ mrc_hob = GetNextGuidHob(&mrc_guid, hob_start);
+ if (mrc_hob == NULL){
+ printk(BIOS_DEBUG, "Memory Configure Data Hob is not present\n");
+ return(0);
+ }
+
+ mrc_hob_data = GET_GUID_HOB_DATA (mrc_hob);
+ mrc_hob_size = (u32) GET_HOB_LENGTH(mrc_hob);
+
+ printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n",
+ (void *)mrc_hob_data, mrc_hob_size);
+
+ output_len = ALIGN(mrc_hob_size, 16);
+
+ /* Save the MRC S3/fast boot/ADR restore data to cbmem */
+ mrc_data = cbmem_add (CBMEM_ID_MRCDATA,
+ output_len + sizeof(struct mrc_data_container));
+
+ /* Just return if there was a problem with getting CBMEM */
+ if (mrc_data == NULL) {
+ printk(BIOS_WARNING, "CBMEM was not available to save the fast boot cache data.\n");
+ return 0;
+ }
+
+ printk(BIOS_DEBUG, "Copy FSP MRC DATA to HOB (source addr %p, dest addr %p, %u bytes)\n",
+ (void *)mrc_hob_data, mrc_data, output_len);
+
+ mrc_data->mrc_signature = MRC_DATA_SIGNATURE;
+ mrc_data->mrc_data_size = output_len;
+ mrc_data->reserved = 0;
+ memcpy(mrc_data->mrc_data, (const void *)mrc_hob_data, mrc_hob_size);
+
+ /* Zero the unused space in aligned buffer. */
+ if (output_len > mrc_hob_size)
+ memset((mrc_data->mrc_data + mrc_hob_size), 0,
+ output_len - mrc_hob_size);
+
+ mrc_data->mrc_checksum = compute_ip_checksum(mrc_data->mrc_data,
+ mrc_data->mrc_data_size);
+
+ printk(BIOS_SPEW, "Fast boot data (includes align and checksum):\n");
+ hexdump32(BIOS_SPEW, (void *)mrc_data->mrc_data, output_len / 4);
+ return (1);
+}
+#endif /* CONFIG_ENABLE_MRC_CACHE */
+
+static void find_fsp_hob_update_mrc(void *unused)
+{
+ /* Set the global HOB list pointer */
+ FspHobListPtr = (void*)*((u32*) cbmem_find(CBMEM_ID_HOB_POINTER));
+
+ if (!FspHobListPtr){
+ printk(BIOS_ERR, "ERROR: Could not find FSP HOB pointer in CBFS!\n");
+ } else {
+ /* 0x0000: Print all types */
+ print_hob_type_structure(0x000, FspHobListPtr);
+
+ #if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+ if(save_mrc_data(FspHobListPtr))
+ update_mrc_cache(NULL);
+ else
+ printk(BIOS_DEBUG,"Not updating MRC data in flash.\n");
+ #endif
+ }
+}
+
+/** @brief Notify FSP for PostPciEnumeration
+ *
+ * @param unused
+ */
+static void fsp_after_pci_enum(void *unused)
+{
+ /* This call needs to be done before resource allocation. */
+ printk(BIOS_DEBUG, "FspNotify(EnumInitPhaseAfterPciEnumeration)\n");
+ FspNotify(EnumInitPhaseAfterPciEnumeration);
+ printk(BIOS_DEBUG,
+ "Returned from FspNotify(EnumInitPhaseAfterPciEnumeration)\n");
+}
+
+/** @brief Notify FSP for ReadyToBoot
+ *
+ * @param unused
+ */
+static void fsp_finalize(void *unused)
+{
+ printk(BIOS_DEBUG, "FspNotify(EnumInitPhaseReadyToBoot)\n");
+ print_fsp_info();
+ FspNotify(EnumInitPhaseReadyToBoot);
+ printk(BIOS_DEBUG, "Returned from FspNotify(EnumInitPhaseReadyToBoot)\n");
+}
+
+/* Set up for the ramstage FSP calls */
+BOOT_STATE_INIT_ENTRY(BS_DEV_ENUMERATE, BS_ON_EXIT, fsp_after_pci_enum, NULL);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, fsp_finalize, NULL);
+
+/* Update the MRC/fast boot cache as part of the late table writing stage */
+BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
+ find_fsp_hob_update_mrc, NULL);
+#endif /* #ifndef __PRE_RAM__ */
diff --git a/src/drivers/intel/fsp1_1/fsp_util.h b/src/drivers/intel/fsp1_1/fsp_util.h
new file mode 100644
index 0000000..d65b842
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_util.h
@@ -0,0 +1,135 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FSP_UTIL_H
+#define FSP_UTIL_H
+
+#include <chipset_fsp_util.h>
+#include "fsp_values.h"
+
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+int save_mrc_data(void *hob_start);
+void * find_and_set_fastboot_cache(void);
+#endif
+
+volatile u8 * find_fsp (void);
+void fsp_early_init(FSP_INFO_HEADER *fsp_info);
+void FspNotify(u32 Phase);
+void FspNotifyReturnPoint(EFI_STATUS Status, VOID *HobListPtr);
+void romstage_fsp_rt_buffer_callback(FSP_INIT_RT_BUFFER *FspRtBuffer);
+void print_fsp_info(void);
+void chipset_fsp_early_init(FSP_INIT_PARAMS *FspInitParams,
+ FSP_INFO_HEADER *fsp_ptr);
+void ChipsetFspReturnPoint(EFI_STATUS Status, VOID *HobListPtr);
+void * find_saved_temp_mem(void *hob_list_ptr);
+void * find_fsp_reserved_mem(void *hob_list_ptr);
+
+/* functions in hob.c */
+void print_hob_mem_attributes(void *Hobptr);
+void print_hob_type_structure(u16 Hobtype, void *Hoblistptr);
+void print_hob_resource_attributes(void *Hobptr);
+void print_guid_type_attributes(void *Hobptr);
+const char * get_hob_type_string(void *Hobptr);
+void * find_hob_by_guid(void *Hoblistptr, EFI_GUID *guid1);
+uint8_t guids_are_equal(EFI_GUID *guid1, EFI_GUID *guid2);
+void printguid(EFI_GUID *guid);
+
+/* Additional HOB types not included in the FSP:
+ * #define EFI_HOB_TYPE_HANDOFF 0x0001
+ * #define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002
+ * #define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003
+ * #define EFI_HOB_TYPE_GUID_EXTENSION 0x0004
+ * #define EFI_HOB_TYPE_FV 0x0005
+ * #define EFI_HOB_TYPE_CPU 0x0006
+ * #define EFI_HOB_TYPE_MEMORY_POOL 0x0007
+ * #define EFI_HOB_TYPE_CV 0x0008
+ * #define EFI_HOB_TYPE_UNUSED 0xFFFE
+ * #define EFI_HOB_TYPE_END_OF_HOB_LIST 0xffff
+ */
+#define EFI_HOB_TYPE_HANDOFF 0x0001
+#define EFI_HOB_TYPE_MEMORY_POOL 0x0007
+
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+#define MRC_DATA_ALIGN 0x1000
+#define MRC_DATA_SIGNATURE (('M'<<0)|('R'<<8)|('C'<<16)|('D'<<24))
+
+struct mrc_data_container {
+ u32 mrc_signature; // "MRCD"
+ u32 mrc_data_size; // Actual total size of this structure
+ u32 mrc_checksum; // IP style checksum
+ u32 reserved; // For header alignment
+ u8 mrc_data[0]; // Variable size, platform/run time dependent.
+} __attribute__ ((packed));
+
+struct mrc_data_container *find_current_mrc_cache(void);
+
+#if !defined(__PRE_RAM__)
+void update_mrc_cache(void *unused);
+#endif
+
+#endif
+
+/* The offset in bytes from the start of the info structure */
+#define FSP_IMAGE_SIG_LOC 0
+#define FSP_IMAGE_ID_LOC 16
+#define FSP_IMAGE_BASE_LOC 28
+
+#define FSP_SIG 0x48505346 /* 'FSPH' */
+
+#define ERROR_NO_FV_SIG 1
+#define ERROR_NO_FFS_GUID 2
+#define ERROR_NO_INFO_HEADER 3
+#define ERROR_IMAGEBASE_MISMATCH 4
+#define ERROR_INFO_HEAD_SIG_MISMATCH 5
+#define ERROR_FSP_SIG_MISMATCH 6
+
+#ifndef __PRE_RAM__
+extern void *FspHobListPtr;
+#endif
+
+#define UPD_DEFAULT_CHECK(member) \
+ if (config->member != UPD_DEFAULT) { \
+ UpdData->member = config->member - 1; \
+ } \
+ printk(FSP_INFO_LEVEL, #member ":\t\t0x%02x %s\n", UpdData->member, \
+ config->member ? "(set)" : "(default)");
+
+#define UPD_SPD_CHECK(member) \
+ if (config->member == UPD_SPD_ADDR_DISABLED) { \
+ UpdData->member = 0x00; \
+ } else if (config->member != UPD_SPD_ADDR_DEFAULT) { \
+ UpdData->member = config->member; \
+ } \
+ printk(FSP_INFO_LEVEL, #member ":\t\t0x%02x %s\n", UpdData->member, \
+ config->member ? "(set)" : "(default)");
+
+#define UPD_DEVICE_CHECK(devicename, member, statement) \
+ case devicename: \
+ UpdData->member = dev->enabled; \
+ printk(FSP_INFO_LEVEL, statement "%s\n", \
+ UpdData->member?"Enabled":"Disabled"); \
+ break;
+
+
+#ifndef FSP_BOOTLOADER_TEMPORARY_MEMORY_HOB_GUID
+#define FSP_BOOTLOADER_TEMPORARY_MEMORY_HOB_GUID \
+ { 0xbbcff46c, 0xc8d3, 0x4113, { 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } };
+#endif
+
+#endif /* FSP_UTIL_H */
diff --git a/src/drivers/intel/fsp1_1/fsp_values.h b/src/drivers/intel/fsp1_1/fsp_values.h
new file mode 100644
index 0000000..e5098bb
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_values.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FSP_VALUES_H
+#define FSP_VALUES_H
+
+#ifndef FSP_DEBUG_LEVEL
+# define FSP_DEBUG_LEVEL BIOS_SPEW
+#endif
+
+#ifndef FSP_INFO_LEVEL
+# define FSP_INFO_LEVEL BIOS_DEBUG
+#endif
+
+#define INCREMENT_FOR_DEFAULT(x) (x+1)
+
+#define UPD_DEFAULT 0x00
+#define UPD_DISABLE INCREMENT_FOR_DEFAULT(0)
+#define UPD_ENABLE INCREMENT_FOR_DEFAULT(1)
+#define UPD_USE_DEVICETREE 0xff
+
+#define UPD_SPD_ADDR_DEFAULT UPD_DEFAULT
+#define UPD_SPD_ADDR_DISABLED 0xFF
+
+#endif
diff --git a/src/drivers/intel/fsp1_1/hob.c b/src/drivers/intel/fsp1_1/hob.c
new file mode 100644
index 0000000..99c4ba1
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/hob.c
@@ -0,0 +1,269 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <lib.h> // hexdump
+#include "fsp_util.h"
+
+
+/** Displays a GUID's address and value
+ *
+ * @param guid pointer to the GUID to display
+ */
+void printguid(EFI_GUID *guid)
+{
+ printk(BIOS_SPEW,"Address: %p Guid: %08lx-%04x-%04x-",
+ guid, (unsigned long)guid->Data1,
+ guid->Data2, guid->Data3);
+ printk(BIOS_SPEW,"%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ guid->Data4[0], guid->Data4[1],
+ guid->Data4[2], guid->Data4[3],
+ guid->Data4[4], guid->Data4[5],
+ guid->Data4[6], guid->Data4[7] );
+}
+
+void print_hob_mem_attributes(void *Hobptr)
+{
+ EFI_HOB_MEMORY_ALLOCATION *HobMemoryPtr = (EFI_HOB_MEMORY_ALLOCATION *)Hobptr;
+ EFI_MEMORY_TYPE Hobmemtype = HobMemoryPtr->AllocDescriptor.MemoryType;
+ u64 Hobmemaddr = HobMemoryPtr->AllocDescriptor.MemoryBaseAddress;
+ u64 Hobmemlength = HobMemoryPtr->AllocDescriptor.MemoryLength;
+ const char * Hobmemtypenames[15];
+
+ Hobmemtypenames[0] = "EfiReservedMemoryType";
+ Hobmemtypenames[1] = "EfiLoaderCode";
+ Hobmemtypenames[2] = "EfiLoaderData";
+ Hobmemtypenames[3] = "EfiBootServicesCode";
+ Hobmemtypenames[4] = "EfiBootServicesData";
+ Hobmemtypenames[5] = "EfiRuntimeServicesCode";
+ Hobmemtypenames[6] = "EfiRuntimeServicesData";
+ Hobmemtypenames[7] = "EfiConventionalMemory";
+ Hobmemtypenames[8] = "EfiUnusableMemory";
+ Hobmemtypenames[9] = "EfiACPIReclaimMemory";
+ Hobmemtypenames[10] = "EfiACPIMemoryNVS";
+ Hobmemtypenames[11] = "EfiMemoryMappedIO";
+ Hobmemtypenames[12] = "EfiMemoryMappedIOPortSpace";
+ Hobmemtypenames[13] = "EfiPalCode";
+ Hobmemtypenames[14] = "EfiMaxMemoryType";
+
+ printk(BIOS_SPEW, " Memory type %s (0x%x)\n",
+ Hobmemtypenames[(u32)Hobmemtype], (u32) Hobmemtype);
+ printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
+ (unsigned long)Hobmemaddr, (unsigned long)Hobmemlength);
+}
+
+void print_hob_resource_attributes(void *Hobptr)
+{
+ EFI_HOB_RESOURCE_DESCRIPTOR *HobResourcePtr =
+ (EFI_HOB_RESOURCE_DESCRIPTOR *)Hobptr;
+ u32 Hobrestype = HobResourcePtr->ResourceType;
+ u32 Hobresattr = HobResourcePtr->ResourceAttribute;
+ u64 Hobresaddr = HobResourcePtr->PhysicalStart;
+ u64 Hobreslength = HobResourcePtr->ResourceLength;
+ const char *Hobrestypestr = NULL;
+
+ // HOB Resource Types
+ switch (Hobrestype) {
+ case EFI_RESOURCE_SYSTEM_MEMORY:
+ Hobrestypestr = "EFI_RESOURCE_SYSTEM_MEMORY"; break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO:
+ Hobrestypestr = "EFI_RESOURCE_MEMORY_MAPPED_IO"; break;
+ case EFI_RESOURCE_IO:
+ Hobrestypestr = "EFI_RESOURCE_IO"; break;
+ case EFI_RESOURCE_FIRMWARE_DEVICE:
+ Hobrestypestr = "EFI_RESOURCE_FIRMWARE_DEVICE"; break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
+ Hobrestypestr = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT"; break;
+ case EFI_RESOURCE_MEMORY_RESERVED:
+ Hobrestypestr = "EFI_RESOURCE_MEMORY_RESERVED"; break;
+ case EFI_RESOURCE_IO_RESERVED:
+ Hobrestypestr = "EFI_RESOURCE_IO_RESERVED"; break;
+ case EFI_RESOURCE_MAX_MEMORY_TYPE:
+ Hobrestypestr = "EFI_RESOURCE_MAX_MEMORY_TYPE"; break;
+ default:
+ Hobrestypestr = "EFI_RESOURCE_UNKNOWN"; break;
+ }
+
+ printk(BIOS_SPEW, " Resource %s (0x%0x) has attributes 0x%0x\n",
+ Hobrestypestr, Hobrestype, Hobresattr);
+ printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
+ (unsigned long)Hobresaddr, (unsigned long)Hobreslength);
+}
+
+const char * get_hob_type_string(void *Hobptr)
+{
+ EFI_HOB_GENERIC_HEADER *HobHeaderPtr = (EFI_HOB_GENERIC_HEADER *)Hobptr;
+ u16 Hobtype = HobHeaderPtr->HobType;
+ const char *Hobtypestring = NULL;
+
+ switch (Hobtype) {
+ case EFI_HOB_TYPE_HANDOFF:
+ Hobtypestring = "EFI_HOB_TYPE_HANDOFF"; break;
+ case EFI_HOB_TYPE_MEMORY_ALLOCATION:
+ Hobtypestring = "EFI_HOB_TYPE_MEMORY_ALLOCATION"; break;
+ case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
+ Hobtypestring = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR"; break;
+ case EFI_HOB_TYPE_GUID_EXTENSION:
+ Hobtypestring = "EFI_HOB_TYPE_GUID_EXTENSION"; break;
+ case EFI_HOB_TYPE_MEMORY_POOL:
+ Hobtypestring = "EFI_HOB_TYPE_MEMORY_POOL"; break;
+ case EFI_HOB_TYPE_UNUSED:
+ Hobtypestring = "EFI_HOB_TYPE_UNUSED"; break;
+ case EFI_HOB_TYPE_END_OF_HOB_LIST:
+ Hobtypestring = "EFI_HOB_TYPE_END_OF_HOB_LIST"; break;
+ default:
+ Hobtypestring = "EFI_HOB_TYPE_UNRECOGNIZED"; break;
+ }
+
+ return Hobtypestring;
+}
+
+/** Displays the length, location, and GUID value of a GUID extension
+ *
+ * The EFI_HOB_GUID_TYPE is very basic - it just contains the standard
+ * HOB header containing the HOB type and length, and a GUID for
+ * identification. The rest of the data is undefined and must be known
+ * based on the GUID.
+ *
+ * This displays the entire HOB length, and the location of the start
+ * of the HOB, *NOT* the length of or the start of the data inside the HOB.
+ *
+ * @param Hobptr
+ */
+void print_guid_type_attributes(void *Hobptr)
+{
+ printk(BIOS_SPEW, " at location %p with length0x%0lx\n ",
+ Hobptr, (unsigned long)(((EFI_PEI_HOB_POINTERS *) \
+ Hobptr)->Guid->Header.HobLength));
+ printguid(&(((EFI_HOB_GUID_TYPE *)Hobptr)->Name));
+
+}
+
+/* Print out a structure of all the HOBs
+ * that match a certain type:
+ * Print all types (0x0000)
+ * EFI_HOB_TYPE_HANDOFF (0x0001)
+ * EFI_HOB_TYPE_MEMORY_ALLOCATION (0x0002)
+ * EFI_HOB_TYPE_RESOURCE_DESCRIPTOR (0x0003)
+ * EFI_HOB_TYPE_GUID_EXTENSION (0x0004)
+ * EFI_HOB_TYPE_MEMORY_POOL (0x0007)
+ * EFI_HOB_TYPE_UNUSED (0xFFFE)
+ * EFI_HOB_TYPE_END_OF_HOB_LIST (0xFFFF)
+ */
+void print_hob_type_structure(u16 Hobtype, void *Hoblistptr)
+{
+ u32 *Currenthob;
+ u32 *Nexthob = 0;
+ u8 Lasthob = 0;
+ u32 Currenttype;
+ const char *Currenttypestr;
+
+ Currenthob = Hoblistptr;
+
+ /* Print out HOBs of our desired type until
+ * the end of the HOB list
+ */
+ printk(BIOS_DEBUG, "\n=== FSP HOB Data Structure ===\n");
+ printk(BIOS_DEBUG, "FSP Hoblistptr: 0x%0x\n",
+ (u32) Hoblistptr);
+ do {
+ EFI_HOB_GENERIC_HEADER *CurrentHeaderPtr =
+ (EFI_HOB_GENERIC_HEADER *)Currenthob;
+ Currenttype = CurrentHeaderPtr->HobType; /* Get the type of this HOB */
+ Currenttypestr = get_hob_type_string(Currenthob);
+
+ if (Currenttype == Hobtype || Hobtype == 0x0000) {
+ printk(BIOS_DEBUG, "HOB 0x%0x is an %s (type 0x%0x)\n",
+ (u32) Currenthob, Currenttypestr, Currenttype);
+ switch (Currenttype) {
+ case EFI_HOB_TYPE_MEMORY_ALLOCATION:
+ print_hob_mem_attributes(Currenthob); break;
+ case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
+ print_hob_resource_attributes(Currenthob); break;
+ case EFI_HOB_TYPE_GUID_EXTENSION:
+ print_guid_type_attributes(Currenthob); break;
+ }
+ }
+
+ Lasthob = END_OF_HOB_LIST(Currenthob); /* Check for end of HOB list */
+ if (!Lasthob) {
+ Nexthob = GET_NEXT_HOB(Currenthob); /* Get next HOB pointer */
+ Currenthob = Nexthob; // Start on next HOB
+ }
+ } while (!Lasthob);
+ printk(BIOS_DEBUG, "=== End of FSP HOB Data Structure ===\n\n");
+}
+
+
+/** Finds a HOB entry based on type and guid
+ *
+ * @param current_hob pointer to the start of the HOB list
+ * @param guid the GUID of the HOB entry to find
+ * @return pointer to the start of the requested HOB or NULL if not found.
+ */
+void * find_hob_by_guid(void *current_hob, EFI_GUID *guid)
+{
+ do {
+ switch (((EFI_HOB_GENERIC_HEADER *)current_hob)->HobType) {
+
+ case EFI_HOB_TYPE_MEMORY_ALLOCATION:
+ if (guids_are_equal(guid, &(((EFI_HOB_MEMORY_ALLOCATION *) \
+ current_hob)->AllocDescriptor.Name)))
+ return current_hob;
+ break;
+ case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
+ if (guids_are_equal(guid,
+ &(((EFI_HOB_RESOURCE_DESCRIPTOR *) \
+ current_hob)->Owner)))
+ return current_hob;
+ break;
+ case EFI_HOB_TYPE_GUID_EXTENSION:
+ if (guids_are_equal(guid, &(((EFI_HOB_GUID_TYPE *) \
+ current_hob)->Name)))
+ return current_hob;
+ break;
+ }
+
+ if (!END_OF_HOB_LIST(current_hob))
+ current_hob = GET_NEXT_HOB(current_hob); /* Get next HOB pointer */
+ } while (!END_OF_HOB_LIST(current_hob));
+
+ return NULL;
+}
+
+/** Compares a pair of GUIDs to see if they are equal
+ *
+ * GUIDs are 128 bits long, so compare them as pairs of quadwords.
+ *
+ * @param guid1 pointer to the first of the GUIDs to compare
+ * @param guid2 pointer to the second of the GUIDs to compare
+ * @return 1 if the GUIDs were equal, 0 if GUIDs were not equal
+ */
+uint8_t guids_are_equal(EFI_GUID *guid1, EFI_GUID *guid2)
+{
+ uint64_t* guid_1 = (void *) guid1;
+ uint64_t* guid_2 = (void *) guid2;
+
+ if ((*(guid_1) != *(guid_2)) || (*(guid_1 + 1) != *(guid_2 + 1)))
+ return 0;
+
+ return 1;
+}
Aaron Durbin (adurbin(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10157
-gerrit
commit c4c20bf32c1e9a0d979a956e6190e2e60c6bfd8c
Author: Aaron Durbin <adurbin(a)chromium.org>
Date: Fri May 8 17:14:15 2015 -0500
vboot: allow for dynamic work buffers
The vboot library currently relies on link-time known
address and sizes of the work buffer. Not all platforms
can provide such semantics. Therefore, add an option
to use cbmem for the work buffer. This implies such platforms
can only do verification of the firmware after main memory
has been initialized.
Change-Id: If0b0f6b2a187b5c1fb56af08b6cb384a935be096
Signed-off-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/include/cbmem.h | 2 ++
src/vendorcode/google/chromeos/vboot2/Kconfig | 10 ++++++++++
src/vendorcode/google/chromeos/vboot2/common.c | 14 ++++++++++++--
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/include/cbmem.h b/src/include/cbmem.h
index c5cd52a..07e5645 100644
--- a/src/include/cbmem.h
+++ b/src/include/cbmem.h
@@ -84,6 +84,7 @@
#define CBMEM_ID_STAGEx_CACHE 0x57a9e100
#define CBMEM_ID_TIMESTAMP 0x54494d45
#define CBMEM_ID_VBOOT_HANDOFF 0x780074f0
+#define CBMEM_ID_VBOOT_WORKBUF 0x78007343
#define CBMEM_ID_WIFI_CALIBRATION 0x57494649
#ifndef __ASSEMBLER__
@@ -128,6 +129,7 @@
{ CBMEM_ID_SPINTABLE, "SPIN TABLE " }, \
{ CBMEM_ID_TIMESTAMP, "TIME STAMP " }, \
{ CBMEM_ID_VBOOT_HANDOFF, "VBOOT " }, \
+ { CBMEM_ID_VBOOT_WORKBUF, "VBOOT WORK " }, \
{ CBMEM_ID_WIFI_CALIBRATION, "WIFI CLBR " },
struct cbmem_entry;
diff --git a/src/vendorcode/google/chromeos/vboot2/Kconfig b/src/vendorcode/google/chromeos/vboot2/Kconfig
index bb6c1ad..a086785 100644
--- a/src/vendorcode/google/chromeos/vboot2/Kconfig
+++ b/src/vendorcode/google/chromeos/vboot2/Kconfig
@@ -101,3 +101,13 @@ config VBOOT_BOOT_LOADER_INDEX
help
This is the index of the bootloader component in the verified
firmware block.
+
+config VBOOT_DYNAMIC_WORK_BUFFER
+ bool "Vboot's work buffer is dynamically allocated."
+ default n
+ depends on VBOOT_VERIFY_FIRMWARE
+ help
+ This option is used when there isn't enough pre-main memory
+ ram to allocate the vboot work buffer. That means vboot verification
+ is after memory init and requires main memory to back the work
+ buffer.
diff --git a/src/vendorcode/google/chromeos/vboot2/common.c b/src/vendorcode/google/chromeos/vboot2/common.c
index 289005c..deb0c88 100644
--- a/src/vendorcode/google/chromeos/vboot2/common.c
+++ b/src/vendorcode/google/chromeos/vboot2/common.c
@@ -18,6 +18,7 @@
*/
#include <cbfs.h>
+#include <cbmem.h>
#include <console/console.h>
#include <reset.h>
#include "../chromeos.h"
@@ -25,14 +26,23 @@
#include "../vboot_handoff.h"
#include "misc.h"
+static const size_t vb_work_buf_size = 16 * KiB;
+
struct vb2_working_data * const vboot_get_working_data(void)
{
- return (struct vb2_working_data *)_vboot2_work;
+ if (IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER))
+ /* cbmem_add() does a cbmem_find() first. */
+ return cbmem_add(CBMEM_ID_VBOOT_WORKBUF, vb_work_buf_size);
+ else
+ return (struct vb2_working_data *)_vboot2_work;
}
size_t vb2_working_data_size(void)
{
- return _vboot2_work_size;
+ if (IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER))
+ return vb_work_buf_size;
+ else
+ return _vboot2_work_size;
}
void *vboot_get_work_buffer(struct vb2_working_data *wd)