summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/intel/Kconfig1
-rw-r--r--src/drivers/intel/Makefile.inc1
-rw-r--r--src/drivers/intel/fsp1_1/Kconfig159
-rw-r--r--src/drivers/intel/fsp1_1/Makefile.inc34
-rw-r--r--src/drivers/intel/fsp1_1/cache_as_ram.inc268
-rw-r--r--src/drivers/intel/fsp1_1/fastboot_cache.c45
-rw-r--r--src/drivers/intel/fsp1_1/fsp_gop.c101
-rw-r--r--src/drivers/intel/fsp1_1/fsp_gop.h (renamed from src/drivers/intel/fsp1_1/fsp_values.h)33
-rw-r--r--src/drivers/intel/fsp1_1/fsp_relocate.c496
-rw-r--r--src/drivers/intel/fsp1_1/fsp_util.c449
-rw-r--r--src/drivers/intel/fsp1_1/fsp_util.h110
-rw-r--r--src/drivers/intel/fsp1_1/hob.c560
12 files changed, 1600 insertions, 657 deletions
diff --git a/src/drivers/intel/Kconfig b/src/drivers/intel/Kconfig
index 0f2d27eb47..a37ab739d6 100644
--- a/src/drivers/intel/Kconfig
+++ b/src/drivers/intel/Kconfig
@@ -17,5 +17,6 @@
## Foundation, Inc.
##
+source src/drivers/intel/fsp1_1/Kconfig
source src/drivers/intel/gma/Kconfig
source src/drivers/intel/i210/Kconfig
diff --git a/src/drivers/intel/Makefile.inc b/src/drivers/intel/Makefile.inc
index dc947ff4f0..3ddb05fb20 100644
--- a/src/drivers/intel/Makefile.inc
+++ b/src/drivers/intel/Makefile.inc
@@ -1,4 +1,5 @@
subdirs-y += gma
subdirs-y += wifi
subdirs-$(CONFIG_PLATFORM_USES_FSP1_0) += fsp1_0
+subdirs-$(CONFIG_PLATFORM_USES_FSP1_1) += fsp1_1
subdirs-$(CONFIG_DRIVER_INTEL_I210) += i210
diff --git a/src/drivers/intel/fsp1_1/Kconfig b/src/drivers/intel/fsp1_1/Kconfig
index d2e144f31c..a6d34eef6f 100644
--- a/src/drivers/intel/fsp1_1/Kconfig
+++ b/src/drivers/intel/fsp1_1/Kconfig
@@ -17,18 +17,14 @@
## Foundation, Inc.
##
-if PLATFORM_USES_FSP1_0
-
comment "Intel FSP"
-config HAVE_FSP_BIN
+config PLATFORM_USES_FSP1_1
bool "Use Intel Firmware Support Package"
help
- Select this option to add an Intel FSP binary to
- the resulting coreboot image.
+ Does the code require the Intel Firmware Support Package?
- Note: Without this binary, coreboot builds relying on the FSP
- will not boot
+if PLATFORM_USES_FSP1_1
config DCACHE_RAM_BASE
hex
@@ -38,13 +34,61 @@ config DCACHE_RAM_SIZE
hex
default 0x4000
+config HAVE_FSP_BIN
+ bool "Should the Intel FSP binary be added to the flash image"
+ 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
+
if HAVE_FSP_BIN
+config CPU_MICROCODE_CBFS_LEN
+ hex "Microcode update region length in bytes"
+ default 0
+ help
+ The length in bytes of the microcode update region.
+
+config CPU_MICROCODE_CBFS_LOC
+ hex "Microcode update base address in CBFS"
+ default 0
+ help
+ The location (base address) in CBFS that contains the microcode update
+ binary.
+
+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 FSP_FILE
string "Intel FSP binary path and filename"
help
The path and filename of the Intel FSP binary for this platform.
+config FSP_IMAGE_ID_DWORD0
+ hex "First 4 bytes of 8 byte platform string"
+ help
+ The first four bytes of the eight byte platform specific string
+ used to identify the FSP binary that should be used.
+
+config FSP_IMAGE_ID_DWORD1
+ hex "Second 4 bytes of 8 byte platform string"
+ help
+ The second four bytes of the eight byte platform specific string
+ used to identify the FSP binary that should be used.
+
+config FSP_INCLUDE_PATH
+ string "Path for FSP specific include files"
+ help
+ The path and filename of the Intel FSP binary for this platform.
+
config FSP_LOC
hex "Intel FSP Binary location in CBFS"
help
@@ -52,23 +96,27 @@ config FSP_LOC
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
+config MRC_CACHE_FILE
+ string "File containing the cached MRC values"
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.
+ The path and filename of the cached MRC values.
-config ENABLE_MRC_CACHE
- bool
- default y if HAVE_ACPI_RESUME
- default n
+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
- 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.
+ 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 MRC_CACHE_LOC_OVERRIDE
+ hex
+ help
+ Sets the override CBFS location of the MRC/fast boot cache.
config MRC_CACHE_SIZE
hex "Fast Boot Data Cache Size"
@@ -88,23 +136,6 @@ config OVERRIDE_CACHE_CACHE_LOC
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
@@ -126,20 +157,54 @@ config CACHE_ROM_SIZE_OVERRIDE
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.
+ 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
+config DISPLAY_FAST_BOOT_DATA
+ bool "Display fast boot data"
+ default n
+
+config DISPLAY_HOBS
+ bool "Display hand-off-blocks (HOBs)"
+ default n
+
+config DISPLAY_VBT
+ bool "Display Video BIOS Table (VBT)"
+ default n
+
+config DISPLAY_FSP_ENTRY_POINTS
+ bool "Display FSP entry points"
+ default n
+
+config DISPLAY_UPD_DATA
+ bool "Display UPD data"
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.
+ Display the user specified product data prior to memory
+ initialization.
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_0
+ If this FSP uses UPD/VPD data regions, select this in the chipset
+ Kconfig.
+
+config GOP_SUPPORT
+ bool "Enable GOP support"
+ default y
+
+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 VBT_FILE
+ string "GOP Video BIOS table binary path"
+ depends on GOP_SUPPORT
+ default "3rdparty/mainboard/$(MAINBOARDDIR)/vbt.bin"
+
+endif #PLATFORM_USES_FSP1_1
diff --git a/src/drivers/intel/fsp1_1/Makefile.inc b/src/drivers/intel/fsp1_1/Makefile.inc
index a29bf32136..9bb3fc4842 100644
--- a/src/drivers/intel/fsp1_1/Makefile.inc
+++ b/src/drivers/intel/fsp1_1/Makefile.inc
@@ -2,6 +2,7 @@
# This file is part of the coreboot project.
#
# Copyright (C) 2014 Sage Electronic Engineering, LLC.
+# Copyright (C) 2015 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
@@ -17,18 +18,29 @@
# Foundation, Inc.
#
-ramstage-y += fsp_util.c hob.c
-romstage-y += fsp_util.c hob.c
+romstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+romstage-$(CONFIG_GOP_SUPPORT) += fsp_gop.c
+romstage-y += fsp_util.c
+romstage-y += hob.c
ramstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
-romstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+ramstage-$(CONFIG_GOP_SUPPORT) += fsp_gop.c
+ramstage-y += fsp_relocate.c
+ramstage-y += fsp_util.c
+ramstage-y += hob.c
-CPPFLAGS_common += -Isrc/drivers/intel/fsp1_0
+CPPFLAGS_common += -Isrc/drivers/intel/fsp1_1
+
+cpu_incs-$(CONFIG_USE_GENERIC_FSP_CAR_INC) += $(src)/drivers/intel/fsp1_1/cache_as_ram.inc
-ifeq ($(CONFIG_USE_GENERIC_FSP_CAR_INC),y)
-cpu_incs += $(src)/drivers/intel/fsp1_0/cache_as_ram.inc
-endif
+# Add the GOP Video BIOS Table to the cbfs image
+cbfs-files-$(CONFIG_GOP_SUPPORT) += vbt.bin
+vbt.bin-file := $(call strip_quotes,$(CONFIG_VBT_FILE))
+vbt.bin-type := optionrom
+
+
+# Add the FSP binary to the cbfs image
ifeq ($(CONFIG_HAVE_FSP_BIN),y)
cbfs-files-y += fsp.bin
fsp.bin-file := $(call strip_quotes,$(CONFIG_FSP_FILE))
@@ -36,14 +48,16 @@ fsp.bin-position := $(CONFIG_FSP_LOC)
fsp.bin-type := fsp
endif
-ifeq ($(CONFIG_ENABLE_MRC_CACHE),y)
+
+# Create and add the MRC cache to the cbfs image
+ifeq ($(CONFIG_ENABLE_MRC_CACHE_FILE),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-file := $(call strip_quotes,$(CONFIG_MRC_CACHE_FILE))
mrc.cache-position := $(CONFIG_MRC_CACHE_LOC)
-mrc.cache-type := mrc_cache
+mrc.cache-type := CBFS_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
index 941da3bdf9..4a0827d2df 100644
--- a/src/drivers/intel/fsp1_1/cache_as_ram.inc
+++ b/src/drivers/intel/fsp1_1/cache_as_ram.inc
@@ -4,6 +4,7 @@
* Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
* Copyright (C) 2007-2008 coresystems GmbH
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -19,10 +20,17 @@
* Foundation, Inc.
*/
+/*
+ * Replacement for cache_as_ram.inc when using the FSP binary. This code
+ * locates the FSP binary, initializes the cache as RAM and performs the
+ * first stage of initialization. Next this code switches the stack from
+ * the cache to RAM and then disables the cache as RAM. Finally this code
+ * performs the final stage of initialization.
+ */
+
#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
@@ -33,7 +41,7 @@
# error "CONFIG_POST_IO must be set."
#endif
-#if CONFIG_POST_IO
+#if IS_ENABLED(CONFIG_POST_IO)
# ifndef CONFIG_POST_IO_PORT
# error "CONFIG_POST_IO_PORT must be set."
# endif
@@ -45,79 +53,216 @@
#define LHLT_DELAY 0x50000 /* I/O delay between post codes on failure */
- cmp $0, %eax
- jne bisthalt
+ /*
+ * eax: BIST value
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ */
+
+ mov %eax, %edi
cache_as_ram:
post_code(0x20)
/*
+ * edi: BIST value
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ */
+
+ /*
* 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
+ 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
+ mov %eax, %ebp
+
+ /*
+ * Only when a valid FSP binary is found at CONFIG_FSP_LOC is
+ * the returned FSP_INFO_HEADER structure address above the base
+ * address of FSP binary specified by the CONFIG_FSP_LOC value.
+ * All of the error values are in the 0x8xxxxxxx range which are
+ * below the CONFIG_FSP_LOC value.
+ */
+ cmp $CONFIG_FSP_LOC, %eax
+ jbe 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 */
+ mov 0x30(%ebp), %eax /* Load TempRamInitEntry */
+ add 0x1c(%ebp), %eax /* add in the offset for FSP */
/*
* Pass early init variables on a fake stack (no memory yet)
* as well as the return location
*/
- lea CAR_init_stack, %esp
+ lea CAR_init_stack, %esp
+
+ /*
+ * BIST value is zero
+ * eax: TempRamInitApi address
+ * ebp: FSP_INFO_HEADER address
+ * edi: BIST value
+ * esi: Not used
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ */
/* call FSP binary to setup temporary stack */
- jmp *%eax
+ jmp *%eax
CAR_init_done:
- addl $4, %esp
- cmp $0, %eax
- jne halt2
+ addl $4, %esp
+
+ /*
+ * ebp: FSP_INFO_HEADER address
+ * ecx: Temp RAM base
+ * edx: Temp RAM top
+ * edi: BIST value
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ */
+
+ cmp $0, %eax
+ jne halt2
+
+ /* Setup bootloader stack */
+ movl %edx, %esp
+
+ /* Save BIST value */
+ movd %edi, %mm2
+
+ /*
+ * ebp: FSP_INFO_HEADER address
+ * ecx: Temp RAM base
+ * edx: Temp RAM top
+ * esp: Top of stack in temp RAM
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ * mm2: BIST value
+ */
+
+ /* Coreboot assumes stack/heap region will be zero */
+ cld
+ movl %ecx, %edi
+ neg %ecx
+ add %edx, %ecx
+ shrl $2, %ecx
+ xorl %eax, %eax
+ rep stosl
/* Save FSP_INFO_HEADER location in ebx */
- mov %ebp, %ebx
+ mov %ebp, %ebx
/*
- * set up bootloader stack
- * ecx: stack base
- * edx: stack top
+ * ebx: FSP_INFO_HEADER address
+ * esi: Temp RAM base
+ * esp: Top of stack in temp RAM
+ * mm0: low 32-bits of TSC value
+ * mm1: high 32-bits of TSC value
+ * mm2: BIST value
*/
- 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
+ /* Frame for romstage_main(bist, tsc_low, tsc_hi, fih) */
+ pushl %ebx
+ movd %mm1, %eax
+ pushl %eax
+ movd %mm0, %eax
+ pushl %eax
+ movd %mm2, %eax
+ pushl %eax
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
+ call romstage_main
+
+ /*
+ * eax: New stack address
+ * ebx: FSP_INFO_HEADER address
+ */
+
+ /* Switch to the stack in RAM */
+ movl %eax, %esp
+
+ /* Calculate TempRamExit entry into FSP */
+ movl %ebx, %ebp
+ mov 0x40(%ebp), %eax
+ add 0x1c(%ebp), %eax
+
+ /* Build the call frame */
+ pushl $0
+
+ /* Call TempRamExit */
+ call *%eax
+ add $4, %esp
+ cmp $0, %eax
+ jne halt3
+
+ /* Get number of MTRRs. */
+ popl %ebx
+ movl $MTRRphysBase_MSR(0), %ecx
+1:
+ testl %ebx, %ebx
+ jz 1f
+
+ /* Low 32 bits of MTRR base. */
+ popl %eax
+ /* Upper 32 bits of MTRR base. */
+ popl %edx
+ /* Write MTRR base. */
+ wrmsr
+ inc %ecx
+ /* Low 32 bits of MTRR mask. */
+ popl %eax
+ /* Upper 32 bits of MTRR mask. */
+ popl %edx
+ /* Write MTRR mask. */
+ wrmsr
+ inc %ecx
+
+ dec %ebx
+ jmp 1b
+1:
+ post_code(0x39)
+
+ /* And enable cache again after setting MTRRs. */
+ movl %cr0, %eax
+ andl $~(CR0_CacheDisable | CR0_NoWriteThrough), %eax
+ movl %eax, %cr0
+
+ post_code(0x3a)
+
+ /* Enable MTRR. */
+ movl $MTRRdefType_MSR, %ecx
+ rdmsr
+ orl $MTRRdefTypeEn, %eax
+ wrmsr
+
+ post_code(0x3b)
-bisthalt:
- movb $0xB9, %ah
- jmp .Lhlt
+ /* Invalidate the cache again. */
+ invd
+
+ post_code(0x3c)
+
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* Clear direction flag. */
+ call romstage_after_car
+
+
+ movb $0x69, %ah
+ jmp .Lhlt
halt1:
/*
- * Failures for postcode 0xBA - failed in find_fsp()
+ * Failures for postcode 0xBA - failed in fsp_fih_early_find()
*
* Values are:
* 0x01 - FV signature, "_FVH" not present
@@ -128,8 +273,8 @@ halt1:
* 0x05 - FSP INFO Header signature "FSPH" not found
* 0x06 - FSP Image ID is not the expected ID.
*/
- movb $0xBA, %ah
- jmp .Lhlt
+ movb $0xBA, %ah
+ jmp .Lhlt
halt2:
/*
@@ -137,25 +282,37 @@ halt2:
*
* 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
+ * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode region.
* 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked
*/
- movb $0xBB, %ah
+ movb $0xBB, %ah
+ jmp .Lhlt
+
+halt3:
+ /*
+ * Failures for post code BC - failed in TempRamExit
+ *
+ * 0x00 - FSP_SUCCESS: Temp RAM Exit completed successfully.
+ * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid.
+ * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met.
+ * 0x07 - FSP_DEVICE_ERROR: Temp RAM Exit failed.
+ */
+ movb $0xBC, %ah
.Lhlt:
- xchg %al, %ah
-#if CONFIG_POST_IO
- outb %al, $CONFIG_POST_IO_PORT
+ xchg %al, %ah
+#if IS_ENABLED(CONFIG_POST_IO)
+ outb %al, $CONFIG_POST_IO_PORT
#else
post_code(POST_DEAD_CODE)
#endif
- movl $LHLT_DELAY, %ecx
+ movl $LHLT_DELAY, %ecx
.Lhlt_Delay:
- outb %al, $0xED
- loop .Lhlt_Delay
- jmp .Lhlt
+ outb %al, $0xED
+ loop .Lhlt_Delay
+ jmp .Lhlt
/*
* esp is set to this location so that the call into and return from the FSP
@@ -163,15 +320,14 @@ halt2:
*/
.align 4
fake_fsp_stack:
- .long find_fsp_ret
+ .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 */
+ .long CONFIG_CPU_MICROCODE_CBFS_LOC /* Microcode Location */
+ .long CONFIG_CPU_MICROCODE_CBFS_LEN /* Microcode Length */
+ .long 0xFFFFFFFF - CONFIG_CBFS_SIZE + 1 /* Firmware Location */
+ .long CONFIG_CBFS_SIZE /* Total Firmware Length */
CAR_init_stack:
- .long CAR_init_done
- .long CAR_init_params
-
+ .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
index 306359eafc..a0d15c4769 100644
--- a/src/drivers/intel/fsp1_1/fastboot_cache.c
+++ b/src/drivers/intel/fsp1_1/fastboot_cache.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -18,26 +19,23 @@
* Foundation, Inc.
*/
-#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 <console/console.h>
#include "fsp_util.h"
+#include <ip_checksum.h>
+#include <lib.h> // hexdump
+#include <spi_flash.h>
+#include <string.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 inline u32 to_flash_offset(void *p)
+{
+ return (u32)p + CONFIG_VIRTUAL_ROM_SIZE;
}
static struct mrc_data_container *next_mrc_block(
@@ -50,14 +48,15 @@ static struct mrc_data_container *next_mrc_block(
mrc_size += MRC_DATA_ALIGN;
}
- u8 *region_ptr = (u8*)mrc_cache;
+ 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);
+ return (!!mrc_cache)
+ && (mrc_cache->mrc_signature == MRC_DATA_SIGNATURE);
}
static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
@@ -96,7 +95,8 @@ static struct mrc_data_container *find_current_mrc_cache_local
}
if (entry_id == 0) {
- printk(BIOS_ERR, "%s: No valid fast boot cache found.\n", __func__);
+ printk(BIOS_ERR, "%s: No valid fast boot cache found.\n",
+ __func__);
return NULL;
}
@@ -104,7 +104,8 @@ static struct mrc_data_container *find_current_mrc_cache_local
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__);
+ printk(BIOS_ERR, "%s: fast boot cache checksum mismatch\n",
+ __func__);
return NULL;
}
@@ -117,7 +118,7 @@ static struct mrc_data_container *find_current_mrc_cache_local
/* SPI code needs malloc/free.
* Also unknown if writing flash from XIP-flash code is a good idea
*/
-#if !defined(__PRE_RAM__)
+#if ENV_RAMSTAGE
/* find the first empty block in the MRC cache area.
* If there's none, return NULL.
*
@@ -164,6 +165,7 @@ void update_mrc_cache(void *unused)
return;
}
+ cache_base = NULL;
cache_size = get_mrc_cache_region(&cache_base);
if (cache_base == NULL) {
printk(BIOS_ERR, "%s: could not find fast boot cache area\n",
@@ -218,19 +220,21 @@ void update_mrc_cache(void *unused)
current->mrc_data_size + sizeof(*current), current);
}
-#endif /* !defined(__PRE_RAM__) */
+#endif /* ENV_RAMSTAGE */
-void * find_and_set_fastboot_cache(void)
+void *find_and_set_fastboot_cache(void)
{
struct mrc_data_container *mrc_cache = NULL;
- if (((mrc_cache = find_current_mrc_cache()) == NULL) ||
+ mrc_cache = find_current_mrc_cache();
+ if ((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);
+ hexdump32(BIOS_SPEW, (void *)mrc_cache->mrc_data,
+ mrc_cache->mrc_data_size);
return (void *) mrc_cache->mrc_data;
}
@@ -239,6 +243,7 @@ struct mrc_data_container *find_current_mrc_cache(void)
struct mrc_data_container *cache_base;
u32 cache_size;
+ cache_base = NULL;
cache_size = get_mrc_cache_region(&cache_base);
if (cache_base == NULL) {
printk(BIOS_ERR, "%s: could not find fast boot cache area\n",
diff --git a/src/drivers/intel/fsp1_1/fsp_gop.c b/src/drivers/intel/fsp1_1/fsp_gop.c
new file mode 100644
index 0000000000..cf781cdea7
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_gop.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 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; 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 <cbfs.h>
+#include <console/console.h>
+#include "fsp_util.h"
+#include <lib.h>
+
+/* Reading VBT table from flash */
+const optionrom_vbt_t *fsp_get_vbt(uint32_t *vbt_len)
+{
+ struct cbfs_file *vbt_file;
+ union {
+ const optionrom_vbt_t *data;
+ uint32_t *signature;
+ } vbt;
+
+ /* Locate the vbt file in cbfs */
+ vbt_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "vbt.bin");
+ if (!vbt_file) {
+ printk(BIOS_INFO,
+ "FSP_INFO: VBT data file (vbt.bin) not found in CBFS");
+ return NULL;
+ }
+
+ /* Validate the vbt file */
+ vbt.data = CBFS_SUBHEADER(vbt_file);
+ if (*vbt.signature != VBT_SIGNATURE) {
+ printk(BIOS_WARNING,
+ "FSP_WARNING: Invalid signature in VBT data file (vbt.bin)!\n");
+ return NULL;
+ }
+ *vbt_len = ntohl(vbt_file->len);
+ printk(BIOS_DEBUG, "FSP_INFO: VBT found at %p, 0x%08x bytes\n",
+ vbt.data, *vbt_len);
+
+#if IS_ENABLED(CONFIG_DISPLAY_VBT)
+ /* Display the vbt file contents */
+ printk(BIOS_DEBUG, "VBT Data:\n");
+ hexdump(vbt.data, *vbt_len);
+ printk(BIOS_DEBUG, "\n");
+#endif
+
+ /* Return the pointer to the vbt file data */
+ return vbt.data;
+}
+
+#if ENV_RAMSTAGE
+void fsp_gop_framebuffer(struct lb_header *header)
+{
+ struct lb_framebuffer *framebuffer;
+ framebuffer = (struct lb_framebuffer *)lb_new_record(header);
+
+ VOID *hob_list_ptr;
+ hob_list_ptr = get_hob_list();
+ const EFI_GUID vbt_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
+ u32 *vbt_hob;
+ EFI_PEI_GRAPHICS_INFO_HOB *vbt_gop;
+ vbt_hob = get_next_guid_hob(&vbt_guid, hob_list_ptr);
+ if (vbt_hob == NULL) {
+ printk(BIOS_ERR, "FSP_ERR: Graphics Data HOB is not present\n");
+ return;
+ } else {
+ printk(BIOS_DEBUG, "FSP_DEBUG: Graphics Data HOB present\n");
+ vbt_gop = GET_GUID_HOB_DATA(vbt_hob);
+ }
+
+ framebuffer->physical_address = vbt_gop->FrameBufferBase;
+ framebuffer->x_resolution = vbt_gop->GraphicsMode.HorizontalResolution;
+ framebuffer->y_resolution = vbt_gop->GraphicsMode.VerticalResolution;
+ framebuffer->bytes_per_line = vbt_gop->GraphicsMode.PixelsPerScanLine
+ * 4;
+ framebuffer->bits_per_pixel = 32;
+ framebuffer->red_mask_pos = 16;
+ framebuffer->red_mask_size = 8;
+ framebuffer->green_mask_pos = 8;
+ framebuffer->green_mask_size = 8;
+ framebuffer->blue_mask_pos = 0;
+ framebuffer->blue_mask_size = 8;
+ framebuffer->reserved_mask_pos = 24;
+ framebuffer->reserved_mask_size = 8;
+ framebuffer->tag = LB_TAG_FRAMEBUFFER;
+ framebuffer->size = sizeof(*framebuffer);
+}
+#endif /* ENV_RAMSTAGE */
diff --git a/src/drivers/intel/fsp1_1/fsp_values.h b/src/drivers/intel/fsp1_1/fsp_gop.h
index 1e83d401aa..fc259014e3 100644
--- a/src/drivers/intel/fsp1_1/fsp_values.h
+++ b/src/drivers/intel/fsp1_1/fsp_gop.h
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -17,25 +17,18 @@
* Foundation, Inc.
*/
-#ifndef FSP_VALUES_H
-#define FSP_VALUES_H
+#ifndef _FSP_GOP_H_
+#define _FSP_GOP_H_
-#ifndef FSP_DEBUG_LEVEL
-# define FSP_DEBUG_LEVEL BIOS_SPEW
-#endif
+/* GOP support */
+#if IS_ENABLED(CONFIG_GOP_SUPPORT)
-#ifndef FSP_INFO_LEVEL
-# define FSP_INFO_LEVEL BIOS_DEBUG
-#endif
+#include <boot/coreboot_tables.h>
+#include <soc/intel/common/gma.h>
-#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
+const optionrom_vbt_t *fsp_get_vbt(uint32_t *vbt_len);
+#if ENV_RAMSTAGE
+void fsp_gop_framebuffer(struct lb_header *header);
+#endif /* ENV_RAMSTAGE */
+#endif /* CONFIG_GOP_SUPPORT */
+#endif /* _FSP_GOP_H_ */
diff --git a/src/drivers/intel/fsp1_1/fsp_relocate.c b/src/drivers/intel/fsp1_1/fsp_relocate.c
new file mode 100644
index 0000000000..08e1eb82f0
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_relocate.c
@@ -0,0 +1,496 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+#include <cbmem.h>
+#include <fsp_util.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <uefi_types.h>
+
+#define FSP_DBG_LVL BIOS_NEVER
+
+static const EFI_GUID ffs2_guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
+static const EFI_GUID fih_guid = FSP_INFO_HEADER_GUID;
+
+struct fsp_patch_table {
+ uint32_t signature;
+ uint16_t header_length;
+ uint8_t header_revision;
+ uint8_t reserved;
+ uint32_t patch_entry_num;
+ uint32_t patch_entries[0];
+} __attribute__((packed));
+
+#define FSPP_SIG 0x50505346
+
+static void *relative_offset(void *base, ssize_t offset)
+{
+ uintptr_t loc;
+
+ loc = (uintptr_t)base;
+ loc += offset;
+
+ return (void *)loc;
+}
+
+static uint32_t *fspp_reloc(void *fsp, size_t fsp_size, uint32_t e)
+{
+ size_t offset;
+
+ /* Offsets live in bits 23:0. */
+ offset = e & 0xffffff;
+
+ /* If bit 31 is set then the offset is considered a negative value
+ * relative to the end of the image using 16MiB as the offset's
+ * reference. */
+ if (e & (1 << 31))
+ offset = fsp_size - (16 * MiB - offset);
+
+ /* Determine if offset falls within fsp_size for a 32 bit relocation. */
+ if (offset > fsp_size - sizeof(uint32_t))
+ return NULL;
+
+ return relative_offset(fsp, offset);
+}
+
+static int reloc_type(uint16_t reloc_entry)
+{
+ /* Reloc type in upper 4 bits */
+ return reloc_entry >> 12;
+}
+
+static size_t reloc_offset(uint16_t reloc_entry)
+{
+ /* Offsets are in low 12 bits. */
+ return reloc_entry & ((1 << 12) - 1);
+}
+
+static int te_relocate_in_place(void *te, size_t size)
+{
+ EFI_TE_IMAGE_HEADER *teih;
+ EFI_IMAGE_DATA_DIRECTORY *relocd;
+ EFI_IMAGE_BASE_RELOCATION *relocb;
+ size_t fixup_offset;
+ size_t num_relocs;
+ uint16_t *reloc;
+ size_t relocd_offset;
+ uint8_t *te_base;
+ uint32_t adj;
+
+ teih = te;
+
+ if (teih->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ printk(BIOS_ERR, "TE Signature mismatch: %x vs %x\n",
+ teih->Signature, EFI_TE_IMAGE_HEADER_SIGNATURE);
+ return -1;
+ }
+
+ /*
+ * A TE image is created by converting a PE file. Because of this
+ * the offsets within the headers are off. In order to calculate
+ * the correct releative offets one needs to subtract fixup_offset
+ * from the encoded offets. Similarly, the linked address of the
+ * program is found by adding the fixup_offset to the ImageBase.
+ */
+ fixup_offset = teih->StrippedSize - sizeof(EFI_TE_IMAGE_HEADER);
+ /* Keep track of a base that is correctly adjusted so that offsets
+ * can be used directly. */
+ te_base = te;
+ te_base -= fixup_offset;
+
+ adj = (uintptr_t)te - (teih->ImageBase + fixup_offset);
+
+ printk(FSP_DBG_LVL, "TE Image %p -> %p adjust value: %x\n",
+ (void *)(uintptr_t)(teih->ImageBase + fixup_offset),
+ te, adj);
+
+ /* Adjust ImageBase for consistency. */
+ teih->ImageBase = (uint32_t)(teih->ImageBase + adj);
+
+ relocd = &teih->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+
+ relocd_offset = 0;
+ /* Though the field name is VirtualAddress it's actually relative to
+ * the beginning of the image which is linked at ImageBase. */
+ relocb = relative_offset(te, relocd->VirtualAddress - fixup_offset);
+ while (relocd_offset < relocd->Size) {
+ size_t rva_offset = relocb->VirtualAddress;
+
+ printk(FSP_DBG_LVL, "Relocs for RVA offset %zx\n", rva_offset);
+ num_relocs = relocb->SizeOfBlock - sizeof(*relocb);
+ num_relocs /= sizeof(uint16_t);
+ reloc = relative_offset(relocb, sizeof(*relocb));
+
+ printk(FSP_DBG_LVL, "Num relocs in block: %zx\n", num_relocs);
+
+ while (num_relocs > 0) {
+ int type = reloc_type(*reloc);
+ size_t offset = reloc_offset(*reloc);
+
+ printk(FSP_DBG_LVL, "reloc type %x offset %zx\n",
+ type, offset);
+
+ if (type == EFI_IMAGE_REL_BASED_HIGHLOW) {
+ uint32_t *reloc_addr;
+
+ offset += rva_offset;
+ reloc_addr = (void *)&te_base[offset];
+
+ printk(FSP_DBG_LVL, "Adjusting %p %x -> %x\n",
+ reloc_addr, *reloc_addr,
+ *reloc_addr + adj);
+ *reloc_addr += adj;
+ } else if (type != EFI_IMAGE_REL_BASED_ABSOLUTE) {
+ printk(BIOS_ERR, "Unknown reloc type: %x\n",
+ type);
+ return -1;
+ }
+ num_relocs--;
+ reloc++;
+ }
+
+ /* Track consumption of relocation directory contents. */
+ relocd_offset += relocb->SizeOfBlock;
+ /* Get next relocation block to process. */
+ relocb = relative_offset(relocb, relocb->SizeOfBlock);
+ }
+
+ return 0;
+}
+
+static size_t csh_size(const EFI_COMMON_SECTION_HEADER *csh)
+{
+ size_t size;
+
+ /* Unpack the array into a type that can be used. */
+ size = 0;
+ size |= csh->Size[0] << 0;
+ size |= csh->Size[1] << 8;
+ size |= csh->Size[2] << 16;
+
+ return size;
+}
+
+static size_t section_data_offset(const EFI_COMMON_SECTION_HEADER *csh)
+{
+ if (csh_size(csh) == 0x00ffffff)
+ return sizeof(EFI_COMMON_SECTION_HEADER2);
+ else
+ return sizeof(EFI_COMMON_SECTION_HEADER);
+}
+
+static size_t section_data_size(const EFI_COMMON_SECTION_HEADER *csh)
+{
+ size_t section_size;
+
+ if (csh_size(csh) == 0x00ffffff)
+ section_size = SECTION2_SIZE(csh);
+ else
+ section_size = csh_size(csh);
+
+ return section_size - section_data_offset(csh);
+}
+
+static size_t file_section_offset(const EFI_FFS_FILE_HEADER *ffsfh)
+{
+ if (IS_FFS_FILE2(ffsfh))
+ return sizeof(EFI_FFS_FILE_HEADER2);
+ else
+ return sizeof(EFI_FFS_FILE_HEADER);
+}
+
+static size_t ffs_file_size(const EFI_FFS_FILE_HEADER *ffsfh)
+{
+ size_t size;
+
+ if (IS_FFS_FILE2(ffsfh))
+ size = FFS_FILE2_SIZE(ffsfh);
+ else {
+ size = ffsfh->Size[0] << 0;
+ size |= ffsfh->Size[1] << 8;
+ size |= ffsfh->Size[2] << 16;
+ }
+ return size;
+}
+
+static int relocate_patch_table(void *fsp, size_t size, size_t offset,
+ ssize_t adjustment)
+{
+ struct fsp_patch_table *table;
+ uint32_t num;
+
+ table = relative_offset(fsp, offset);
+
+ if ((offset + sizeof(*table) > size) ||
+ (table->header_length + offset) > size) {
+ printk(BIOS_ERR, "FSPP not entirely contained in region.\n");
+ return -1;
+ }
+
+ printk(FSP_DBG_LVL, "FSPP relocs: %x\n", table->patch_entry_num);
+
+ for (num = 0; num < table->patch_entry_num; num++) {
+ uint32_t *reloc;
+
+ reloc = fspp_reloc(fsp, size, table->patch_entries[num]);
+
+ if (reloc == NULL) {
+ printk(BIOS_ERR, "Ignoring FSPP entry: %x\n",
+ table->patch_entries[num]);
+ continue;
+ }
+
+ printk(FSP_DBG_LVL, "Adjusting %p %x -> %x\n",
+ reloc, *reloc, (unsigned int)(*reloc + adjustment));
+
+ *reloc += adjustment;
+ }
+
+ return 0;
+}
+
+static void *relocate_remaining_items(void *fsp, size_t size, size_t fih_offset)
+{
+ EFI_FFS_FILE_HEADER *ffsfh;
+ EFI_COMMON_SECTION_HEADER *csh;
+ FSP_INFO_HEADER *fih;
+ ssize_t adjustment;
+ size_t offset;
+
+ printk(FSP_DBG_LVL, "FSP_INFO_HEADER offset is %zx\n", fih_offset);
+
+ if (fih_offset == 0) {
+ printk(BIOS_ERR, "FSP_INFO_HEADER offset is 0.\n");
+ return NULL;
+ }
+
+ /* FSP_INFO_HEADER at first file in FV within first RAW section. */
+ ffsfh = relative_offset(fsp, fih_offset);
+ fih_offset += file_section_offset(ffsfh);
+ csh = relative_offset(fsp, fih_offset);
+ fih_offset += section_data_offset(csh);
+ fih = relative_offset(fsp, fih_offset);
+
+ if (memcmp(&ffsfh->Name, &fih_guid, sizeof(fih_guid))) {
+ printk(BIOS_ERR, "Bad FIH GUID.\n");
+ return NULL;
+ }
+
+ if (csh->Type != EFI_SECTION_RAW) {
+ printk(BIOS_ERR, "FIH file should have raw section: %x\n",
+ csh->Type);
+ return NULL;
+ }
+
+ if (fih->Signature != FSP_SIG) {
+ printk(BIOS_ERR, "Unexpected FIH signature: %08x\n",
+ fih->Signature);
+ return NULL;
+ }
+
+ adjustment = (intptr_t)fsp - fih->ImageBase;
+
+ /* Update ImageBase to reflect FSP's new home. */
+ fih->ImageBase += adjustment;
+
+ /* Need to find patch table and adjust each entry. The tables
+ * following FSP_INFO_HEADER have a 32-bit signature and header
+ * length. The patch table is denoted as having a 'FSPP' signature;
+ * the table format doesn't follow the other tables. */
+ offset = fih_offset + fih->HeaderLength;
+ while (offset + 2 * sizeof(uint32_t) <= size) {
+ uint32_t *table_headers;
+
+ table_headers = relative_offset(fsp, offset);
+
+ printk(FSP_DBG_LVL, "Checking offset %zx for 'FSPP'\n",
+ offset);
+
+ if (table_headers[0] != FSPP_SIG) {
+ offset += table_headers[1];
+ continue;
+ }
+
+ if (relocate_patch_table(fsp, size, offset, adjustment)) {
+ printk(BIOS_ERR, "FSPP relocation failed.\n");
+ return NULL;
+ }
+
+ return fih;
+ }
+
+ printk(BIOS_ERR, "Could not find the FSP patch table.\n");
+ return NULL;
+}
+
+static ssize_t relocate_fvh(void *fsp, size_t fsp_size, size_t fvh_offset,
+ size_t *fih_offset)
+{
+ EFI_FIRMWARE_VOLUME_HEADER *fvh;
+ EFI_FFS_FILE_HEADER *ffsfh;
+ EFI_COMMON_SECTION_HEADER *csh;
+ size_t offset;
+ size_t file_offset;
+ size_t size;
+
+ offset = fvh_offset;
+ fvh = relative_offset(fsp, offset);
+
+ if (fvh->Signature != EFI_FVH_SIGNATURE)
+ return -1;
+
+ printk(FSP_DBG_LVL, "FVH length: %zx Offset: %zx Mapping length: %zx\n",
+ (size_t)fvh->FvLength, offset, fsp_size);
+
+ if (fvh->FvLength + offset > fsp_size)
+ return -1;
+
+ /* Parse only this FV. However, the algorithm uses offsets into the
+ * entire FSP region so make size include the starting offset. */
+ size = fvh->FvLength + offset;
+
+ if (memcmp(&fvh->FileSystemGuid, &ffs2_guid, sizeof(ffs2_guid))) {
+ printk(BIOS_ERR, "FVH not an FFS2 type.\n");
+ return -1;
+ }
+
+ if (fvh->ExtHeaderOffset != 0) {
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
+
+ offset += fvh->ExtHeaderOffset;
+ fveh = relative_offset(fsp, offset);
+ printk(FSP_DBG_LVL, "Extended Header Offset: %zx Size: %zx\n",
+ (size_t)fvh->ExtHeaderOffset,
+ (size_t)fveh->ExtHeaderSize);
+ offset += fveh->ExtHeaderSize;
+ /* FFS files are 8 byte aligned after extended header. */
+ offset = ALIGN_UP(offset, 8);
+ } else {
+ offset += fvh->HeaderLength;
+ }
+
+ file_offset = offset;
+ while (file_offset + sizeof(*ffsfh) < size) {
+ offset = file_offset;
+ printk(FSP_DBG_LVL, "file offset: %zx\n", file_offset);
+
+ /* First file and section should be FSP info header. */
+ if (fih_offset != NULL && *fih_offset == 0)
+ *fih_offset = file_offset;
+
+ ffsfh = relative_offset(fsp, file_offset);
+
+ printk(FSP_DBG_LVL, "file type = %x\n", ffsfh->Type);
+ printk(FSP_DBG_LVL, "file attribs = %x\n", ffsfh->Attributes);
+
+ /* Exit FV relocation when empty space found */
+ if (ffsfh->Type == EFI_FV_FILETYPE_FFS_MAX)
+ break;
+
+ /* Next file on 8 byte alignment. */
+ file_offset += ffs_file_size(ffsfh);
+ file_offset = ALIGN_UP(file_offset, 8);
+
+ /* Padding files have no section information. */
+ if (ffsfh->Type == EFI_FV_FILETYPE_FFS_PAD)
+ continue;
+
+ offset += file_section_offset(ffsfh);
+
+ while (offset + sizeof(*csh) < file_offset) {
+ size_t data_size;
+ size_t data_offset;
+
+ csh = relative_offset(fsp, offset);
+
+ printk(FSP_DBG_LVL, "section offset: %zx\n", offset);
+ printk(FSP_DBG_LVL, "section type: %x\n", csh->Type);
+
+ data_size = section_data_size(csh);
+ data_offset = section_data_offset(csh);
+
+ if (data_size + data_offset + offset > file_offset) {
+ printk(BIOS_ERR, "Section exceeds FV size.\n");
+ return -1;
+ }
+
+ if (csh->Type == EFI_SECTION_TE) {
+ void *te;
+ size_t te_offset = offset + data_offset;
+
+ printk(FSP_DBG_LVL, "TE image at offset %zx\n",
+ te_offset);
+ te = relative_offset(fsp, te_offset);
+ te_relocate_in_place(te, data_size);
+ }
+
+ offset += data_size + data_offset;
+ /* Sections are aligned to 4 bytes. */
+ offset = ALIGN_UP(offset, 4);
+ }
+ }
+
+ /* Return amount of buffer parsed: FV size. */
+ return fvh->FvLength;
+}
+
+static FSP_INFO_HEADER *fsp_relocate_in_place(void *fsp, size_t size)
+{
+ size_t offset;
+ size_t fih_offset;
+
+ offset = 0;
+ fih_offset = 0;
+ while (offset < size) {
+ ssize_t nparsed;
+
+ /* Relocate each FV within the FSP region. The FSP_INFO_HEADER
+ * should only be located in the first FV. */
+ if (offset == 0)
+ nparsed = relocate_fvh(fsp, size, offset, &fih_offset);
+ else
+ nparsed = relocate_fvh(fsp, size, offset, NULL);
+
+ /* FV should be larger than 0 or failed to parse. */
+ if (nparsed <= 0) {
+ printk(BIOS_ERR, "FV @ offset %zx relocation failed\n",
+ offset);
+ return NULL;
+ }
+
+ offset += nparsed;
+ }
+
+ return relocate_remaining_items(fsp, size, fih_offset);
+}
+
+FSP_INFO_HEADER *fsp_relocate(void *fsp_src, size_t size)
+{
+ void *new_loc;
+
+ new_loc = cbmem_add(CBMEM_ID_REFCODE, size);
+ if (new_loc == NULL) {
+ printk(BIOS_ERR, "Unable to load FSP into memory.\n");
+ return NULL;
+ }
+ memcpy(new_loc, fsp_src, size);
+ return fsp_relocate_in_place(new_loc, size);
+}
diff --git a/src/drivers/intel/fsp1_1/fsp_util.c b/src/drivers/intel/fsp1_1/fsp_util.c
index 9dbd50278e..51ddc67de3 100644
--- a/src/drivers/intel/fsp1_1/fsp_util.c
+++ b/src/drivers/intel/fsp1_1/fsp_util.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -17,336 +18,234 @@
* Foundation, Inc.
*/
-#include <types.h>
-#include <string.h>
-#include <console/console.h>
#include <bootstate.h>
#include <cbmem.h>
+#include <console/console.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)
+/* Locate the FSP binary in the coreboot filesystem */
+FSP_INFO_HEADER *find_fsp(void)
{
- 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;
+ union {
+ EFI_FFS_FILE_HEADER *ffh;
+ FSP_INFO_HEADER *fih;
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *fveh;
+ EFI_FIRMWARE_VOLUME_HEADER *fvh;
+ EFI_RAW_SECTION *rs;
+ u8 *u8;
+ u32 u32;
+ } fsp_ptr;
+ u32 *image_id;
- timestamp_add_now(Phase == EnumInitPhaseReadyToBoot ?
- TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
+#ifndef CONFIG_FSP_LOC
+#error "CONFIG_FSP_LOC must be set."
+#endif
- Status = NotifyPhaseProc (&NotifyPhaseParams);
+ for (;;) {
+ /* Get the FSP binary base address in CBFS */
+ fsp_ptr.u8 = (u8 *)CONFIG_FSP_LOC;
- timestamp_add_now(Phase == EnumInitPhaseReadyToBoot ?
- TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
+ /* Check the FV signature, _FVH */
+ if (fsp_ptr.fvh->Signature != 0x4856465F) {
+ fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG;
+ break;
+ }
- 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__ */
+ /* Locate the file header which follows the FV header. */
+ fsp_ptr.u8 += fsp_ptr.fvh->ExtHeaderOffset;
+ fsp_ptr.u8 += fsp_ptr.fveh->ExtHeaderSize;
+ fsp_ptr.u8 = (u8 *)((fsp_ptr.u32 + 7) & 0xFFFFFFF8);
+
+ /* Check the FFS GUID */
+ if ((((u32 *)&fsp_ptr.ffh->Name)[0] != 0x912740BE)
+ || (((u32 *)&fsp_ptr.ffh->Name)[1] != 0x47342284)
+ || (((u32 *)&fsp_ptr.ffh->Name)[2] != 0xB08471B9)
+ || (((u32 *)&fsp_ptr.ffh->Name)[3] != 0x0C3F3527)) {
+ fsp_ptr.u8 = (u8 *)ERROR_NO_FFS_GUID;
+ break;
+ }
-#ifdef __PRE_RAM__
+ /* Locate the Raw Section Header */
+ fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER);
-/*
- * 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 (fsp_ptr.rs->Type != EFI_SECTION_RAW) {
+ fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER;
+ break;
+ }
-#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);
+ /* Locate the FSP INFO Header which follows the Raw Header. */
+ fsp_ptr.u8 += sizeof(EFI_RAW_SECTION);
- /* Call the chipset code to fill in the chipset specific structures */
- chipset_fsp_early_init(&FspInitParams, fsp_ptr);
+ /* Verify that the FSP base address.*/
+ if (fsp_ptr.fih->ImageBase != CONFIG_FSP_LOC) {
+ fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH;
+ break;
+ }
- /* Call back to romstage for board specific changes */
- romstage_fsp_rt_buffer_callback(&FspRtBuffer);
+ /* Verify the FSP Signature */
+ if (fsp_ptr.fih->Signature != FSP_SIG) {
+ fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
+ break;
+ }
- FspInitApi(&FspInitParams);
+ /* Verify the FSP ID */
+ image_id = (u32 *)&fsp_ptr.fih->ImageId[0];
+ if ((image_id[0] != CONFIG_FSP_IMAGE_ID_DWORD0)
+ || (image_id[1] != CONFIG_FSP_IMAGE_ID_DWORD1))
+ fsp_ptr.u8 = (u8 *)ERROR_FSP_SIG_MISMATCH;
+ break;
+ }
- /* Should never return. Control will continue from ContinuationFunc */
- die("Uh Oh! FspInitApi returned");
+ return fsp_ptr.fih;
}
-#endif /* __PRE_RAM__ */
-volatile u8 * find_fsp ()
+void print_fsp_info(FSP_INFO_HEADER *fsp_header)
{
-
-#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;
+ u8 *fsp_base;
+
+ fsp_base = (u8 *)fsp_header->ImageBase;
+ printk(BIOS_SPEW, "FSP_INFO_HEADER: %p\n", fsp_header);
+ printk(BIOS_INFO, "FSP Signature: %c%c%c%c%c%c%c%c\n",
+ fsp_header->ImageId[0], fsp_header->ImageId[1],
+ fsp_header->ImageId[2], fsp_header->ImageId[3],
+ fsp_header->ImageId[4], fsp_header->ImageId[5],
+ fsp_header->ImageId[6], fsp_header->ImageId[7]);
+ printk(BIOS_INFO, "FSP Header Version: %d\n",
+ fsp_header->HeaderRevision);
+ printk(BIOS_INFO, "FSP Revision: %d.%d\n",
+ (u8)((fsp_header->ImageRevision >> 8) & 0xff),
+ (u8)(fsp_header->ImageRevision & 0xff));
+#if IS_ENABLED(CONFIG_DISPLAY_FSP_ENTRY_POINTS)
+ printk(BIOS_SPEW, "FSP Entry Points:\n");
+ printk(BIOS_SPEW, " 0x%p: Image Base\n", fsp_base);
+ printk(BIOS_SPEW, " 0x%p: TempRamInit\n",
+ &fsp_base[fsp_header->TempRamInitEntryOffset]);
+ printk(BIOS_SPEW, " 0x%p: FspInit\n",
+ &fsp_base[fsp_header->FspInitEntryOffset]);
+ if (fsp_header->HeaderRevision >= FSP_HEADER_REVISION_2) {
+ printk(BIOS_SPEW, " 0x%p: MemoryInit\n",
+ &fsp_base[fsp_header->FspMemoryInitEntryOffset]);
+ printk(BIOS_SPEW, " 0x%p: TempRamExit\n",
+ &fsp_base[fsp_header->TempRamExitEntryOffset]);
+ printk(BIOS_SPEW, " 0x%p: SiliconInit\n",
+ &fsp_base[fsp_header->FspSiliconInitEntryOffset]);
}
+ printk(BIOS_SPEW, " 0x%p: NotifyPhase\n",
+ &fsp_base[fsp_header->NotifyPhaseEntryOffset]);
+ printk(BIOS_SPEW, " 0x%p: Image End\n",
+ &fsp_base[fsp_header->ImageSize]);
+#endif
+}
- 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;
- }
+#if ENV_RAMSTAGE
- /* 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;
- }
+void fsp_notify(u32 phase)
+{
+ FSP_NOTIFY_PHASE notify_phase_proc;
+ NOTIFY_PHASE_PARAMS notify_phase_params;
+ EFI_STATUS status;
+ FSP_INFO_HEADER *fsp_header_ptr;
- /* 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;
+ fsp_header_ptr = fsp_get_fih();
+ if (fsp_header_ptr == NULL) {
+ fsp_header_ptr = (void *)find_fsp();
+ if ((u32)fsp_header_ptr < 0xff) {
+ /* output something in case there is no serial */
+ post_code(0x4F);
+ die("Can't find the FSP!\n");
+ }
}
- /* 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;
- }
+ /* call FSP PEI to Notify PostPciEnumeration */
+ notify_phase_proc = (FSP_NOTIFY_PHASE)(fsp_header_ptr->ImageBase +
+ fsp_header_ptr->NotifyPhaseEntryOffset);
+ notify_phase_params.Phase = phase;
- return (fsp_ptr);
-}
+ timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
+ TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
-/** 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);
+ status = notify_phase_proc(&notify_phase_params);
- if (saved_mem_hob == NULL)
- return NULL;
+ timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
+ TS_FSP_AFTER_FINALIZE : TS_FSP_AFTER_ENUMERATE);
- return (void *) ((char *) saved_mem_hob + sizeof(EFI_HOB_GUID_TYPE));
+ if (status != 0)
+ printk(BIOS_ERR, "FSP API NotifyPhase failed for phase 0x%x with status: 0x%x\n",
+ phase, status);
}
-#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)
+static void fsp_notify_boot_state_callback(void *arg)
{
- 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);
+ u32 phase = (u32)arg;
- if (fsp_reserved_mem == NULL)
- return NULL;
-
- return (void *)((uintptr_t)fsp_reserved_mem->PhysicalStart);
+ printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
+ fsp_notify(phase);
}
-#endif /* FSP_RESERVE_MEMORY_SIZE */
-#ifndef __PRE_RAM__ /* Only parse HOB data in ramstage */
+BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_EXIT,
+ fsp_notify_boot_state_callback,
+ (void *)EnumInitPhaseAfterPciEnumeration);
+BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT,
+ fsp_notify_boot_state_callback,
+ (void *)EnumInitPhaseReadyToBoot);
+BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY,
+ fsp_notify_boot_state_callback,
+ (void *)EnumInitPhaseReadyToBoot);
-void print_fsp_info(void) {
+#endif /* ENV_RAMSTAGE */
- 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");
- }
+struct fsp_runtime {
+ uint32_t fih;
+ uint32_t hob_list;
+} __attribute__((packed));
- 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)
+void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
{
- 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);
- }
+ struct fsp_runtime *fspr;
- mrc_hob_data = GET_GUID_HOB_DATA (mrc_hob);
- mrc_hob_size = (u32) GET_HOB_LENGTH(mrc_hob);
+ fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
- printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n",
- (void *)mrc_hob_data, mrc_hob_size);
+ if (fspr == NULL)
+ die("Can't save FSP runtime information.\n");
- output_len = ALIGN(mrc_hob_size, 16);
+ fspr->fih = (uintptr_t)fih;
+ fspr->hob_list = (uintptr_t)hob_list;
+}
- /* 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));
+FSP_INFO_HEADER *fsp_get_fih(void)
+{
+ struct fsp_runtime *fspr;
- /* 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;
- }
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
- 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);
+ if (fspr == NULL)
+ return NULL;
- 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);
+ return (void *)(uintptr_t)fspr->fih;
+}
- /* 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);
+void *fsp_get_hob_list(void)
+{
+ struct fsp_runtime *fspr;
- mrc_data->mrc_checksum = compute_ip_checksum(mrc_data->mrc_data,
- mrc_data->mrc_data_size);
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
- 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 */
+ if (fspr == NULL)
+ return NULL;
-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
- }
+ return (void *)(uintptr_t)fspr->hob_list;
}
-/** @brief Notify FSP for PostPciEnumeration
- *
- * @param unused
- */
-static void fsp_after_pci_enum(void *unused)
+void fsp_update_fih(FSP_INFO_HEADER *fih)
{
- /* 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");
-}
+ struct fsp_runtime *fspr;
-/** @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");
-}
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
-/* 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);
+ if (fspr == NULL)
+ die("Can't update FSP runtime information.\n");
-/* 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__ */
+ fspr->fih = (uintptr_t)fih;
+}
diff --git a/src/drivers/intel/fsp1_1/fsp_util.h b/src/drivers/intel/fsp1_1/fsp_util.h
index 054de1c5a1..38fa86211b 100644
--- a/src/drivers/intel/fsp1_1/fsp_util.h
+++ b/src/drivers/intel/fsp1_1/fsp_util.h
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -20,35 +21,52 @@
#ifndef FSP_UTIL_H
#define FSP_UTIL_H
+#include <types.h>
+#include <arch/cpu.h>
+#include <fsp_gop.h>
+
+/*
+ * The following are functions with prototypes defined in the EDK2 headers. The
+ * EDK2 headers are included with chipset_fsp_util.h. Define the following
+ * names to reduce the use of CamelCase in the other source files.
+ */
+#define GetHobList get_hob_list
+#define GetNextHob get_next_hob
+#define GetFirstHob get_first_hob
+#define GetNextGuidHob get_next_guid_hob
+#define GetFirstGuidHob get_first_guid_hob
+
+/* Include the EDK2 headers */
#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);
+/* find_fsp() should only be called from assembly code. */
+FSP_INFO_HEADER *find_fsp(void);
+/* Set FSP's runtime information. */
+void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list);
+/* Use a new FSP_INFO_HEADER at runtime. */
+void fsp_update_fih(FSP_INFO_HEADER *fih);
+/* fsp_get_fih() is only valid after calling fsp_set_runtime(). */
+FSP_INFO_HEADER *fsp_get_fih(void);
+/* fsp_get_hob_list() is only valid after calling fsp_set_runtime(). */
+void *fsp_get_hob_list(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);
+void fsp_notify(u32 phase);
+void print_hob_type_structure(u16 hob_type, void *hob_list_ptr);
+void print_fsp_info(FSP_INFO_HEADER *fsp_header);
+void *get_next_type_guid_hob(UINT16 type, const EFI_GUID *guid,
+ const void *hob_start);
+void *get_next_resource_hob(const EFI_GUID *guid, const void *hob_start);
+void *get_first_resource_hob(const EFI_GUID *guid);
+/*
+ * Relocate FSP entire binary into ram. Returns NULL on error. Otherwise the
+ * FSP_INFO_HEADER pointer to the relocated FSP.
+ */
+FSP_INFO_HEADER *fsp_relocate(void *fsp_src, size_t size);
/* Additional HOB types not included in the FSP:
* #define EFI_HOB_TYPE_HANDOFF 0x0001
@@ -73,63 +91,31 @@ 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
+ 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
+#endif /* CONFIG_ENABLE_MRC_CACHE */
/* 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_IMAGE_SIG_LOC 0
+#define FSP_IMAGE_ID_LOC 16
+#define FSP_IMAGE_BASE_LOC 28
-#define FSP_SIG 0x48505346 /* 'FSPH' */
+#define FSP_SIG 0x48505346 /* 'FSPH' */
#define ERROR_NO_FV_SIG 1
-#define ERROR_NO_FFS_GUID 2
+#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_INFO_HEAD_SIG_MISMATCH 5
#define ERROR_FSP_SIG_MISMATCH 6
-#ifndef __PRE_RAM__
+#if ENV_RAMSTAGE
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/hob.c b/src/drivers/intel/fsp1_1/hob.c
index ecc6bad845..905d3ec1ab 100644
--- a/src/drivers/intel/fsp1_1/hob.c
+++ b/src/drivers/intel/fsp1_1/hob.c
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2013-2014 Sage Electronic Engineering, LLC.
+ * Copyright (C) 2015 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
@@ -17,150 +18,329 @@
* Foundation, Inc.
*/
-#include <types.h>
-#include <string.h>
+#include <arch/early_variables.h>
+#include <arch/hlt.h>
+#include <bootstate.h>
+#include <cbmem.h>
#include <console/console.h>
-#include <lib.h> // hexdump
#include "fsp_util.h"
+#include <ip_checksum.h>
+#include <lib.h> // hexdump
+#include <string.h>
+
+/*
+ * Reads a 64-bit value from memory that may be unaligned.
+ *
+ * This function returns the 64-bit value pointed to by buffer. The
+ * function guarantees that the read operation does not produce an
+ * alignment fault.
+ *
+ * If buffer is NULL, then ASSERT().
+ *
+ * buffer: Pointer to a 64-bit value that may be unaligned.
+ *
+ * Returns the 64-bit value read from buffer.
+ *
+ */
+static
+uint64_t
+read_unaligned_64(
+ const uint64_t *buffer
+ )
+{
+ ASSERT(buffer != NULL);
+ return *buffer;
+}
-/** Displays a GUID's address and value
+/*
+ * Compares two GUIDs.
+ *
+ * This function compares guid1 to guid2. If the GUIDs are identical then
+ * TRUE is returned. If there are any bit differences in the two GUIDs,
+ * then FALSE is returned.
+ *
+ * If guid1 is NULL, then ASSERT().
+ * If guid2 is NULL, then ASSERT().
+ *
+ * guid1: A pointer to a 128 bit GUID.
+ * guid2: A pointer to a 128 bit GUID.
*
- * @param guid pointer to the GUID to display
+ * Returns non-zero if guid1 and guid2 are identical, otherwise returns 0.
+ *
+ */
+static
+long
+compare_guid(
+ const EFI_GUID * guid1,
+ const EFI_GUID * guid2
+ )
+{
+ uint64_t low_part_of_guid1;
+ uint64_t low_part_of_guid2;
+ uint64_t high_part_of_guid1;
+ uint64_t high_part_of_guid2;
+
+ low_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1);
+ low_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2);
+ high_part_of_guid1 = read_unaligned_64((const uint64_t *) guid1 + 1);
+ high_part_of_guid2 = read_unaligned_64((const uint64_t *) guid2 + 1);
+
+ return ((low_part_of_guid1 == low_part_of_guid2)
+ && (high_part_of_guid1 == high_part_of_guid2));
+}
+
+/* Returns the pointer to the HOB list. */
+VOID *
+EFIAPI
+get_hob_list(
+ VOID
+ )
+{
+ void *hob_list;
+
+ hob_list = fsp_get_hob_list();
+ if (hob_list == NULL)
+ die("Call fsp_set_runtime() before this call!\n");
+ return hob_list;
+}
+
+/* Returns the next instance of a HOB type from the starting HOB. */
+VOID *
+EFIAPI
+get_next_hob(
+ UINT16 type,
+ CONST VOID *hob_start
+ )
+{
+ EFI_PEI_HOB_POINTERS hob;
+
+ ASSERT(hob_start != NULL);
+
+ hob.Raw = (UINT8 *)hob_start;
+
+ /* Parse the HOB list until end of list or matching type is found. */
+ while (!END_OF_HOB_LIST(hob.Raw)) {
+ if (hob.Header->HobType == type)
+ return hob.Raw;
+ if (GET_HOB_LENGTH(hob.Raw) < sizeof(*hob.Header))
+ break;
+ hob.Raw = GET_NEXT_HOB(hob.Raw);
+ }
+ return NULL;
+}
+
+/* Returns the first instance of a HOB type among the whole HOB list. */
+VOID *
+EFIAPI
+get_first_hob(
+ UINT16 type
+ )
+{
+ VOID *hob_list;
+
+ hob_list = get_hob_list();
+ return get_next_hob(type, hob_list);
+}
+
+/* Returns the next instance of the matched GUID HOB from the starting HOB. */
+VOID *
+EFIAPI
+get_next_guid_hob(
+ CONST EFI_GUID * guid,
+ CONST VOID *hob_start
+ )
+{
+ EFI_PEI_HOB_POINTERS hob;
+
+ hob.Raw = (UINT8 *)hob_start;
+ while ((hob.Raw = get_next_hob(EFI_HOB_TYPE_GUID_EXTENSION, hob.Raw))
+ != NULL) {
+ if (compare_guid(guid, &hob.Guid->Name))
+ break;
+ hob.Raw = GET_NEXT_HOB(hob.Raw);
+ }
+ return hob.Raw;
+}
+
+/*
+ * Returns the first instance of the matched GUID HOB among the whole HOB list.
+ */
+VOID *
+EFIAPI
+get_first_guid_hob(
+ CONST EFI_GUID * guid
+ )
+{
+ return get_next_guid_hob(guid, get_hob_list());
+}
+
+/*
+ * Returns the next instance of the matching resource HOB from the starting HOB.
*/
-void printguid(EFI_GUID *guid)
+void *get_next_resource_hob(const EFI_GUID *guid, const void *hob_start)
{
- 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] );
+ EFI_PEI_HOB_POINTERS hob;
+
+ hob.Raw = (UINT8 *)hob_start;
+ while ((hob.Raw = get_next_hob(EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+ hob.Raw)) != NULL) {
+ if (compare_guid(guid, &hob.ResourceDescriptor->Owner))
+ break;
+ hob.Raw = GET_NEXT_HOB(hob.Raw);
+ }
+ return hob.Raw;
+}
+
+/*
+ * Returns the first instance of the matching resource HOB among the whole HOB
+ * list.
+ */
+void *get_first_resource_hob(const EFI_GUID *guid)
+{
+ return get_next_resource_hob(guid, get_hob_list());
}
-void print_hob_mem_attributes(void *Hobptr)
+static void print_hob_mem_attributes(void *hob_ptr)
{
- 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";
+ EFI_HOB_MEMORY_ALLOCATION *hob_memory_ptr =
+ (EFI_HOB_MEMORY_ALLOCATION *)hob_ptr;
+ EFI_MEMORY_TYPE hob_mem_type =
+ hob_memory_ptr->AllocDescriptor.MemoryType;
+ u64 hob_mem_addr = hob_memory_ptr->AllocDescriptor.MemoryBaseAddress;
+ u64 hob_mem_length = hob_memory_ptr->AllocDescriptor.MemoryLength;
+ const char *hob_mem_type_names[15];
+
+ hob_mem_type_names[0] = "EfiReservedMemoryType";
+ hob_mem_type_names[1] = "EfiLoaderCode";
+ hob_mem_type_names[2] = "EfiLoaderData";
+ hob_mem_type_names[3] = "EfiBootServicesCode";
+ hob_mem_type_names[4] = "EfiBootServicesData";
+ hob_mem_type_names[5] = "EfiRuntimeServicesCode";
+ hob_mem_type_names[6] = "EfiRuntimeServicesData";
+ hob_mem_type_names[7] = "EfiConventionalMemory";
+ hob_mem_type_names[8] = "EfiUnusableMemory";
+ hob_mem_type_names[9] = "EfiACPIReclaimMemory";
+ hob_mem_type_names[10] = "EfiACPIMemoryNVS";
+ hob_mem_type_names[11] = "EfiMemoryMappedIO";
+ hob_mem_type_names[12] = "EfiMemoryMappedIOPortSpace";
+ hob_mem_type_names[13] = "EfiPalCode";
+ hob_mem_type_names[14] = "EfiMaxMemoryType";
printk(BIOS_SPEW, " Memory type %s (0x%x)\n",
- Hobmemtypenames[(u32)Hobmemtype], (u32) Hobmemtype);
+ hob_mem_type_names[(u32)hob_mem_type],
+ (u32)hob_mem_type);
printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
- (unsigned long)Hobmemaddr, (unsigned long)Hobmemlength);
+ (unsigned long)hob_mem_addr,
+ (unsigned long)hob_mem_length);
}
-void print_hob_resource_attributes(void *Hobptr)
+static void print_hob_resource_attributes(void *hob_ptr)
{
- 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) {
+ EFI_HOB_RESOURCE_DESCRIPTOR *hob_resource_ptr =
+ (EFI_HOB_RESOURCE_DESCRIPTOR *)hob_ptr;
+ u32 hob_res_type = hob_resource_ptr->ResourceType;
+ u32 hob_res_attr = hob_resource_ptr->ResourceAttribute;
+ u64 hob_res_addr = hob_resource_ptr->PhysicalStart;
+ u64 hob_res_length = hob_resource_ptr->ResourceLength;
+ const char *hob_res_type_str = NULL;
+
+ /* HOB Resource Types */
+ switch (hob_res_type) {
case EFI_RESOURCE_SYSTEM_MEMORY:
- Hobrestypestr = "EFI_RESOURCE_SYSTEM_MEMORY"; break;
+ hob_res_type_str = "EFI_RESOURCE_SYSTEM_MEMORY";
+ break;
case EFI_RESOURCE_MEMORY_MAPPED_IO:
- Hobrestypestr = "EFI_RESOURCE_MEMORY_MAPPED_IO"; break;
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO";
+ break;
case EFI_RESOURCE_IO:
- Hobrestypestr = "EFI_RESOURCE_IO"; break;
+ hob_res_type_str = "EFI_RESOURCE_IO";
+ break;
case EFI_RESOURCE_FIRMWARE_DEVICE:
- Hobrestypestr = "EFI_RESOURCE_FIRMWARE_DEVICE"; break;
+ hob_res_type_str = "EFI_RESOURCE_FIRMWARE_DEVICE";
+ break;
case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
- Hobrestypestr = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT"; break;
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT";
+ break;
case EFI_RESOURCE_MEMORY_RESERVED:
- Hobrestypestr = "EFI_RESOURCE_MEMORY_RESERVED"; break;
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_RESERVED";
+ break;
case EFI_RESOURCE_IO_RESERVED:
- Hobrestypestr = "EFI_RESOURCE_IO_RESERVED"; break;
+ hob_res_type_str = "EFI_RESOURCE_IO_RESERVED";
+ break;
case EFI_RESOURCE_MAX_MEMORY_TYPE:
- Hobrestypestr = "EFI_RESOURCE_MAX_MEMORY_TYPE"; break;
+ hob_res_type_str = "EFI_RESOURCE_MAX_MEMORY_TYPE";
+ break;
default:
- Hobrestypestr = "EFI_RESOURCE_UNKNOWN"; break;
+ hob_res_type_str = "EFI_RESOURCE_UNKNOWN";
+ break;
}
printk(BIOS_SPEW, " Resource %s (0x%0x) has attributes 0x%0x\n",
- Hobrestypestr, Hobrestype, Hobresattr);
+ hob_res_type_str, hob_res_type, hob_res_attr);
printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
- (unsigned long)Hobresaddr, (unsigned long)Hobreslength);
+ (unsigned long)hob_res_addr,
+ (unsigned long)hob_res_length);
}
-const char * get_hob_type_string(void *Hobptr)
+static const char *get_hob_type_string(void *hob_ptr)
{
- EFI_HOB_GENERIC_HEADER *HobHeaderPtr = (EFI_HOB_GENERIC_HEADER *)Hobptr;
- u16 Hobtype = HobHeaderPtr->HobType;
- const char *Hobtypestring = NULL;
+ EFI_PEI_HOB_POINTERS hob;
+ const char *hob_type_string = NULL;
+ const EFI_GUID fsp_reserved_guid =
+ FSP_RESERVED_MEMORY_RESOURCE_HOB_GUID;
+ const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
+ const EFI_GUID bootldr_tmp_mem_guid =
+ FSP_BOOTLOADER_TEMP_MEMORY_HOB_GUID;
+ const EFI_GUID bootldr_tolum_guid = FSP_BOOTLOADER_TOLUM_HOB_GUID;
+ const EFI_GUID graphics_info_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
- switch (Hobtype) {
+ hob.Header = (EFI_HOB_GENERIC_HEADER *)hob_ptr;
+ switch (hob.Header->HobType) {
case EFI_HOB_TYPE_HANDOFF:
- Hobtypestring = "EFI_HOB_TYPE_HANDOFF"; break;
+ hob_type_string = "EFI_HOB_TYPE_HANDOFF";
+ break;
case EFI_HOB_TYPE_MEMORY_ALLOCATION:
- Hobtypestring = "EFI_HOB_TYPE_MEMORY_ALLOCATION"; break;
+ hob_type_string = "EFI_HOB_TYPE_MEMORY_ALLOCATION";
+ break;
case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
- Hobtypestring = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR"; break;
+ hob_type_string = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR";
+ break;
case EFI_HOB_TYPE_GUID_EXTENSION:
- Hobtypestring = "EFI_HOB_TYPE_GUID_EXTENSION"; break;
+ hob_type_string = "EFI_HOB_TYPE_GUID_EXTENSION";
+ if (compare_guid(&bootldr_tmp_mem_guid, &hob.Guid->Name))
+ hob_type_string = "FSP_BOOTLOADER_TEMP_MEMORY_HOB";
+ else if (compare_guid(&fsp_reserved_guid, &hob.Guid->Name))
+ hob_type_string = "FSP_RESERVED_MEMORY_RESOURCE_HOB";
+ else if (compare_guid(&mrc_guid, &hob.Guid->Name))
+ hob_type_string = "FSP_NON_VOLATILE_STORAGE_HOB";
+ else if (compare_guid(&bootldr_tolum_guid, &hob.Guid->Name))
+ hob_type_string = "FSP_BOOTLOADER_TOLUM_HOB_GUID";
+ else if (compare_guid(&graphics_info_guid, &hob.Guid->Name))
+ hob_type_string = "EFI_PEI_GRAPHICS_INFO_HOB_GUID";
+ break;
case EFI_HOB_TYPE_MEMORY_POOL:
- Hobtypestring = "EFI_HOB_TYPE_MEMORY_POOL"; break;
+ hob_type_string = "EFI_HOB_TYPE_MEMORY_POOL";
+ break;
case EFI_HOB_TYPE_UNUSED:
- Hobtypestring = "EFI_HOB_TYPE_UNUSED"; break;
+ hob_type_string = "EFI_HOB_TYPE_UNUSED";
+ break;
case EFI_HOB_TYPE_END_OF_HOB_LIST:
- Hobtypestring = "EFI_HOB_TYPE_END_OF_HOB_LIST"; break;
+ hob_type_string = "EFI_HOB_TYPE_END_OF_HOB_LIST";
+ break;
default:
- Hobtypestring = "EFI_HOB_TYPE_UNRECOGNIZED"; break;
+ hob_type_string = "EFI_HOB_TYPE_UNRECOGNIZED";
+ break;
}
- return Hobtypestring;
+ return hob_type_string;
}
-/** 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
+/*
+ * 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_HANDOFF (0x0001)
* EFI_HOB_TYPE_MEMORY_ALLOCATION (0x0002)
* EFI_HOB_TYPE_RESOURCE_DESCRIPTOR (0x0003)
* EFI_HOB_TYPE_GUID_EXTENSION (0x0004)
@@ -168,102 +348,148 @@ void print_guid_type_attributes(void *Hobptr)
* EFI_HOB_TYPE_UNUSED (0xFFFE)
* EFI_HOB_TYPE_END_OF_HOB_LIST (0xFFFF)
*/
-void print_hob_type_structure(u16 Hobtype, void *Hoblistptr)
+void print_hob_type_structure(u16 hob_type, void *hob_list_ptr)
{
- u32 *Currenthob;
- u32 *Nexthob = 0;
- u8 Lasthob = 0;
- u32 Currenttype;
- const char *Currenttypestr;
+ u32 *current_hob;
+ u32 *next_hob = 0;
+ u8 last_hob = 0;
+ u32 current_type;
+ const char *current_type_str;
- Currenthob = Hoblistptr;
+ current_hob = hob_list_ptr;
- /* Print out HOBs of our desired type until
+ /*
+ * 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);
+ printk(BIOS_DEBUG, "0x%p: hob_list_ptr\n", hob_list_ptr);
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);
+ EFI_HOB_GENERIC_HEADER *current_header_ptr =
+ (EFI_HOB_GENERIC_HEADER *)current_hob;
+
+ /* Get the type of this HOB */
+ current_type = current_header_ptr->HobType;
+ current_type_str = get_hob_type_string(current_hob);
- if (Currenttype == Hobtype || Hobtype == 0x0000) {
+ if (current_type == hob_type || hob_type == 0x0000) {
printk(BIOS_DEBUG, "HOB 0x%0x is an %s (type 0x%0x)\n",
- (u32) Currenthob, Currenttypestr, Currenttype);
- switch (Currenttype) {
+ (u32)current_hob, current_type_str,
+ current_type);
+ switch (current_type) {
case EFI_HOB_TYPE_MEMORY_ALLOCATION:
- print_hob_mem_attributes(Currenthob); break;
+ print_hob_mem_attributes(current_hob);
+ 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;
+ print_hob_resource_attributes(current_hob);
+ 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
+ /* Check for end of HOB list */
+ last_hob = END_OF_HOB_LIST(current_hob);
+ if (!last_hob) {
+ /* Get next HOB pointer */
+ next_hob = GET_NEXT_HOB(current_hob);
+
+ /* Start on next HOB */
+ current_hob = next_hob;
}
- } while (!Lasthob);
+ } while (!last_hob);
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.
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+/*
+ * Save the FSP memory HOB (mrc data) to the MRC area in CBMEM
*/
-void * find_hob_by_guid(void *current_hob, EFI_GUID *guid)
+int save_mrc_data(void *hob_start)
{
- do {
- switch (((EFI_HOB_GENERIC_HEADER *)current_hob)->HobType) {
+ 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;
- 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;
- }
+ mrc_hob = get_next_guid_hob(&mrc_guid, hob_start);
+ if (mrc_hob == NULL) {
+ printk(BIOS_DEBUG,
+ "Memory Configure Data Hob is not present\n");
+ return 0;
+ }
- 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));
+ mrc_hob_data = GET_GUID_HOB_DATA(mrc_hob);
+ mrc_hob_size = (u32) GET_HOB_LENGTH(mrc_hob);
- return NULL;
-}
+ printk(BIOS_DEBUG, "Memory Configure Data Hob at %p (size = 0x%x).\n",
+ (void *)mrc_hob_data, mrc_hob_size);
-/** 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;
+ 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));
- if ((*(guid_1) != *(guid_2)) || (*(guid_1 + 1) != *(guid_2 + 1)))
+ /* 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);
+
+#if IS_ENABLED(CONFIG_DISPLAY_FAST_BOOT_DATA)
+ printk(BIOS_SPEW, "Fast boot data (includes align and checksum):\n");
+ hexdump32(BIOS_SPEW, (void *)mrc_data->mrc_data, output_len);
+#endif
return 1;
}
+
+void __attribute__ ((weak)) update_mrc_cache(void *unused)
+{
+ printk(BIOS_ERR, "Add routine %s to save the MRC data.\n", __func__);
+}
+#endif /* CONFIG_ENABLE_MRC_CACHE */
+
+#if ENV_RAMSTAGE
+
+static void find_fsp_hob_update_mrc(void *unused)
+{
+ void *hob_list_ptr;
+
+ /* 0x0000: Print all types */
+ hob_list_ptr = get_hob_list();
+#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
+ print_hob_type_structure(0x000, hob_list_ptr);
+#endif
+
+ #if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+ if (save_mrc_data(hob_list_ptr))
+ update_mrc_cache(NULL);
+ else
+ printk(BIOS_DEBUG, "Not updating MRC data in flash.\n");
+ #endif
+}
+
+/* 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 /* ENV_RAMSTAGE */