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/10052
-gerrit
commit 339ad4ac9e605f370e3d23acc524ed895d1431f9
Author: Lee Leahy <leroy.p.leahy(a)intel.com>
Date: Fri May 1 10:34:54 2015 -0700
DO NOT MERGE: mainboard/intel/strago
Initial files to support the Intel RVP for Braswell
BRANCH=none
BUG=None
TEST=Build and run on Braswell
Change-Id: I5cb2efe3d8adf919165c62b25e08c544b316a05a
Signed-off-by: Lee Leahy <leroy.p.leahy(a)intel.com>
---
src/mainboard/intel/strago/Kconfig | 64 +++++
src/mainboard/intel/strago/Kconfig.name | 2 +
src/mainboard/intel/strago/Makefile.inc | 33 +++
src/mainboard/intel/strago/acpi/chromeos.asl | 37 +++
src/mainboard/intel/strago/acpi/dptf.asl | 93 +++++++
src/mainboard/intel/strago/acpi/ec.asl | 25 ++
src/mainboard/intel/strago/acpi/mainboard.asl | 259 ++++++++++++++++++++
src/mainboard/intel/strago/acpi/superio.asl | 34 +++
src/mainboard/intel/strago/acpi_tables.c | 234 ++++++++++++++++++
src/mainboard/intel/strago/chromeos.c | 143 +++++++++++
src/mainboard/intel/strago/cmos.layout | 140 +++++++++++
src/mainboard/intel/strago/com_init.c | 57 +++++
src/mainboard/intel/strago/devicetree.cb | 68 ++++++
src/mainboard/intel/strago/dsdt.asl | 59 +++++
src/mainboard/intel/strago/ec.c | 55 +++++
src/mainboard/intel/strago/ec.h | 69 ++++++
src/mainboard/intel/strago/fadt.c | 51 ++++
src/mainboard/intel/strago/fsp.c | 74 ++++++
src/mainboard/intel/strago/gpio.c | 266 +++++++++++++++++++++
src/mainboard/intel/strago/irqroute.c | 23 ++
src/mainboard/intel/strago/irqroute.h | 64 +++++
src/mainboard/intel/strago/mainboard.c | 27 +++
src/mainboard/intel/strago/onboard.h | 92 +++++++
src/mainboard/intel/strago/romstage.c | 43 ++++
src/mainboard/intel/strago/smihandler.c | 168 +++++++++++++
src/mainboard/intel/strago/spd/Makefile.inc | 41 ++++
.../spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex | 32 +++
...nix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR.spd.hex | 32 +++
.../spd/samsung_2GiB_dimm_K4B4G1646Q-HYK0.spd.hex | 32 +++
src/mainboard/intel/strago/spd/spd.c | 115 +++++++++
src/mainboard/intel/strago/w25q64.c | 75 ++++++
31 files changed, 2507 insertions(+)
diff --git a/src/mainboard/intel/strago/Kconfig b/src/mainboard/intel/strago/Kconfig
new file mode 100755
index 0000000..4b88a22
--- /dev/null
+++ b/src/mainboard/intel/strago/Kconfig
@@ -0,0 +1,64 @@
+if BOARD_INTEL_STRAGO
+
+config BOARD_SPECIFIC_OPTIONS
+ def_bool y
+# select ALWAYS_LOAD_OPROM
+ select BOARD_ROMSIZE_KB_8192
+# select CHROMEOS
+# select CHROMEOS_VBNV_CMOS
+ select EC_GOOGLE_CHROMEEC
+# select EC_GOOGLE_CHROMEEC_MEC
+# select EC_GOOGLE_CHROMEEC_ACPI_MEMMAP
+# select ENABLE_BUILTIN_COM1
+ select HAVE_ACPI_TABLES
+ select HAVE_OPTION_TABLE
+ select SOC_INTEL_BRASWELL
+ select VIRTUAL_DEV_SWITCH
+
+config DISPLAY_SPD_DATA
+ bool "Display Memory Serial Presence Detect Data"
+ default n
+ help
+ When enabled displays the memory configuration data.
+
+config DISPLAY_SPD_DATA
+ bool "Display Memory Serial Presence Detect Data"
+ default n
+ help
+ When enabled displays the memory SPD data.
+config DYNAMIC_VNN_SUPPORT
+ bool "Enables support for Dynamic VNN"
+ default n
+config MAINBOARD_DIR
+ string
+ default intel/strago
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "Strago"
+
+config MAINBOARD_VENDOR
+ string
+ default "Intel"
+
+config VBOOT_RAMSTAGE_INDEX
+ hex
+ default 0x2
+
+config VBOOT_REFCODE_INDEX
+ hex
+ default 0x3
+
+if !CONFIG_GOP_SUPPORT
+config VGA_BIOS_FILE
+ string
+ default "3rdparty/mainboard/intel/strago/vgabios_c0.bin" if C0_DISP_SUPPORT
+ default "3rdparty/mainboard/intel/strago/vgabios.bin" if !C0_DISP_SUPPORT
+
+config VGA_BIOS_ID
+ string
+ default "8086,22b1" if C0_DISP_SUPPORT
+ default "8086,22b0" if !C0_DISP_SUPPORT
+endif
+
+endif # BOARD_INTEL_STRAGO
diff --git a/src/mainboard/intel/strago/Kconfig.name b/src/mainboard/intel/strago/Kconfig.name
new file mode 100644
index 0000000..aae2379
--- /dev/null
+++ b/src/mainboard/intel/strago/Kconfig.name
@@ -0,0 +1,2 @@
+config BOARD_INTEL_STRAGO
+ bool "Strago"
diff --git a/src/mainboard/intel/strago/Makefile.inc b/src/mainboard/intel/strago/Makefile.inc
new file mode 100755
index 0000000..7a964a3
--- /dev/null
+++ b/src/mainboard/intel/strago/Makefile.inc
@@ -0,0 +1,33 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google Inc.
+## 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
+##
+
+subdirs-y += spd
+
+romstage-$(CONFIG_CHROMEOS) += chromeos.c
+romstage-$(CONFIG_ENABLE_BUILTIN_COM1) += com_init.c
+romstage-y += fsp.c
+
+ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+ramstage-y += ec.c
+ramstage-$(CONFIG_CHROMEOS) += gpio.c
+ramstage-y += irqroute.c
+ramstage-y += w25q64.c
+
+smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c
diff --git a/src/mainboard/intel/strago/acpi/chromeos.asl b/src/mainboard/intel/strago/acpi/chromeos.asl
new file mode 100644
index 0000000..04edefa
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi/chromeos.asl
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Google Inc.
+ * 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
+ */
+
+/*
+ * Fields are in the following order.
+ * - Type: recovery = 1 developer mode = 2 write protect = 3
+ * - Active Level - if -1 not a valid gpio
+ * - GPIO number encoding - if -1 not a valid gpio
+ * - Chipset Name
+ *
+ * Note: We need to encode gpios within the 3 separate banks
+ * with the MMIO offset of each banks space. e.g. GPIO_SUS[8] would be encoded
+ * as 0x2008 where the SUS offset (IO_BASE_OFFSET_GPSSUS) is 0x2000.
+ */
+
+Name(OIPG, Package() {
+ /* No physical recovery button */
+ Package () { 0x0001, 0, 0xFFFFFFFF, "Braswell" },
+ Package () { 0x0003, 1, 0x2006, "Braswell" },
+})
diff --git a/src/mainboard/intel/strago/acpi/dptf.asl b/src/mainboard/intel/strago/acpi/dptf.asl
new file mode 100755
index 0000000..67bdbb4
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi/dptf.asl
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2105 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
+ */
+
+#define DPTF_TSR0_SENSOR_ID 0
+#define DPTF_TSR0_SENSOR_NAME "TMP432_Internal"
+#define DPTF_TSR0_PASSIVE 48
+#define DPTF_TSR0_CRITICAL 70
+
+
+#define DPTF_TSR1_SENSOR_ID 1
+#define DPTF_TSR1_SENSOR_NAME "TMP432_Power_top"
+#define DPTF_TSR1_PASSIVE 60
+#define DPTF_TSR1_CRITICAL 70
+
+#define DPTF_TSR2_SENSOR_ID 2
+#define DPTF_TSR2_SENSOR_NAME "TMP432_CPU_bottom"
+#define DPTF_TSR2_PASSIVE 55
+#define DPTF_TSR2_CRITICAL 70
+
+
+#define DPTF_ENABLE_CHARGER
+
+/* Charger performance states, board-specific values from charger and EC */
+Name (CHPS, Package () {
+ Package () { 0, 0, 0, 0, 255, 0x6a4, "mA", 0 }, /* 1.7A (MAX) */
+ Package () { 0, 0, 0, 0, 24, 0x600, "mA", 0 }, /* 1.5A */
+ Package () { 0, 0, 0, 0, 16, 0x400, "mA", 0 }, /* 1.0A */
+ Package () { 0, 0, 0, 0, 8, 0x200, "mA", 0 }, /* 0.5A */
+ Package () { 0, 0, 0, 0, 0, 0x000, "mA", 0 }, /* 0.0A */
+})
+
+/* Mainboard specific _PDL is 1GHz */
+Name (MPDL, 8)
+
+Name (DTRT, Package () {
+ /* CPU Throttle Effect on CPU */
+ Package () { \_SB.PCI0.B0DB, \_SB.PCI0.B0DB, 100, 50, 0, 0, 0, 0 },
+
+ /* CPU Effect on Temp Sensor 0 */
+ Package () { \_SB.PCI0.B0DB, \_SB.DPTF.TSR0, 100, 600, 0, 0, 0, 0 },
+
+#ifdef DPTF_ENABLE_CHARGER
+ /* Charger Effect on Temp Sensor 1 */
+ Package () { \_SB.DPTF.TCHG, \_SB.DPTF.TSR1, 200, 600, 0, 0, 0, 0 },
+#endif
+
+ /* CPU Effect on Temp Sensor 1 */
+ Package () { \_SB.PCI0.B0DB, \_SB.DPTF.TSR1, 100, 600, 0, 0, 0, 0 },
+
+ /* CPU Effect on Temp Sensor 2 */
+ Package () { \_SB.PCI0.B0DB, \_SB.DPTF.TSR2, 100, 600, 0, 0, 0, 0 },
+})
+
+Name (MPPC, Package ()
+{
+ 0x2, /* Revision */
+ Package () { /* Power Limit 1 */
+ 0, /* PowerLimitIndex, 0 for Power Limit 1 */
+ 1600, /* PowerLimitMinimum */
+ 6200, /* PowerLimitMaximum */
+ 1000, /* TimeWindowMinimum */
+ 1000, /* TimeWindowMaximum */
+ 200 /* StepSize */
+ },
+ Package () { /* Power Limit 2 */
+ 1, /* PowerLimitIndex, 1 for Power Limit 2 */
+ 8000, /* PowerLimitMinimum */
+ 8000, /* PowerLimitMaximum */
+ 1000, /* TimeWindowMinimum */
+ 1000, /* TimeWindowMaximum */
+ 1000 /* StepSize */
+ }
+})
+
+/* Include DPTF */
+#include <soc/intel/braswell/acpi/dptf/dptf.asl>
diff --git a/src/mainboard/intel/strago/acpi/ec.asl b/src/mainboard/intel/strago/acpi/ec.asl
new file mode 100755
index 0000000..4733a60
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi/ec.asl
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * Copyright (C) 2105 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
+ */
+
+/* mainboard configuration */
+#include <mainboard/intel/strago/ec.h>
+
+/* ACPI code for EC functions */
+#include <ec/google/chromeec/acpi/ec.asl>
diff --git a/src/mainboard/intel/strago/acpi/mainboard.asl b/src/mainboard/intel/strago/acpi/mainboard.asl
new file mode 100755
index 0000000..3528467
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi/mainboard.asl
@@ -0,0 +1,259 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * 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 <mainboard/intel/strago/onboard.h>
+
+Scope (\_SB)
+{
+ Device (LID0)
+ {
+ Name (_HID, EisaId ("PNP0C0D"))
+ Method (_LID, 0)
+ {
+ Store (\_SB.PCI0.LPCB.EC0.LIDS, \LIDS)
+ Return (\LIDS)
+ }
+ }
+
+ Device (PWRB)
+ {
+ Name (_HID, EisaId ("PNP0C0C"))
+ Name (_UID, 1)
+ }
+}
+
+/*
+ * LPC Trusted Platform Module
+ */
+Scope (\_SB.PCI0.LPCB)
+{
+ #include <drivers/pc80/tpm/acpi/tpm.asl>
+}
+Scope (\_SB.I2C1)
+{
+ Device (ATSB)
+ {
+ Name (_HID, "ATML0001")
+ Name (_DDN, "Atmel Touchscreen Bootloader")
+ Name (_UID, 4)
+ Name (ISTP, 0) /* TouchScreen */
+
+ Name (_CRS, ResourceTemplate()
+ {
+ I2cSerialBus (
+ 0x26, /* SlaveAddress */
+ ControllerInitiated, /* SlaveMode */
+ 400000, /* ConnectionSpeed */
+ AddressingMode7Bit, /* AddressingMode */
+ "\\_SB.I2C1", /* ResourceSource */
+ )
+ Interrupt (ResourceConsumer, Edge, ActiveLow)
+ {
+ BOARD_TOUCHSCREEN_IRQ
+ }
+ })
+
+ Method (_STA)
+ {
+ If (LEqual (\S1EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ /* Allow device to power off in S0 */
+ Name (_S0W, 4)
+ }
+
+ Device (ATSA)
+ {
+ Name (_HID, "ATML0001")
+ Name (_DDN, "Atmel Touchscreen")
+ Name (_UID, 5)
+ Name (ISTP, 0) /* TouchScreen */
+
+ Name (_CRS, ResourceTemplate()
+ {
+ I2cSerialBus (
+ 0x4b, /* SlaveAddress */
+ ControllerInitiated, /* SlaveMode */
+ 400000, /* ConnectionSpeed */
+ AddressingMode7Bit, /* AddressingMode */
+ "\\_SB.I2C1", /* ResourceSource */
+ )
+ Interrupt (ResourceConsumer, Edge, ActiveLow)
+ {
+ BOARD_TOUCHSCREEN_IRQ
+ }
+ })
+
+ Method (_STA)
+ {
+ If (LEqual (\S1EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ Name (_PRW, Package() { BOARD_TOUCHSCREEN_WAKE_GPIO, 0x3 })
+
+ /* Allow device to power off in S0 */
+ Name (_S0W, 4)
+ }
+}
+
+Scope (\_SB.I2C2)
+{
+ /* Realtek Audio Codec */
+ Device (RTEK) /* Audio Codec driver I2C */
+ {
+ Name (_ADR, 0)
+ Name (_HID, AUDIO_CODEC_HID)
+ Name (_CID, AUDIO_CODEC_CID)
+ Name (_DDN, AUDIO_CODEC_DDN)
+ Name (_UID, 1)
+
+ Method(_CRS, 0x0, NotSerialized)
+ {
+ Name(SBUF,ResourceTemplate ()
+ {
+ I2CSerialBus(
+ AUDIO_CODEC_I2C_ADDR, /* SlaveAddress: bus address */
+ ControllerInitiated, /* SlaveMode: default to ControllerInitiated */
+ 400000, /* ConnectionSpeed: in Hz */
+ AddressingMode7Bit, /* Addressing Mode: default to 7 bit */
+ "\\_SB.I2C2", /* ResourceSource: I2C bus controller name */
+ )
+
+ Interrupt (ResourceConsumer, Edge, ActiveLow)
+ {
+ BOARD_CODEC_IRQ
+ }
+
+ /* Jack Detect (index 0) */
+ GpioInt (Edge, ActiveLow, ExclusiveAndWake, PullNone,,
+ "\\_SB.GPSE") { JACK_DETECT_GPIO_INDEX }
+ } )
+ Return (SBUF)
+ }
+
+ Method (_STA)
+ {
+ If (LEqual (\S2EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+ }
+}
+
+Scope (\_SB.I2C5)
+{
+ Device (ALSI)
+ {
+ /*
+ * TODO(dlaurie): Need official HID.
+ *
+ * The current HID is created from the Intersil PNP
+ * Vendor ID "LSD" and a shortened device identifier.
+ */
+ Name (_HID, EisaId ("LSD2918"))
+ Name (_DDN, "Intersil 29018 Ambient Light Sensor")
+ Name (_UID, 1)
+
+ Name (_CRS, ResourceTemplate()
+ {
+ I2cSerialBus (
+ 0x44, /* SlaveAddress */
+ ControllerInitiated, /* SlaveMode */
+ 400000, /* ConnectionSpeed */
+ AddressingMode7Bit, /* AddressingMode */
+ "\\_SB.I2C5", /* ResourceSource */
+ )
+ Interrupt (ResourceConsumer, Edge, ActiveLow)
+ {
+ BOARD_ALS_IRQ
+ }
+ })
+
+ Method (_STA)
+ {
+ If (LEqual (\S5EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+ }
+}
+
+Scope (\_SB.I2C6)
+{
+ Device (ETPA)
+ {
+ Name (_HID, "ELAN0000")
+ Name (_DDN, "Elan Touchpad")
+ Name (_UID, 3)
+ Name (ISTP, 1) /* Touchpad */
+
+ Name (_CRS, ResourceTemplate()
+ {
+ I2cSerialBus (
+ 0x15, /* SlaveAddress */
+ ControllerInitiated, /* SlaveMode */
+ 400000, /* ConnectionSpeed */
+ AddressingMode7Bit, /* AddressingMode */
+ "\\_SB.I2C6", /* ResourceSource */
+ )
+ Interrupt (ResourceConsumer, Edge, ActiveLow)
+ {
+ BOARD_TRACKPAD_IRQ
+ }
+ })
+
+ Method (_STA)
+ {
+ If (LEqual (\S6EN, 1)) {
+ Return (0xF)
+ } Else {
+ Return (0x0)
+ }
+ }
+
+ Name (_PRW, Package() { BOARD_TRACKPAD_WAKE_GPIO, 0x3 })
+ /* Allow device to power off in S0 */
+ Name (_S0W, 4)
+ }
+}
+
+Scope (\_SB.LPEA)
+{
+ Name (GBUF, ResourceTemplate ()
+ {
+ /* Jack Detect (index 0) */
+ GpioInt (Edge, ActiveLow, ExclusiveAndWake, PullNone,,
+ "\\_SB.GPSE") { JACK_DETECT_GPIO_INDEX }
+ })
+}
diff --git a/src/mainboard/intel/strago/acpi/superio.asl b/src/mainboard/intel/strago/acpi/superio.asl
new file mode 100755
index 0000000..931678b
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi/superio.asl
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Google Inc.
+ * 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
+ */
+
+/* mainboard configuration */
+#include <mainboard/intel/strago/ec.h>
+#include <mainboard/intel/strago/onboard.h>
+
+#define SIO_EC_MEMMAP_ENABLE /* EC Memory Map Resources */
+#define SIO_EC_HOST_ENABLE /* EC Host Interface Resources */
+#define SIO_EC_ENABLE_PS2K /* Enable PS/2 Keyboard */
+
+/* Override default IRQ settings */
+#define SIO_EC_PS2K_IRQ Interrupt(ResourceConsumer, Edge, ActiveLow){\
+ BOARD_I8042_IRQ}
+
+/* ACPI code for EC SuperIO functions */
+#include <ec/google/chromeec/acpi/superio.asl>
diff --git a/src/mainboard/intel/strago/acpi_tables.c b/src/mainboard/intel/strago/acpi_tables.c
new file mode 100755
index 0000000..00301b6
--- /dev/null
+++ b/src/mainboard/intel/strago/acpi_tables.c
@@ -0,0 +1,234 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * 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 <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <arch/ioapic.h>
+#include <arch/smp/mpspec.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/msr.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/acpi.h>
+#include <soc/iomap.h>
+#include <soc/nvs.h>
+#include <string.h>
+#include <types.h>
+
+extern const unsigned char AmlCode[];
+
+static void acpi_create_gnvs(global_nvs_t *gnvs)
+{
+ acpi_init_gnvs(gnvs);
+
+ /* Enable USB ports in S3 */
+ gnvs->s3u0 = 1;
+ gnvs->s3u1 = 1;
+
+ /* Disable USB ports in S5 */
+ gnvs->s5u0 = 0;
+ gnvs->s5u1 = 0;
+
+ /* Enable DPTF */
+ gnvs->dpte = 1;
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ /* Local APICs */
+ current = acpi_create_madt_lapics(current);
+
+ /* IOAPIC */
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+ 2, IO_APIC_ADDR, 0);
+
+ current = acpi_madt_irq_overrides(current);
+
+ return current;
+}
+
+unsigned long acpi_fill_ssdt_generator(unsigned long current,
+ const char *oem_table_id)
+{
+ generate_cpu_entries();
+ return (unsigned long) (acpigen_get_current());
+}
+
+unsigned long acpi_fill_slit(unsigned long current)
+{
+ /* Not implemented */
+ return current;
+}
+
+unsigned long acpi_fill_srat(unsigned long current)
+{
+ /* No NUMA, no SRAT */
+ return current;
+}
+
+#define ALIGN_CURRENT (current = (ALIGN(current, 16)))
+
+unsigned long write_acpi_tables(unsigned long start)
+{
+ unsigned long current;
+ int i;
+ acpi_rsdp_t *rsdp;
+ acpi_rsdt_t *rsdt;
+ acpi_xsdt_t *xsdt;
+ acpi_hpet_t *hpet;
+ acpi_madt_t *madt;
+ acpi_mcfg_t *mcfg;
+ acpi_fadt_t *fadt;
+ acpi_facs_t *facs;
+ acpi_header_t *ssdt;
+ acpi_header_t *dsdt;
+ global_nvs_t *gnvs;
+
+ current = start;
+
+ /* Align ACPI tables to 16byte */
+ ALIGN_CURRENT;
+
+ printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
+
+ /* We need at least an RSDP and an RSDT Table */
+ rsdp = (acpi_rsdp_t *) current;
+ current += sizeof(acpi_rsdp_t);
+ ALIGN_CURRENT;
+ rsdt = (acpi_rsdt_t *) current;
+ current += sizeof(acpi_rsdt_t);
+ ALIGN_CURRENT;
+ xsdt = (acpi_xsdt_t *) current;
+ current += sizeof(acpi_xsdt_t);
+ ALIGN_CURRENT;
+
+ /* clear all table memory */
+ memset((void *) start, 0, current - start);
+
+ acpi_write_rsdp(rsdp, rsdt, xsdt);
+ acpi_write_rsdt(rsdt);
+ acpi_write_xsdt(xsdt);
+
+ printk(BIOS_DEBUG, "ACPI: * FACS\n");
+ facs = (acpi_facs_t *) current;
+ current += sizeof(acpi_facs_t);
+ ALIGN_CURRENT;
+ acpi_create_facs(facs);
+
+ printk(BIOS_DEBUG, "ACPI: * DSDT\n");
+ dsdt = (acpi_header_t *) current;
+ memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
+ current += dsdt->length;
+ memcpy(dsdt, &AmlCode, dsdt->length);
+
+ ALIGN_CURRENT;
+
+ printk(BIOS_DEBUG, "ACPI: * FADT\n");
+ fadt = (acpi_fadt_t *) current;
+ current += sizeof(acpi_fadt_t);
+ ALIGN_CURRENT;
+
+ acpi_create_fadt(fadt, facs, dsdt);
+ acpi_add_table(rsdp, fadt);
+
+ /*
+ * We explicitly add these tables later on:
+ */
+ printk(BIOS_DEBUG, "ACPI: * HPET\n");
+ hpet = (acpi_hpet_t *) current;
+ current += sizeof(acpi_hpet_t);
+ ALIGN_CURRENT;
+ acpi_create_intel_hpet(hpet);
+ acpi_add_table(rsdp, hpet);
+
+ /* If we want to use HPET Timers Linux wants an MADT */
+ printk(BIOS_DEBUG, "ACPI: * MADT\n");
+
+ madt = (acpi_madt_t *) current;
+ acpi_create_madt(madt);
+ current += madt->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, madt);
+
+ printk(BIOS_DEBUG, "ACPI: * MCFG\n");
+ mcfg = (acpi_mcfg_t *) current;
+ acpi_create_mcfg(mcfg);
+ current += mcfg->header.length;
+ ALIGN_CURRENT;
+ acpi_add_table(rsdp, mcfg);
+#if CONFIG_GOP_SUPPORT
+ igd_opregion_t *opregion;
+ printk(BIOS_DEBUG, "ACPI: * IGD OpRegion\n");
+ opregion = (igd_opregion_t *)current;
+ init_igd_opregion(opregion);
+ current += sizeof(igd_opregion_t);
+ ALIGN_CURRENT;
+#endif
+
+ /* Update GNVS pointer into CBMEM */
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (!gnvs) {
+ printk(BIOS_DEBUG, "ACPI: Could not find CBMEM GNVS\n");
+ gnvs = (global_nvs_t *)current;
+ }
+
+ for (i = 0; i < dsdt->length; i++) {
+ if (*(u32 *)(((u32)dsdt) + i) == 0xC0DEBABE) {
+ printk(BIOS_DEBUG,
+ "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> %p\n",
+ i, gnvs);
+ *(u32 *)(((u32)dsdt) + i) = (unsigned long)gnvs;
+ acpi_save_gnvs((unsigned long)gnvs);
+ break;
+ }
+ }
+
+ /* And fill it */
+ acpi_create_gnvs(gnvs);
+
+ /* And tell SMI about it */
+#if IS_ENABLED(CONFIG_SMM_MODULES)
+ smm_setup_structures(gnvs, NULL, NULL);
+#endif
+
+ current += sizeof(global_nvs_t);
+ ALIGN_CURRENT;
+
+ /* We patched up the DSDT, so we need to recalculate the checksum */
+ dsdt->checksum = 0;
+ dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
+
+ printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n", dsdt,
+ dsdt->length);
+
+ printk(BIOS_DEBUG, "ACPI: * SSDT\n");
+ ssdt = (acpi_header_t *)current;
+ acpi_create_ssdt_generator(ssdt, ACPI_TABLE_CREATOR);
+ current += ssdt->length;
+ acpi_add_table(rsdp, ssdt);
+ ALIGN_CURRENT;
+
+ printk(BIOS_DEBUG, "current = %lx\n", current);
+ printk(BIOS_INFO, "ACPI: done.\n");
+ return current;
+}
diff --git a/src/mainboard/intel/strago/chromeos.c b/src/mainboard/intel/strago/chromeos.c
new file mode 100755
index 0000000..3987b64
--- /dev/null
+++ b/src/mainboard/intel/strago/chromeos.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+#include "ec.h"
+#include <ec/google/chromeec/ec.h>
+#endif
+#include <soc/gpio.h>
+#include <string.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+
+/* The WP status pin lives on GPIO_SSUS_6 which is pad 36 in the SUS well. */
+#define WP_STATUS_PAD 36
+
+#ifndef __PRE_RAM__
+#include <boot/coreboot_tables.h>
+
+#define GPIO_COUNT 6
+#define ACTIVE_LOW 0
+#define ACTIVE_HIGH 1
+
+static int get_lid_switch(void)
+{
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ u8 ec_switches;
+
+ mec_io_bytes(0, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES, 1,
+ &ec_switches, NULL);
+
+ return !!(ec_switches & EC_SWITCH_LID_OPEN);
+#else
+ /* Default to force open. */
+ return 1;
+#endif
+}
+
+static void fill_lb_gpio(struct lb_gpio *gpio, int port, int polarity,
+ const char *name, int force)
+{
+ memset(gpio, 0, sizeof(*gpio));
+ gpio->port = port;
+ gpio->polarity = polarity;
+ if (force >= 0)
+ gpio->value = force;
+ strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH);
+}
+
+void fill_lb_gpios(struct lb_gpios *gpios)
+{
+ struct lb_gpio *gpio;
+
+ gpios->size = sizeof(*gpios) + (GPIO_COUNT * sizeof(struct lb_gpio));
+ gpios->count = GPIO_COUNT;
+
+ gpio = gpios->gpios;
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "write protect",
+ get_write_protect_state());
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "recovery",
+ recovery_mode_enabled());
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "developer",
+ get_developer_mode_switch());
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "lid", get_lid_switch());
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "power", 0);
+ fill_lb_gpio(gpio++, -1, ACTIVE_HIGH, "oprom", oprom_is_loaded);
+}
+#endif
+
+int get_developer_mode_switch(void)
+{
+ return 0;
+}
+
+int get_recovery_mode_switch(void)
+{
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ u8 ec_switches;
+ u32 ec_events;
+ mec_io_bytes(0, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES, 1,
+ &ec_switches, NULL);
+
+ /* If a switch is set, we don't need to look at events. */
+ if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY))
+ return 1;
+
+ /* Else check if the EC has posted the keyboard recovery event. */
+ ec_events = google_chromeec_get_events_b();
+
+ return !!(ec_events &
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY));
+#else
+ return 0;
+#endif
+}
+
+int clear_recovery_mode_switch(void)
+{
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ const uint32_t kb_rec_mask =
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY);
+ /* Unconditionally clear the EC recovery request. */
+ return google_chromeec_clear_events_b(kb_rec_mask);
+#else
+ return 0;
+#endif
+}
+
+int get_write_protect_state(void)
+{
+ /*
+ * The vboot loader queries this function in romstage. The GPIOs have
+ * not been set up yet as that configuration is done in ramstage. The
+ * hardware defaults to an input but there is a 20K pulldown. Externally
+ * there is a 10K pullup. Disable the internal pull in romstage so that
+ * there isn't any ambiguity in the reading.
+ */
+#if defined(__PRE_RAM__)
+ ssus_disable_internal_pull(WP_STATUS_PAD);
+#endif
+
+ /* WP is enabled when the pin is reading high. */
+ return ssus_get_gpio(WP_STATUS_PAD);
+}
diff --git a/src/mainboard/intel/strago/cmos.layout b/src/mainboard/intel/strago/cmos.layout
new file mode 100644
index 0000000..18bf4ce
--- /dev/null
+++ b/src/mainboard/intel/strago/cmos.layout
@@ -0,0 +1,140 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2008 coresystems GmbH
+## 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
+##
+
+# -----------------------------------------------------------------
+entries
+
+#start-bit length config config-ID name
+#0 8 r 0 seconds
+#8 8 r 0 alarm_seconds
+#16 8 r 0 minutes
+#24 8 r 0 alarm_minutes
+#32 8 r 0 hours
+#40 8 r 0 alarm_hours
+#48 8 r 0 day_of_week
+#56 8 r 0 day_of_month
+#64 8 r 0 month
+#72 8 r 0 year
+# -----------------------------------------------------------------
+# Status Register A
+#80 4 r 0 rate_select
+#84 3 r 0 REF_Clock
+#87 1 r 0 UIP
+# -----------------------------------------------------------------
+# Status Register B
+#88 1 r 0 auto_switch_DST
+#89 1 r 0 24_hour_mode
+#90 1 r 0 binary_values_enable
+#91 1 r 0 square-wave_out_enable
+#92 1 r 0 update_finished_enable
+#93 1 r 0 alarm_interrupt_enable
+#94 1 r 0 periodic_interrupt_enable
+#95 1 r 0 disable_clock_updates
+# -----------------------------------------------------------------
+# Status Register C
+#96 4 r 0 status_c_rsvd
+#100 1 r 0 uf_flag
+#101 1 r 0 af_flag
+#102 1 r 0 pf_flag
+#103 1 r 0 irqf_flag
+# -----------------------------------------------------------------
+# Status Register D
+#104 7 r 0 status_d_rsvd
+#111 1 r 0 valid_cmos_ram
+# -----------------------------------------------------------------
+# Diagnostic Status Register
+#112 8 r 0 diag_rsvd1
+
+# -----------------------------------------------------------------
+0 120 r 0 reserved_memory
+#120 264 r 0 unused
+
+# -----------------------------------------------------------------
+# RTC_BOOT_BYTE (coreboot hardcoded)
+384 1 e 4 boot_option
+385 1 e 4 last_boot
+388 4 r 0 reboot_bits
+#390 2 r 0 unused?
+
+# -----------------------------------------------------------------
+# coreboot config options: console
+392 3 e 5 baud_rate
+395 4 e 6 debug_level
+#399 1 r 0 unused
+
+# coreboot config options: cpu
+400 1 e 2 hyper_threading
+#401 7 r 0 unused
+
+# coreboot config options: southbridge
+408 1 e 1 nmi
+409 2 e 7 power_on_after_fail
+#411 5 r 0 unused
+
+# coreboot config options: bootloader
+#Used by ChromeOS:
+416 128 r 0 vbnv
+#544 440 r 0 unused
+
+# SandyBridge MRC Scrambler Seed values
+896 32 r 0 mrc_scrambler_seed
+928 32 r 0 mrc_scrambler_seed_s3
+
+# coreboot config options: check sums
+984 16 h 0 check_sum
+#1000 24 r 0 amd_reserved
+
+# -----------------------------------------------------------------
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+5 0 115200
+5 1 57600
+5 2 38400
+5 3 19200
+5 4 9600
+5 5 4800
+5 6 2400
+5 7 1200
+6 1 Emergency
+6 2 Alert
+6 3 Critical
+6 4 Error
+6 5 Warning
+6 6 Notice
+6 7 Info
+6 8 Debug
+6 9 Spew
+7 0 Disable
+7 1 Enable
+7 2 Keep
+# -----------------------------------------------------------------
+checksums
+
+checksum 392 415 984
+
+
diff --git a/src/mainboard/intel/strago/com_init.c b/src/mainboard/intel/strago/com_init.c
new file mode 100755
index 0000000..c982178
--- /dev/null
+++ b/src/mainboard/intel/strago/com_init.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <arch/io.h>
+#include <soc/gpio.h>
+#include <soc/lpc.h>
+#include <soc/pci_devs.h>
+#include <soc/romstage.h>
+
+/*
+ * return family number and internal pad number in that community
+ * by pad number and which community it is in.
+ */
+
+
+
+ /* family number in high byte and inner pad number in lowest byte */
+
+void mainboard_pre_console_init(struct romstage_params *params)
+{
+ uint32_t reg;
+ uint32_t *pad_config_reg;
+
+ /* Enable the UART hardware for COM1. */
+ reg = 1;
+ pci_write_config32(PCI_DEV(0, LPC_DEV, 0), UART_CONT, reg);
+
+ /*
+ * Set up the pads to select the UART function for Strago
+ * AD12 SW16(UART1_DATAIN/UART0_DATAIN) - Setting Mode 2 for UART0_RXD
+ * AD10 SW20(UART1_DATAOUT/UART0_DATAOUT) - Setting Mode 2 for UART0_TXD
+ */
+ pad_config_reg = gpio_pad_config_reg(GP_SOUTHWEST, UART1_RXD_PAD);
+ write32(pad_config_reg, SET_PAD_MODE_SELECTION(PAD_CONFIG0_DEFAULT0,
+ M2));
+
+ pad_config_reg = gpio_pad_config_reg(GP_SOUTHWEST, UART1_TXD_PAD);
+ write32(pad_config_reg, SET_PAD_MODE_SELECTION(PAD_CONFIG0_DEFAULT0,
+ M2));
+}
diff --git a/src/mainboard/intel/strago/devicetree.cb b/src/mainboard/intel/strago/devicetree.cb
new file mode 100755
index 0000000..6ee81c3
--- /dev/null
+++ b/src/mainboard/intel/strago/devicetree.cb
@@ -0,0 +1,68 @@
+chip soc/intel/braswell
+
+ # LPE audio codec settings
+ register "lpe_codec_clk_freq" = "25" # 25MHz clock
+ register "lpe_codec_clk_num" = "0" # PMC_PLT_CLK[0]
+
+ # Enable devices in ACPI mode
+ register "lpss_acpi_mode" = "1"
+ register "emmc_acpi_mode" = "1"
+ register "sd_acpi_mode" = "1"
+ register "lpe_acpi_mode" = "1"
+
+ # Disable SLP_X stretching after SUS power well fail.
+ register "disable_slp_x_stretch_sus_fail" = "1"
+
+ device cpu_cluster 0 on
+ device lapic 0 on end
+ end
+ device domain 0 on
+ # EDS Table 24-4, Figure 24-5
+ device pci 00.0 on end # 8086 2280 - SoC transaction router
+ device pci 02.0 on end # 8086 22b0/22b1 - B1/C0 stepping Graphics and Display
+ device pci 03.0 on end # 8086 22b8 - Camera and Image Processor
+ device pci 0b.0 on end # 8086 22dc - ?
+ device pci 10.0 on end # 8086 2294 - MMC Port
+ device pci 11.0 off end # 8086 0F15 - SDIO Port
+ device pci 12.0 on end # 8086 0F16 - SD Port
+ device pci 13.0 off end # 8086 22a3 - Sata controller
+ device pci 14.0 on end # 8086 22b5 - USB XHCI - Only 1 USB controller at a time
+ device pci 15.0 on end # 8086 22a8 - LP Engine Audio
+ device pci 16.0 off end # 8086 22b7 - USB device
+ device pci 18.0 on end # 8086 22c0 - SIO - DMA
+ device pci 18.1 on end # 8086 22c1 - I2C Port 1
+ device pci 18.2 on end # 8086 22c2 - I2C Port 2
+ device pci 18.3 on end # 8086 22c3 - I2C Port 3
+ device pci 18.4 on end # 8086 22c4 - I2C Port 4
+ device pci 18.5 on end # 8086 22c5 - I2C Port 5
+ device pci 18.6 on end # 8086 22c6 - I2C Port 6
+ device pci 18.7 on end # 8086 22c7 - I2C Port 7
+ device pci 1a.0 on end # 8086 0F18 - Trusted Execution Engine
+ device pci 1b.0 on end # 8086 0F04 - HD Audio
+ device pci 1c.0 on end # 8086 0000 - PCIe Root Port 1
+ device pci 1c.1 on end # 8086 0000 - PCIe Root Port 2
+ device pci 1c.2 on end # 8086 0000 - PCIe Root Port 3
+ device pci 1c.3 on end # 8086 0000 - PCIe Root Port 4
+ device pci 1e.0 on end # 8086 2286 - SIO - DMA
+ device pci 1e.1 off end # 8086 0F08 - PWM 1
+ device pci 1e.2 off end # 8086 0F09 - PWM 2
+ device pci 1e.3 on end # 8086 228a - HSUART 1
+ device pci 1e.4 on end # 8086 228c - HSUART 2
+ device pci 1e.5 on end # 8086 228e - SPI 1
+ device pci 1e.6 on end # 8086 2290 - SPI 2
+ device pci 1e.7 on end # 8086 22ac - SPI 3
+ device pci 1f.0 on # 8086 229c - LPC bridge
+ chip drivers/pc80/tpm
+ # Rising edge interrupt
+ register "irq_polarity" = "2"
+ device pnp 0c31.0 on
+ irq 0x70 = 10
+ end
+ end
+ chip ec/google/chromeec
+ device pnp 0c09.0 on end
+ end
+ end # LPC Bridge
+ device pci 1f.3 off end # 8086 0F12 - SMBus 0
+ end
+end
diff --git a/src/mainboard/intel/strago/dsdt.asl b/src/mainboard/intel/strago/dsdt.asl
new file mode 100755
index 0000000..abeb8b3
--- /dev/null
+++ b/src/mainboard/intel/strago/dsdt.asl
@@ -0,0 +1,59 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ * 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
+ */
+
+
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ 0x05, /* DSDT revision: ACPI v5.0 */
+ "COREv4", /* OEM id */
+ "COREBOOT", /* OEM table id */
+ 0x20110725 /* OEM revision */
+)
+{
+ /* Some generic macros */
+ #include <soc/intel/braswell/acpi/platform.asl>
+
+ /* global NVS and variables */
+ #include <soc/intel/braswell/acpi/globalnvs.asl>
+
+ #include <soc/intel/braswell/acpi/cpu.asl>
+
+ Scope (\_SB) {
+ Device (PCI0)
+ {
+ /* #include <soc/intel/braswell/acpi/northcluster.asl> */
+ #include <soc/intel/braswell/acpi/southcluster.asl>
+ #include <soc/intel/braswell/acpi/dptf/cpu.asl>
+ }
+
+ /* Dynamic Platform Thermal Framework */
+ #include "acpi/dptf.asl"
+ }
+
+ #include "acpi/chromeos.asl"
+ #include <vendorcode/google/chromeos/acpi/chromeos.asl>
+
+ /* Chipset specific sleep states */
+ #include <soc/intel/braswell/acpi/sleepstates.asl>
+
+ #include "acpi/mainboard.asl"
+}
diff --git a/src/mainboard/intel/strago/ec.c b/src/mainboard/intel/strago/ec.c
new file mode 100755
index 0000000..8debaa4
--- /dev/null
+++ b/src/mainboard/intel/strago/ec.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * 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 <arch/acpi.h>
+#include <console/console.h>
+#include <ec/google/chromeec/ec.h>
+#include "ec.h"
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <types.h>
+
+void mainboard_ec_init(void)
+{
+ printk(BIOS_DEBUG, "mainboard_ec_init\n");
+ post_code(0xf0);
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ /* Restore SCI event mask on resume. */
+ if (acpi_slp_type == 3) {
+ google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS |
+ MAINBOARD_EC_S3_WAKE_EVENTS);
+
+ /* Disable SMI and wake events */
+ google_chromeec_set_smi_mask(0);
+
+ /* Clear pending events */
+ while (google_chromeec_get_event() != 0)
+ ;
+ google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS);
+ } else {
+ google_chromeec_log_events(MAINBOARD_EC_LOG_EVENTS |
+ MAINBOARD_EC_S5_WAKE_EVENTS);
+ }
+
+ /* Clear wake events, these are enabled on entry to sleep */
+ google_chromeec_set_wake_mask(0);
+#endif
+ post_code(0xf1);
+}
diff --git a/src/mainboard/intel/strago/ec.h b/src/mainboard/intel/strago/ec.h
new file mode 100755
index 0000000..7e70d48
--- /dev/null
+++ b/src/mainboard/intel/strago/ec.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Google Inc.
+ * 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
+ */
+
+#ifndef MAINBOARD_EC_H
+#define MAINBOARD_EC_H
+
+#include <ec/google/chromeec/ec_commands.h>
+
+/* GPIO_S0_000 is EC_SCI#, but it is bit 16 in GPE_STS */
+#define EC_SCI_GPI 16
+/* GPIO_S5_07 is EC_SMI#, but it is bit 19 in GPE_STS and ALT_GPIO_SMI. */
+#define EC_SMI_GPI 19
+
+#define MAINBOARD_EC_SCI_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_CONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_THRESHOLD) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_OVERLOAD) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_START) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_THROTTLE_STOP) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_USB_CHARGER))
+
+#define MAINBOARD_EC_SMI_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED))
+
+/* EC can wake from S5 with lid or power button */
+#define MAINBOARD_EC_S5_WAKE_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON))
+
+/* EC can wake from S3 with lid or power button or key press */
+#define MAINBOARD_EC_S3_WAKE_EVENTS \
+ (MAINBOARD_EC_S5_WAKE_EVENTS |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEY_PRESSED))
+
+/* Log EC wake events plus EC shutdown events */
+#define MAINBOARD_EC_LOG_EVENTS \
+ (EC_HOST_EVENT_MASK(EC_HOST_EVENT_THERMAL_SHUTDOWN) |\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_SHUTDOWN)|\
+ EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC))
+
+#ifndef __ACPI__
+extern void mainboard_ec_init(void);
+#endif
+
+#endif
diff --git a/src/mainboard/intel/strago/fadt.c b/src/mainboard/intel/strago/fadt.c
new file mode 100755
index 0000000..45a680a
--- /dev/null
+++ b/src/mainboard/intel/strago/fadt.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * 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 <soc/acpi.h>
+#include <string.h>
+
+void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+
+ memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+ memcpy(header->signature, "FACP", 4);
+ header->length = sizeof(acpi_fadt_t);
+ header->revision = 3;
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+ header->asl_compiler_revision = 1;
+
+ fadt->firmware_ctrl = (unsigned long) facs;
+ fadt->dsdt = (unsigned long) dsdt;
+ fadt->model = 1;
+ fadt->preferred_pm_profile = PM_MOBILE;
+
+ fadt->x_firmware_ctl_l = (unsigned long)facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (unsigned long)dsdt;
+ fadt->x_dsdt_h = 0;
+
+ acpi_fill_in_fadt(fadt);
+
+ header->checksum =
+ acpi_checksum((void *) fadt, header->length);
+}
diff --git a/src/mainboard/intel/strago/fsp.c b/src/mainboard/intel/strago/fsp.c
new file mode 100755
index 0000000..6cd5210
--- /dev/null
+++ b/src/mainboard/intel/strago/fsp.c
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 <arch/early_variables.h>
+#include <console/console.h>
+#include <lib.h> /* hexdump */
+#include <soc/romstage.h>
+
+#define BSW_SVID_CONFIG1 1
+#define BSW_SVID_CONFIG3 3
+
+void board_fsp_memory_init_params(
+ struct romstage_params *params,
+ FSP_INFO_HEADER *fsp_header,
+ FSP_MEMORY_INIT_PARAMS *fsp_memory_init_params)
+{
+ FSP_INIT_RT_COMMON_BUFFER *rt_buffer;
+ UPD_DATA_REGION *upd_ptr;
+
+ /* Initialize pointers to UPD and RT buffers */
+ rt_buffer = fsp_memory_init_params->RtBufferPtr;
+ upd_ptr = rt_buffer->UpdDataRgnPtr;
+
+ /* Update SPD and memory configuration data */
+ upd_ptr->PcdMemorySpdPtr = (u32)params->pei_data->spd_data_ch0;
+ upd_ptr->PcdMemChannel0Config = params->pei_data->spd_ch0_config;
+ upd_ptr->PcdMemChannel1Config = params->pei_data->spd_ch1_config;
+#if IS_ENABLED(CONFIG_GOP_SUPPORT)
+ /* Passing VBT table to FSP */
+ upd_ptr->PcdGraphicsConfigPtr = (u32)params->pei_data->vbt_data;
+#endif
+
+ /* Set the I/O map */
+ upd_ptr->PcdMrcInitTsegSize = 8; /* Use 8MB by default */
+
+ /* Enable/disable the devices */
+ upd_ptr->PcdSdcardMode = params->pei_data->sdcard_mode;
+ upd_ptr->PcdEmmcMode = params->pei_data->emmc_mode;
+ upd_ptr->PcdEnableAzalia = params->pei_data->enable_azalia;
+
+ /* Enable SVID and set the config policy */
+ upd_ptr->PunitPwrConfigDisable = 0;
+
+#if CONFIG_DYNAMIC_VNN_SUPPORT
+ upd_ptr->ChvSvidConfig = BSW_SVID_CONFIG1;
+#else
+ upd_ptr->ChvSvidConfig = BSW_SVID_CONFIG3;
+#endif
+
+ /* Disable IUNIT */
+ upd_ptr->ISPEnable = 0;
+
+ /* Disable FSP from locking access to the RTC NVRAM */
+ upd_ptr->PcdRtcLock = 0;
+
+ /* Disable SATA */
+ upd_ptr->PcdEnableSata = 0;
+}
diff --git a/src/mainboard/intel/strago/gpio.c b/src/mainboard/intel/strago/gpio.c
new file mode 100755
index 0000000..aa9d587
--- /dev/null
+++ b/src/mainboard/intel/strago/gpio.c
@@ -0,0 +1,266 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright(C) 2013 Google Inc.
+ * 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 "irqroute.h"
+#include <soc/gpio.h>
+#include <stdlib.h>
+
+/* South East Community */
+static const struct soc_gpio_map gpse_gpio_map[] = {
+ Native_M1,/* MF_PLT_CLK0 */
+ GPIO_NC, /* 01 PWM1 */
+ GPIO_INPUT_NO_PULL, /* 02 MF_PLT_CLK1, RAMID2 */
+ GPIO_NC, /* 03 MF_PLT_CLK4 */
+ GPIO_NC, /* 04 MF_PLT_CLK3 */
+ GPIO_NC, /* PWM0 05 */
+ GPIO_NC, /* 06 MF_PLT_CLK5 */
+ GPIO_NC, /* 07 MF_PLT_CLK2 */
+ GPIO_NC, /* 15 SDMMC2_D3_CD_B */
+ Native_M1, /* 16 SDMMC1_CLK */
+ NATIVE_PU20K(1), /* 17 SDMMC1_D0 */
+ GPIO_NC, /* 18 SDMMC2_D1 */
+ GPIO_NC, /* 19 SDMMC2_CLK */
+ NATIVE_PU20K(1),/* 20 SDMMC1_D2 */
+ GPIO_NC, /* 21 SDMMC2_D2 */
+ GPIO_NC, /* 22 SDMMC2_CMD */
+ NATIVE_PU20K(1), /* 23 SDMMC1_CMD */
+ NATIVE_PU20K(1), /* 24 SDMMC1_D1 */
+ GPIO_NC, /* 25 SDMMC2_D0 */
+ NATIVE_PU20K(1), /* 26 SDMMC1_D3_CD_B */
+ NATIVE_PU20K(1), /* 30 SDMMC3_D1 */
+ Native_M1, /* 31 SDMMC3_CLK */
+ NATIVE_PU20K(1), /* 32 SDMMC3_D3 */
+ NATIVE_PU20K(1), /* 33 SDMMC3_D2 */
+ NATIVE_PU20K(1), /* 34 SDMMC3_CMD */
+ NATIVE_PU20K(1), /* 35 SDMMC3_D0 */
+ NATIVE_PU20K(1), /* 45 MF_LPC_AD2 */
+ Native_M1, /* 46 LPC_CLKRUNB */
+ NATIVE_PU20K(1), /* 47 MF_LPC_AD0 */
+ Native_M1, /* 48 LPC_FRAMEB */
+ Native_M1, /* 49 MF_LPC_CLKOUT1 */
+ NATIVE_PU20K(1), /* 50 MF_LPC_AD3 */
+ Native_M1, /* 51 MF_LPC_CLKOUT0 */
+ NATIVE_PU20K(1), /* 52 MF_LPC_AD1 */
+ Native_M1,/* SPI1_MISO */
+ Native_M1, /* 61 SPI1_CS0_B */
+ Native_M1, /* SPI1_CLK */
+ NATIVE_PU20K(1), /* 63 MMC1_D6 */
+ Native_M1, /* 62 SPI1_MOSI */
+ NATIVE_PU20K(1), /* 65 MMC1_D5 */
+ GPIO_NC, /* SPI1_CS1_B 66 */
+ NATIVE_PU20K(1), /* 67 MMC1_D4_SD_WE */
+ NATIVE_PU20K(1), /* 68 MMC1_D7 */
+ GPIO_NC, /* 69 MMC1_RCLK */
+ Native_M1, /* 75 GPO USB_OC1_B */
+ Native_M1, /* 76 PMU_RESETBUTTON_B */
+ GPI(trig_edge_both, L0, NA, non_maskable, en_edge_detect, NA , NA),
+ /* GPIO_ALERT 77 */
+ Native_M1, /* 78 SDMMC3_PWR_EN_B */
+ GPIO_NC, /* 79 GPI ILB_SERIRQ */
+ Native_M1, /* 80 USB_OC0_B */
+ NATIVE_INT(1, L1), /* 81 SDMMC3_CD_B */
+ GPIO_NC, /* 82 spkr asummed gpio number */
+ Native_M1, /* 83 SUSPWRDNACK */
+ SPARE_PIN,/* 84 spare pin */
+ Native_M1, /* 85 SDMMC3_1P8_EN */
+ GPIO_END
+};
+
+
+/* South West Community */
+static const struct soc_gpio_map gpsw_gpio_map[] = {
+ GPIO_NC, /* 00 FST_SPI_D2 */
+ Native_M1, /* 01 FST_SPI_D0 */
+ Native_M1, /* 02 FST_SPI_CLK */
+ GPIO_NC, /* 03 FST_SPI_D3 */
+ GPIO_NC, /* GPO FST_SPI_CS1_B */
+ Native_M1, /* 05 FST_SPI_D1 */
+ Native_M1, /* 06 FST_SPI_CS0_B */
+ GPIO_OUT_HIGH, /* 07 FST_SPI_CS2_B */
+ GPIO_NC, /* 15 UART1_RTS_B */
+ Native_M2, /* 16 UART1_RXD */
+ GPIO_NC, /* 17 UART2_RXD */
+ GPIO_NC, /* 18 UART1_CTS_B */
+ GPIO_NC, /* 19 UART2_RTS_B */
+ Native_M2, /* 20 UART1_TXD */
+ GPIO_NC, /* 21 UART2_TXD */
+ GPIO_NC, /* 22 UART2_CTS_B */
+ GPIO_NC, /* 30 MF_HDA_CLK */
+ GPIO_NC, /* 31 GPIO_SW31/MF_HDA_RSTB */
+ GPIO_NC, /* 32 GPIO_SW32 /MF_HDA_SDI0 */
+ GPIO_NC, /* 33 MF_HDA_SDO */
+ GPI(trig_edge_both, L3, P_1K_H, non_maskable, en_edge_detect, NA, NA),
+ /* 34 MF_HDA_DOCKRSTB */
+ GPIO_NC, /* 35 MF_HDA_SYNC */
+ GPIO_NC, /* 36 GPIO_SW36 MF_HDA_SDI1 */
+ GPI(trig_edge_both, L2, P_1K_H, non_maskable, en_edge_detect, NA, NA),
+ /* 37 MF_HDA_DOCKENB */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 45 I2C5_SDA */
+ GPIO_NC, /* 46 I2C4_SDA */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 47 I2C6_SDA */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 48 I2C5_SCL */
+ GPIO_NC, /* 49 I2C_NFC_SDA */
+ GPIO_NC, /* 50 I2C4_SCL */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 51 I2C6_SCL */
+ GPIO_NC, /* 52 I2C_NFC_SCL */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 60 I2C1_SDA */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 61 I2C0_SDA */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 62 I2C2_SDA */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 63 I2C1_SCL */
+ GPIO_INPUT_NO_PULL, /* 64 I2C3_SDA RAMID3*/
+ NATIVE_PU1K_CSEN_INVTX(1), /* 65 I2C0_SCL */
+ NATIVE_PU1K_CSEN_INVTX(1), /* 66 I2C2_SCL */
+ GPIO_INPUT_NO_PULL,/* 67 I2C3_SCL,RAMID1 */
+ GPIO_OUT_HIGH, /* 75 SATA_GP0 */
+ GPI(trig_edge_low, L0, P_1K_H, non_maskable, NA, NA, NA),
+ /* 76 GPI SATA_GP1 */
+ Native_M1, /* 77 SATA_LEDN */
+ GPIO_NC, /* 80 SATA_GP3 */
+ Native_M1, /* 81 NFC_DEV_WAKE , MF_SMB_CLK */
+ GPIO_INPUT_NO_PULL, /* 80 SATA_GP3,RAMID0 */
+ Native_M1, /* 81 NFC_DEV_WAKE , MF_SMB_CLK */
+ Native_M1, /* 82 NFC_FW_DOWNLOAD, MF_SMB_DATA */
+ /* Per DE request, change PCIE_CLKREQ0123B to GPIO_INPUT */
+ Native_M1, /* 90 PCIE_CLKREQ0B */
+ GPIO_INPUT_PU_20K, /* 91 GPI PCIE_CLKREQ1B/LTE_WAKE# */
+ Native_M1, /* 92 GP_SSP_2_CLK */
+ GPIO_INPUT_PU_20K, /* 93 PCIE_CLKREQ2B/PCIE_CLKREQ_WLAN# */
+ Native_M1, /* 94 GP_SSP_2_RXD */
+ GPI(trig_edge_both, L1, P_5K_H, non_maskable, en_edge_detect, NA, NA),
+ /* 95 PCIE_CLKREQ3B/AUDIO_CODEC_IRQ */
+ Native_M1, /* 96 GP_SSP_2_FS */
+ NATIVE_FUNC(1, 0, inv_tx_enable), /* 97 GP_SSP_2f_TXD */
+ GPIO_END
+};
+
+
+/* North Community */
+static const struct soc_gpio_map gpn_gpio_map[] = {
+ Native_M5, /* 00 GPIO_DFX0 */
+ Native_M5, /* 01 GPIO_DFX3 */
+ Native_M1, /* 02 GPIO_DFX7 */
+ Native_M5, /* 03 GPIO_DFX1 */
+ Native_M1, /* 04 GPIO_DFX5 */
+ Native_M1, /* 05 GPIO_DFX4 */
+ GPI(trig_edge_low, L5, NA, non_maskable, en_rx_data, NA, NA),
+ /* 06 GPIO_DFX8 */
+ Native_M5, /* 07 GPIO_DFX2 */
+ Native_M8, /* 08 GPIO_DFX6 */
+ GPI(trig_edge_low, L8, NA, non_maskable, en_edge_rx_data ,
+ UNMASK_WAKE, SCI), /* 15 GPIO_SUS0 */
+ GPO_FUNC(NA, NA), /* 16 SEC_GPIO_SUS10 */
+ GPI(trig_edge_low, L0, P_1K_H, non_maskable, NA, NA, NA),
+ /* 17 GPIO_SUS3 */
+ GPI(trig_edge_low, L1, P_1K_H, non_maskable, NA, UNMASK_WAKE, NA),
+ /* 18 GPIO_SUS7 */
+ GPO_FUNC(0, 0), /* 19 GPIO_SUS1 */
+ GPIO_NC, /* 20 GPIO_SUS5 */
+ GPI(trig_edge_high, L2, NA, non_maskable, en_edge_rx_data, NA , NA),
+ /* 21 SEC_GPIO_SUS11 */
+ GPIO_NC, /* 22 GPIO_SUS4 */
+ GPIO_NC,
+ /* 23 SEC_GPIO_SUS8 */
+ Native_M6, /* 24 GPIO_SUS2 */
+ GPIO_SCI(L6),/* 25 GPIO_SUS6 */
+ Native_M1, /* 26 CX_PREQ_B */
+ GPIO_NC, /* 27 SEC_GPIO_SUS9 */
+ Native_M1, /* 30 TRST_B */
+ Native_M1, /* 31 TCK */
+ GPIO_SKIP, /* 32 PROCHOT_B */
+ GPIO_SKIP, /* 33 SVID0_DATA */
+ Native_M1, /* 34 TMS */
+ GPIO_NC, /* 35 CX_PRDY_B_2 */
+ GPIO_NC, /* 36 TDO_2 */
+ Native_M1, /* 37 CX_PRDY_B */
+ GPIO_SKIP, /* 38 SVID0_ALERT_B */
+ Native_M1, /* 39 TDO */
+ GPIO_SKIP, /* 40 SVID0_CLK */
+ Native_M1, /* 41 TDI */
+ Native_M2, /* 45 GP_CAMERASB05 */
+ Native_M2, /* 46 GP_CAMERASB02 */
+ Native_M2, /* 47 GP_CAMERASB08 */
+ Native_M2, /* 48 GP_CAMERASB00 */
+ Native_M2, /* 49 GP_CAMERASBO6 */
+ GPIO_NC, /* 50 GP_CAMERASB10 */
+ Native_M2, /* 51 GP_CAMERASB03 */
+ GPIO_NC, /* 52 GP_CAMERASB09 */
+ Native_M2, /* 53 GP_CAMERASB01 */
+ Native_M2, /* 54 GP_CAMERASB07 */
+ GPIO_NC, /* 55 GP_CAMERASB11 */
+ Native_M2, /* 56 GP_CAMERASB04 */
+ GPIO_NC, /* 60 PANEL0_BKLTEN */
+ Native_M1, /* 61 HV_DDI0_HPD */
+ NATIVE_PU1K_M1, /* 62 HV_DDI2_DDC_SDA */
+ Native_M1, /* 63 PANEL1_BKLTCTL */
+ NATIVE_TX_RX_EN, /* 64 HV_DDI1_HPD */
+ GPIO_NC, /* 65 PANEL0_BKLTCTL */
+ GPIO_NC, /* 66 HV_DDI0_DDC_SDA */
+ NATIVE_PU1K_M1, /* 67 HV_DDI2_DDC_SCL */
+ NATIVE_TX_RX_EN, /* 68 HV_DDI2_HPD */
+ Native_M1, /* 69 PANEL1_VDDEN */
+ Native_M1, /* 70 PANEL1_BKLTEN */
+ GPIO_NC, /* 71 HV_DDI0_DDC_SCL */
+ GPIO_NC, /* 72 PANEL0_VDDEN */
+ GPIO_END
+};
+
+
+/* East Community */
+static const struct soc_gpio_map gpe_gpio_map[] = {
+ Native_M1, /* 00 PMU_SLP_S3_B */
+ GPIO_NC, /* 01 PMU_BATLOW_B */
+ Native_M1, /* 02 SUS_STAT_B */
+ Native_M1, /* 03 PMU_SLP_S0IX_B */
+ Native_M1, /* 04 PMU_AC_PRESENT */
+ Native_M1, /* 05 PMU_PLTRST_B */
+ Native_M1, /* 06 PMU_SUSCLK */
+ GPIO_NC, /* 07 PMU_SLP_LAN_B */
+ Native_M1, /* 08 PMU_PWRBTN_B */
+ Native_M1, /* 09 PMU_SLP_S4_B */
+ NATIVE_FUNC(M1, P_1K_H, NA), /* 10 PMU_WAKE_B */
+ GPIO_NC, /* 11 PMU_WAKE_LAN_B */
+ GPIO_NC, /* 15 MF_GPIO_3 */
+ GPIO_NC, /* 16 MF_GPIO_7 */
+ GPIO_NC, /* 17 MF_I2C1_SCL */
+ GPIO_NC, /* 18 MF_GPIO_1 */
+ GPIO_NC, /* 19 MF_GPIO_5 */
+ GPIO_NC, /* 20 MF_GPIO_9 */
+ GPIO_NC, /* 21 MF_GPIO_0 */
+ GPIO_NC, /* 22 MF_GPIO_4 */
+ GPIO_NC, /* 23 MF_GPIO_8 */
+ GPIO_NC, /* 24 MF_GPIO_2 */
+ GPIO_NC, /* 25 MF_GPIO_6 */
+ GPIO_NC, /* 26 MF_I2C1_SDA */
+ GPIO_END
+};
+
+
+static struct soc_gpio_config gpio_config = {
+ /* BSW */
+ .north = gpn_gpio_map,
+ .southeast = gpse_gpio_map,
+ .southwest = gpsw_gpio_map,
+ .east = gpe_gpio_map
+};
+
+struct soc_gpio_config *mainboard_get_gpios(void)
+{
+ return &gpio_config;
+}
diff --git a/src/mainboard/intel/strago/irqroute.c b/src/mainboard/intel/strago/irqroute.c
new file mode 100644
index 0000000..83207d9
--- /dev/null
+++ b/src/mainboard/intel/strago/irqroute.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 "irqroute.h"
+
+DEFINE_IRQ_ROUTES;
diff --git a/src/mainboard/intel/strago/irqroute.h b/src/mainboard/intel/strago/irqroute.h
new file mode 100644
index 0000000..5353d42
--- /dev/null
+++ b/src/mainboard/intel/strago/irqroute.h
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <soc/irq.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
+
+#define PCI_DEV_PIRQ_ROUTES \
+ PCI_DEV_PIRQ_ROUTE(GFX_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(SDIO_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(SD_DEV, C, D, E, F), \
+ PCI_DEV_PIRQ_ROUTE(SATA_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(XHCI_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(LPE_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(MMC_DEV, D, E, F, G), \
+ PCI_DEV_PIRQ_ROUTE(SIO1_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(TXE_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(HDA_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(PCIE_DEV, A, B, C, D), \
+ PCI_DEV_PIRQ_ROUTE(SIO2_DEV, B, C, D, E), \
+ PCI_DEV_PIRQ_ROUTE(PCU_DEV, A, B, C, D)
+
+#define PIRQ_PIC_ROUTES \
+ PIRQ_PIC(A, DISABLE), \
+ PIRQ_PIC(B, DISABLE), \
+ PIRQ_PIC(C, DISABLE), \
+ PIRQ_PIC(D, DISABLE), \
+ PIRQ_PIC(E, DISABLE), \
+ PIRQ_PIC(F, DISABLE), \
+ PIRQ_PIC(G, DISABLE), \
+ PIRQ_PIC(H, DISABLE)
+
+/* CORE bank DIRQs - up to 16 supported */
+#define TPAD_IRQ_OFFSET 0
+#define TOUCH_IRQ_OFFSET 1
+#define I8042_IRQ_OFFSET 2
+#define ALS_IRQ_OFFSET 3
+/* Corresponding SCORE GPIO pins */
+#define TPAD_IRQ_GPIO 55
+#define TOUCH_IRQ_GPIO 72
+#define I8042_IRQ_GPIO 101
+#define ALS_IRQ_GPIO 70
+
+/* SUS bank DIRQs - up to 16 supported */
+#define CODEC_IRQ_OFFSET 0
+/* Corresponding SUS GPIO pins */
+#define CODEC_IRQ_GPIO 9
diff --git a/src/mainboard/intel/strago/mainboard.c b/src/mainboard/intel/strago/mainboard.c
new file mode 100755
index 0000000..f155a04
--- /dev/null
+++ b/src/mainboard/intel/strago/mainboard.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ * 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 <bootstate.h>
+#include <device/device.h>
+#include <soc/gpio.h>
+
+struct chip_operations mainboard_ops = {
+};
diff --git a/src/mainboard/intel/strago/onboard.h b/src/mainboard/intel/strago/onboard.h
new file mode 100755
index 0000000..7ae593a
--- /dev/null
+++ b/src/mainboard/intel/strago/onboard.h
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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
+ */
+
+#ifndef ONBOARD_H
+#define ONBOARD_H
+
+#include "irqroute.h"
+
+/*
+ * Calculation of gpio based irq.
+ * Gpio banks ordering : GPSW, GPNC, GPEC, GPSE
+ * Max direct irq (MAX_DIRECT_IRQ) is 114.
+ * Size of gpio banks are
+ * GPSW_SIZE = 98
+ * GPNC_SIZE = 73
+ * GPEC_SIZE = 27
+ * GPSE_SIZE = 86
+ */
+
+/*
+ * gpio based irq for kbd, 17th index in North Bank
+ * MAX_DIRECT_IRQ + GPSW_SIZE + 18
+ */
+#define STRAGO_KBD_IRQ 230
+
+/*
+ * gpio based irq for trackpad, 18th index in North Bank
+ * MAX_DIRECT_IRQ + GPSW_SIZE + 19
+ */
+#define STRAGO_TRACKPAD_IRQ 231
+
+/*
+ * gpio based irq for touchscreen, 76th index in SW Bank
+ * MAX_DIRECT_IRQ + 77
+ */
+#define STRAGO_TOUCH_IRQ 191
+
+/* Gpio index or offset number in SE bank */
+#define JACK_DETECT_GPIO_INDEX 77
+
+#define BOARD_TRACKPAD_NAME "trackpad"
+#define BOARD_TRACKPAD_IRQ STRAGO_TRACKPAD_IRQ
+#define BOARD_TRACKPAD_WAKE_GPIO ACPI_ENABLE_WAKE_SUS_GPIO(1)
+#define BOARD_TRACKPAD_I2C_BUS 5
+#define BOARD_TRACKPAD_I2C_ADDR 0x15
+
+#define BOARD_TOUCHSCREEN_NAME "touchscreen"
+#define BOARD_TOUCHSCREEN_IRQ STRAGO_TOUCH_IRQ
+#define BOARD_TOUCHSCREEN_WAKE_GPIO ACPI_ENABLE_WAKE_SUS_GPIO(2)
+#define BOARD_TOUCHSCREEN_I2C_BUS 0
+#define BOARD_TOUCHSCREEN_I2C_ADDR 0x4a /* TODO(shawnn): Check this */
+
+#define BOARD_I8042_IRQ STRAGO_KBD_IRQ
+#define BOARD_ALS_IRQ GPIO_S0_DED_IRQ(ALS_IRQ_OFFSET)
+
+/*
+ * gpio based irq for codec irq, 77th index in GPSE Bank
+ * MAX_DIRECT_IRQ+GPSW_SIZE+GPNC_SIZE +GPEC_SIZE + 78
+ */
+#define BOARD_CODEC_IRQ 390
+
+/* SD CARD gpio */
+#define SDCARD_CD 81
+
+#define AUDIO_CODEC_HID "193C9890"
+#define AUDIO_CODEC_CID "193C9890"
+#define AUDIO_CODEC_DDN "Maxim 98090 Codec "
+#define AUDIO_CODEC_I2C_ADDR 0x10
+
+#define AUDIO_JACK_IRQ 149
+#define TI_SWITCH_HID "104C227E"
+#define TI_SWITCH_CID "104C227E"
+#define TI_SWITCH_DDN "TI SWITCH "
+#define TI_SWITCH_I2C_ADDR 0x3B
+#endif
diff --git a/src/mainboard/intel/strago/romstage.c b/src/mainboard/intel/strago/romstage.c
new file mode 100755
index 0000000..e2cf12d
--- /dev/null
+++ b/src/mainboard/intel/strago/romstage.c
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <lib.h>
+#include <soc/gpio.h>
+#include <soc/pci_devs.h>
+#include <soc/romstage.h>
+#include <string.h>
+
+/* All FSP specific code goes in this block */
+void mainboard_romstage_entry(struct romstage_params *rp)
+{
+ struct pei_data *ps = rp->pei_data;
+
+ mainboard_fill_spd_data(ps);
+
+ /* Set device state/enable information */
+ ps->sdcard_mode = PCH_ACPI_MODE;
+ ps->emmc_mode = PCH_ACPI_MODE;
+ ps->enable_azalia = 1;
+
+ /* Call back into chipset code with platform values updated. */
+ romstage_common(rp);
+}
diff --git a/src/mainboard/intel/strago/smihandler.c b/src/mainboard/intel/strago/smihandler.c
new file mode 100755
index 0000000..ca3dd0b
--- /dev/null
+++ b/src/mainboard/intel/strago/smihandler.c
@@ -0,0 +1,168 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * 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 <arch/io.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include "ec.h"
+
+#include <ec/google/chromeec/ec.h>
+#include <elog.h>
+
+#include <soc/nvs.h>
+#include <soc/pm.h>
+
+/* The wake gpio is SUS_GPIO[0]. */
+#define WAKE_GPIO_EN SUS_GPIO_EN0
+
+int mainboard_io_trap_handler(int smif)
+{
+ switch (smif) {
+ case 0x99:
+ printk(BIOS_DEBUG, "Sample\n");
+ smm_get_gnvs()->smif = 0;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * On success, the IO Trap Handler returns 0
+ * On failure, the IO Trap Handler returns a value != 0
+ *
+ * For now, we force the return value to 0 and log all traps to
+ * see what's going on.
+ */
+ //gnvs->smif = 0;
+ return 1;
+}
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+static uint8_t mainboard_smi_ec(void)
+{
+ uint8_t cmd = google_chromeec_get_event();
+ uint16_t pmbase = get_pmbase();
+ uint32_t pm1_cnt;
+
+#if IS_ENABLED(CONFIG_ELOG_GSMI)
+ /* Log this event */
+ if (cmd)
+ elog_add_event_byte(ELOG_TYPE_EC_EVENT, cmd);
+#endif
+
+ switch (cmd) {
+ case EC_HOST_EVENT_LID_CLOSED:
+ printk(BIOS_DEBUG, "LID CLOSED, SHUTDOWN\n");
+
+ /* Go to S5 */
+ pm1_cnt = inl(pmbase + PM1_CNT);
+ pm1_cnt |= SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT);
+ outl(pm1_cnt, pmbase + PM1_CNT);
+ break;
+ }
+
+ return cmd;
+}
+#endif
+
+/*
+ * The entire 32-bit ALT_GPIO_SMI register is passed as a parameter. Note, that
+ * this includes the enable bits in the lower 16 bits.
+ */
+void mainboard_smi_gpi(uint32_t alt_gpio_smi)
+{
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ if (alt_gpio_smi & (1 << EC_SMI_GPI)) {
+ /* Process all pending events */
+ while (mainboard_smi_ec() != 0)
+ ;
+ }
+#endif
+}
+
+void mainboard_smi_sleep(uint8_t slp_typ)
+{
+ /* Disable USB charging if required */
+ switch (slp_typ) {
+ case 3:
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ if (smm_get_gnvs()->s3u0 == 0)
+ google_chromeec_set_usb_charge_mode(
+ 0, USB_CHARGE_MODE_DISABLED);
+ if (smm_get_gnvs()->s3u1 == 0)
+ google_chromeec_set_usb_charge_mode(
+ 1, USB_CHARGE_MODE_DISABLED);
+
+ /* Enable wake events */
+ google_chromeec_set_wake_mask(MAINBOARD_EC_S3_WAKE_EVENTS);
+#endif
+ /* Enable wake pin in GPE block. */
+ enable_gpe(WAKE_GPIO_EN);
+ break;
+ case 5:
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ if (smm_get_gnvs()->s5u0 == 0)
+ google_chromeec_set_usb_charge_mode(
+ 0, USB_CHARGE_MODE_DISABLED);
+ if (smm_get_gnvs()->s5u1 == 0)
+ google_chromeec_set_usb_charge_mode(
+ 1, USB_CHARGE_MODE_DISABLED);
+
+ /* Enable wake events */
+ google_chromeec_set_wake_mask(MAINBOARD_EC_S5_WAKE_EVENTS);
+#endif
+ break;
+ }
+
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ /* Disable SCI and SMI events */
+ google_chromeec_set_smi_mask(0);
+ google_chromeec_set_sci_mask(0);
+
+ /* Clear pending events that may trigger immediate wake */
+ while (google_chromeec_get_event() != 0)
+ ;
+#endif
+}
+
+int mainboard_smi_apmc(uint8_t apmc)
+{
+ switch (apmc) {
+ case APM_CNT_ACPI_ENABLE:
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ google_chromeec_set_smi_mask(0);
+ /* Clear all pending events */
+ while (google_chromeec_get_event() != 0)
+ ;
+ google_chromeec_set_sci_mask(MAINBOARD_EC_SCI_EVENTS);
+#endif
+ break;
+ case APM_CNT_ACPI_DISABLE:
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ google_chromeec_set_sci_mask(0);
+ /* Clear all pending events */
+ while (google_chromeec_get_event() != 0)
+ ;
+ google_chromeec_set_smi_mask(MAINBOARD_EC_SMI_EVENTS);
+#endif
+ break;
+ }
+ return 0;
+}
diff --git a/src/mainboard/intel/strago/spd/Makefile.inc b/src/mainboard/intel/strago/spd/Makefile.inc
new file mode 100755
index 0000000..a8c3888
--- /dev/null
+++ b/src/mainboard/intel/strago/spd/Makefile.inc
@@ -0,0 +1,41 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google Inc.
+## 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
+##
+
+romstage-y += spd.c
+SPD_BIN = $(obj)/spd.bin
+
+SPD_SOURCES = samsung_2GiB_dimm_K4B4G1646Q-HYK0
+SPD_SOURCES += hynix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR
+SPD_SOURCES += samsung_2GiB_dimm_K4B4G1646Q-HYK0
+SPD_SOURCES += hynix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR
+
+SPD_DEPS := $(foreach f, $(SPD_SOURCES), src/mainboard/$(MAINBOARDDIR)/spd/$(f).spd.hex)
+
+# Include spd rom data
+$(SPD_BIN): $(SPD_DEPS)
+ for f in $+; \
+ do for c in $$(cat $$f | grep -v ^#); \
+ do echo -e -n "\\x$$c"; \
+ done; \
+ done > $@
+
+cbfs-files-y += spd.bin
+spd.bin-file := $(SPD_BIN)
+spd.bin-type := 0xab
diff --git a/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex b/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex
new file mode 100755
index 0000000..ff4fd29
--- /dev/null
+++ b/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_H5TC4G63AFR-PBA.spd.hex
@@ -0,0 +1,32 @@
+92 12 0b 03 04 19 02 02
+03 52 01 08 0a 00 fe 00
+69 78 69 3c 69 11 18 81
+20 08 3c 3c 01 40 83 01
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 0f 11 62 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 80 ad 01
+00 00 00 00 00 00 ff ab
+48 4d 54 34 32 35 53 36
+41 46 52 36 41 2d 50 42
+20 20 4e 30 80 ad 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff
diff --git a/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR.spd.hex b/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR.spd.hex
new file mode 100755
index 0000000..fdd1a43
--- /dev/null
+++ b/src/mainboard/intel/strago/spd/hynix_2GiB_dimm_HMT425S6CFR6A_H5TC4G63CFR.spd.hex
@@ -0,0 +1,32 @@
+92 13 0B 03 04 19 02 02
+03 52 01 08 0A 00 FE 00
+69 78 69 3C 69 11 18 81
+20 08 3C 3C 01 40 83 01
+00 00 00 00 00 00 00 00
+00 88 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 0F 11 62 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 80 AD 01
+00 00 00 00 00 00 C9 C0
+48 4D 54 34 32 35 53 36
+43 46 52 36 41 2D 50 42
+20 20 4E 30 80 AD 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF
diff --git a/src/mainboard/intel/strago/spd/samsung_2GiB_dimm_K4B4G1646Q-HYK0.spd.hex b/src/mainboard/intel/strago/spd/samsung_2GiB_dimm_K4B4G1646Q-HYK0.spd.hex
new file mode 100755
index 0000000..e0b0ac5
--- /dev/null
+++ b/src/mainboard/intel/strago/spd/samsung_2GiB_dimm_K4B4G1646Q-HYK0.spd.hex
@@ -0,0 +1,32 @@
+92 12 0B 03 04 19 02 02
+03 11 01 08 0A 00 FE 00
+69 78 69 3C 69 11 18 81
+20 08 3C 3C 01 40 83 05
+00 00 00 00 00 00 00 00
+88 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 0F 01 02 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 80 CE 01
+00 00 00 00 00 00 6C F9
+4D 34 37 31 42 35 36 37
+34 51 48 30 2D 59 4B 30
+20 20 00 00 80 CE 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00
diff --git a/src/mainboard/intel/strago/spd/spd.c b/src/mainboard/intel/strago/spd/spd.c
new file mode 100755
index 0000000..01f4dd7
--- /dev/null
+++ b/src/mainboard/intel/strago/spd/spd.c
@@ -0,0 +1,115 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <lib.h>
+#include <soc/gpio.h>
+#include <soc/romstage.h>
+#include <string.h>
+
+#define SPD_SIZE 256
+#define SATA_GP3_PAD_CFG0 0x5828
+#define I2C3_SCL_PAD_CFG0 0x5438
+#define MF_PLT_CLK1_PAD_CFG0 0x4410
+#define I2C3_SDA_PAD_CFG0 0x5420
+
+/*
+ * 0b0000 - 4GiB total - 2 x 2GiB Samsung K4B4G1646Q-HYK0 1600MHz
+ * 0b0001 - 4GiB total - 2 x 2GiB Hynix H5TC4G63CFR-PBA 1600MHz
+ * 0b0010- 2GiB total - 1 x 2GiB Samsung K4B4G1646Q-HYK0 1600MHz
+ * 0b0011 - 2GiB total - 1 x 2GiB Hynix H5TC4G63CFR-PBA 1600MHz
+ */
+static const uint32_t dual_channel_config = (1 << 0);
+
+static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual)
+{
+ int ram_id = 0;
+ ram_id |= get_gpio(COMMUNITY_GPSOUTHWEST_BASE, SATA_GP3_PAD_CFG0) << 0;
+ ram_id |= get_gpio(COMMUNITY_GPSOUTHWEST_BASE, I2C3_SCL_PAD_CFG0) << 1;
+ ram_id |= get_gpio(COMMUNITY_GPSOUTHEAST_BASE, MF_PLT_CLK1_PAD_CFG0)
+ << 2;
+ ram_id |= get_gpio(COMMUNITY_GPSOUTHWEST_BASE, I2C3_SDA_PAD_CFG0) << 3;
+
+ /*
+ * There are only 2 SPDs supported on Cyan Board:
+ * Samsung 4G:0000 & Hynix 2G:0011
+ */
+
+ /*
+ * RAMID0 on the first boot does not read the correct value,so checking
+ * bit 1 is enough as WA
+ */
+ if (ram_id > 0)
+ ram_id = 3;
+ printk(BIOS_DEBUG, "ram_id=%d, total_spds: %d\n", ram_id, total_spds);
+
+ if (ram_id >= total_spds)
+ return NULL;
+
+ /* Single channel configs */
+ if (dual_channel_config & (1 << ram_id))
+ *dual = 1;
+
+ return &spd_file_content[SPD_SIZE * ram_id];
+}
+
+/* Copy SPD data for on-board memory */
+void mainboard_fill_spd_data(struct pei_data *ps)
+{
+ struct cbfs_file *spd_file;
+ void *spd_content;
+ int dual_channel = 0;
+
+ /* Find the SPD data in CBFS. */
+ spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
+ if (!spd_file)
+ die("SPD data not found.");
+
+ /*
+ * Both channels are always present in SPD data. Always use matched
+ * DIMMs so use the same SPD data for each DIMM.
+ */
+ spd_content = get_spd_pointer(CBFS_SUBHEADER(spd_file),
+ ntohl(spd_file->len) / SPD_SIZE,
+ &dual_channel);
+ if (IS_ENABLED(CONFIG_DISPLAY_SPD_DATA) && spd_content != NULL) {
+ printk(BIOS_DEBUG, "SPD Data:\n");
+ hexdump(spd_content, SPD_SIZE);
+ printk(BIOS_DEBUG, "\n");
+ }
+
+ /*
+ * Set SPD and memory configuration:
+ * Memory type: 0=DimmInstalled,
+ * 1=SolderDownMemory,
+ * 2=DimmDisabled
+ */
+ if (spd_content != NULL) {
+ ps->spd_data_ch0 = spd_content;
+ ps->spd_ch0_config = 1;
+ if (dual_channel) {
+ ps->spd_data_ch1 = spd_content;
+ ps->spd_ch1_config = 1;
+ } else {
+ ps->spd_ch1_config = 2;
+ }
+ }
+}
diff --git a/src/mainboard/intel/strago/w25q64.c b/src/mainboard/intel/strago/w25q64.c
new file mode 100755
index 0000000..4399d88
--- /dev/null
+++ b/src/mainboard/intel/strago/w25q64.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * 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 <soc/spi.h>
+#include <string.h>
+
+/*
+ * SPI lockdown configuration W25Q64FW.
+ */
+#define SPI_OPMENU_0 0x01 /* WRSR: Write Status Register */
+#define SPI_OPTYPE_0 0x01 /* Write, no address */
+
+#define SPI_OPMENU_1 0x02 /* BYPR: Byte Program */
+#define SPI_OPTYPE_1 0x03 /* Write, address required */
+
+#define SPI_OPMENU_2 0x03 /* READ: Read Data */
+#define SPI_OPTYPE_2 0x02 /* Read, address required */
+
+#define SPI_OPMENU_3 0x05 /* RDSR: Read Status Register */
+#define SPI_OPTYPE_3 0x00 /* Read, no address */
+
+#define SPI_OPMENU_4 0x20 /* SE20: Sector Erase 0x20 */
+#define SPI_OPTYPE_4 0x03 /* Write, address required */
+
+#define SPI_OPMENU_5 0x9f /* RDID: Read ID */
+#define SPI_OPTYPE_5 0x00 /* Read, no address */
+
+#define SPI_OPMENU_6 0xd8 /* BED8: Block Erase 0xd8 */
+#define SPI_OPTYPE_6 0x03 /* Write, address required */
+
+#define SPI_OPMENU_7 0x0b /* FAST: Fast Read */
+#define SPI_OPTYPE_7 0x02 /* Read, address required */
+
+#define SPI_OPPREFIX ((0x50 << 8) | 0x06) /* EWSR and WREN */
+#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \
+ (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \
+ (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \
+ (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0 << 0))
+#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \
+ (SPI_OPMENU_5 << 8) | (SPI_OPMENU_4 << 0))
+#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
+ (SPI_OPMENU_1 << 8) | (SPI_OPMENU_0 << 0))
+#define SPI_VSCC (WG_64_BYTE | EO(0x20) | BES_4_KB)
+
+static const struct spi_config spi_config = {
+ .preop = SPI_OPPREFIX,
+ .optype = SPI_OPTYPE,
+ .opmenu = { SPI_OPMENU_LOWER, SPI_OPMENU_UPPER },
+ .lvscc = SPI_VSCC,
+ .uvscc = SPI_VSCC,
+};
+
+int mainboard_get_spi_config(struct spi_config *cfg)
+{
+ memcpy(cfg, &spi_config, sizeof(*cfg));
+
+ return 0;
+}
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/10050
-gerrit
commit dc58fdf15cee09794cd2ee4195c2c146e562663e
Author: Lee Leahy <leroy.p.leahy(a)intel.com>
Date: Mon Apr 20 15:24:54 2015 -0700
DO NOT MERGE: Intel Common SOC: Add romstage support
Provide a common romstage implementation for the Intel SOCs.
BRANCH=none
BUG=None
TEST=Build for Braswell
Change-Id: I80f5f8f0f36e9023117b07d4af5c806fff8157b6
Signed-off-by: Lee Leahy <leroy.p.leahy(a)intel.com>
---
src/soc/intel/common/Kconfig | 39 ++++
src/soc/intel/common/Makefile.inc | 12 +-
src/soc/intel/common/fsp_ramstage.c | 153 ++++++++++++++++
src/soc/intel/common/gma.h | 176 ++++++++++++++++++
src/soc/intel/common/junk.c | 21 +++
src/soc/intel/common/memmap.h | 33 ++++
src/soc/intel/common/raminit.c | 275 ++++++++++++++++++++++++++++
src/soc/intel/common/ramstage.h | 36 ++++
src/soc/intel/common/romstage.c | 356 ++++++++++++++++++++++++++++++++++++
src/soc/intel/common/romstage.h | 99 ++++++++++
src/soc/intel/common/spi_loading.c | 152 +++++++++++++++
src/soc/intel/common/stack.c | 173 ++++++++++++++++++
src/soc/intel/common/stack.h | 35 ++++
13 files changed, 1558 insertions(+), 2 deletions(-)
diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig
index 8b5cef3..7e1cd1a 100644
--- a/src/soc/intel/common/Kconfig
+++ b/src/soc/intel/common/Kconfig
@@ -3,6 +3,8 @@ config SOC_INTEL_COMMON
help
common code for Intel SOCs
+if SOC_INTEL_COMMON
+
if HAVE_MRC
config CACHE_MRC_SETTINGS
@@ -27,6 +29,43 @@ endif # CACHE_MRC_SETTINGS
endif # HAVE_MRC
+config CHIPSET_RESERVED_MEM_BYTES
+ hex "Size in bytes of chipset reserved memory area"
+ default 0
+ help
+ If insufficient documentation is available to determine the size of
+ the chipset reserved memory area by walking the chipset registers,
+ the CHIPSET_RESERVED_MEM_BYTES may be used as a workaround to account
+ for the missing pieces of memory. The value specified in bytes is:
+
+ value = TSEG base - top of low usable memory - (any sizes determined
+ by reading chipset registers)
+
+config SOC_INTEL_COMMON_STACK
+ bool
+ default n
+
+config SOC_INTEL_COMMON_RAM_INIT
+ bool "FSP: Use the common raminit.c module"
+ default n
+ depends on PLATFORM_USES_FSP1_1
+
config SOC_INTEL_COMMON_RESET
bool
default n
+
+config SOC_INTEL_COMMON_ROMSTAGE
+ bool
+ default n
+
+config SOC_INTEL_COMMON_SPI_LOADING
+ bool "Use the common spi_loading.c module"
+ default n
+ depends on ALT_CBFS_LOAD_PAYLOAD
+
+config ROMSTAGE_RAM_STACK_SIZE
+ hex "Size of the romstage RAM stack in bytes"
+ default 0x5000
+
+endif # SOC_INTEL_COMMON
+
diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc
index 6d40aa7..9ef8d26 100644
--- a/src/soc/intel/common/Makefile.inc
+++ b/src/soc/intel/common/Makefile.inc
@@ -1,10 +1,18 @@
ifeq ($(CONFIG_SOC_INTEL_COMMON),y)
+romstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_RAM_INIT) += raminit.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_ROMSTAGE) += romstage.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_STACK) += stack.c
+romstage-y += junk.c
+
+ramstage-$(CONFIG_PLATFORM_USES_FSP1_1) += fsp_ramstage.c
ramstage-y += hda_verb.c
ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += nvm.c
ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
-romstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
-romstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_SPI_LOADING) += spi_loading.c
+ramstage-y += junk.c
endif
diff --git a/src/soc/intel/common/fsp_ramstage.c b/src/soc/intel/common/fsp_ramstage.c
new file mode 100644
index 0000000..301d7a1
--- /dev/null
+++ b/src/soc/intel/common/fsp_ramstage.c
@@ -0,0 +1,153 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 <cbmem.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <fsp_util.h>
+#include <romstage_handoff.h>
+#include <soc/intel/common/ramstage.h>
+#include <timestamp.h>
+
+/* SOC initialization after FSP silicon init */
+__attribute__((weak)) void soc_after_silicon_init(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+__attribute__((weak)) void soc_save_support_code(void *start, size_t size,
+ void *entry)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+__attribute__((weak)) void *soc_restore_support_code(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return NULL;
+}
+
+static void fsp_run_silicon_init(void)
+{
+ FSP_INFO_HEADER *fsp_info_header;
+ FSP_SILICON_INIT fsp_silicon_init;
+ EFI_STATUS status;
+
+ /* Find the FSP image */
+ fsp_info_header = fsp_get_fih();
+ if (fsp_info_header == NULL) {
+ printk(BIOS_ERR, "FSP_INFO_HEADER not set!\n");
+ return;
+ }
+
+ /* Perform silicon initialization after RAM is configured */
+ printk(BIOS_DEBUG, "Calling FspSiliconInit\n");
+ fsp_silicon_init = (FSP_SILICON_INIT)(fsp_info_header->ImageBase
+ + fsp_info_header->FspSiliconInitEntryOffset);
+ timestamp_add_now(TS_FSP_SILICON_INIT_START);
+ status = fsp_silicon_init(NULL);
+ timestamp_add_now(TS_FSP_SILICON_INIT_END);
+ printk(BIOS_DEBUG, "FspSiliconInit returned 0x%08x\n", status);
+
+#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
+ /* Verify the HOBs */
+ const EFI_GUID graphics_info_guid = EFI_PEI_GRAPHICS_INFO_HOB_GUID;
+ void *hob_list_ptr = get_hob_list();
+ int missing_hob = 0;
+
+ if (hob_list_ptr == NULL)
+ die("ERROR - HOB pointer is NULL!\n");
+ print_hob_type_structure(0, hob_list_ptr);
+
+ /*
+ * Verify that FSP is generating the required HOBs:
+ * 7.1: FSP_BOOTLOADER_TEMP_MEMORY_HOB only produced for FSP 1.0
+ * 7.2: FSP_RESERVED_MEMORY_RESOURCE_HOB verified by raminit
+ * 7.3: FSP_NON_VOLATILE_STORAGE_HOB verified by raminit
+ * 7.4: FSP_BOOTLOADER_TOLUM_HOB verified by raminit
+ */
+ if (NULL == get_next_guid_hob(&graphics_info_guid, hob_list_ptr)) {
+ printk(BIOS_ERR, "7.5: EFI_PEI_GRAPHICS_INFO_HOB missing!\n");
+ missing_hob = 1;
+ }
+ if (missing_hob)
+ die("ERROR - Missing one or more required FSP HOBs!\n");
+#endif
+
+ soc_after_silicon_init();
+}
+
+static void fsp_cache_save(void)
+{
+ const struct cbmem_entry *fsp_entry;
+ FSP_INFO_HEADER *fih;
+
+ fsp_entry = cbmem_entry_find(CBMEM_ID_REFCODE);
+
+ if (fsp_entry == NULL) {
+ printk(BIOS_ERR, "ERROR: FSP not found in CBMEM.\n");
+ return;
+ }
+
+ fih = fsp_get_fih();
+
+ if (fih == NULL) {
+ printk(BIOS_ERR, "ERROR: No FIH found.\n");
+ return;
+ }
+
+ soc_save_support_code(cbmem_entry_start(fsp_entry),
+ cbmem_entry_size(fsp_entry), fih);
+}
+
+static int fsp_find_and_relocate(void)
+{
+ struct cbfs_file *file;
+ void *fih;
+
+ file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "fsp.bin");
+
+ if (file == NULL) {
+ printk(BIOS_ERR, "Couldn't find fsp.bin in CBFS.\n");
+ return -1;
+ }
+
+ fih = fsp_relocate(CBFS_SUBHEADER(file), ntohl(file->len));
+
+ fsp_update_fih(fih);
+
+ return 0;
+}
+
+void intel_silicon_init(void)
+{
+ struct romstage_handoff *handoff;
+
+ handoff = cbmem_find(CBMEM_ID_ROMSTAGE_INFO);
+
+ if (handoff != NULL && handoff->s3_resume)
+ fsp_update_fih(soc_restore_support_code());
+ else {
+ fsp_find_and_relocate();
+ fsp_cache_save();
+ }
+
+ fsp_run_silicon_init();
+}
diff --git a/src/soc/intel/common/gma.h b/src/soc/intel/common/gma.h
new file mode 100644
index 0000000..9666147
--- /dev/null
+++ b/src/soc/intel/common/gma.h
@@ -0,0 +1,176 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Chromium OS Authors
+ * 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
+ */
+
+#ifndef _GMA_H_
+#define _GMA_H_
+
+#include <types.h>
+
+/* mailbox 0: header */
+typedef struct {
+ u8 signature[16];
+ u32 size;
+ u32 version;
+ u8 sbios_version[32];
+ u8 vbios_version[16];
+ u8 driver_version[16];
+ u32 mailboxes;
+ u8 reserved[164];
+} __attribute__((packed)) opregion_header_t;
+
+#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
+#define IGD_OPREGION_VERSION 2
+
+#define IGD_MBOX1 (1 << 0)
+#define IGD_MBOX2 (1 << 1)
+#define IGD_MBOX3 (1 << 2)
+#define IGD_MBOX4 (1 << 3)
+#define IGD_MBOX5 (1 << 4)
+
+#define MAILBOXES_MOBILE (IGD_MBOX1 | IGD_MBOX2 | IGD_MBOX3 | \
+ IGD_MBOX4 | IGD_MBOX5)
+#define MAILBOXES_DESKTOP (IGD_MBOX2 | IGD_MBOX4)
+
+#define SBIOS_VERSION_SIZE 32
+
+/* mailbox 1: public acpi methods */
+typedef struct {
+ u32 drdy;
+ u32 csts;
+ u32 cevt;
+ u8 reserved1[20];
+ u32 didl[8];
+ u32 cpdl[8];
+ u32 cadl[8];
+ u32 nadl[8];
+ u32 aslp;
+ u32 tidx;
+ u32 chpd;
+ u32 clid;
+ u32 cdck;
+ u32 sxsw;
+ u32 evts;
+ u32 cnot;
+ u32 nrdy;
+ u8 reserved2[60];
+} __attribute__((packed)) opregion_mailbox1_t;
+
+/* mailbox 2: software sci interface */
+typedef struct {
+ u32 scic;
+ u32 parm;
+ u32 dslp;
+ u8 reserved[244];
+} __attribute__((packed)) opregion_mailbox2_t;
+
+/* mailbox 3: power conservation */
+typedef struct {
+ u32 ardy;
+ u32 aslc;
+ u32 tche;
+ u32 alsi;
+ u32 bclp;
+ u32 pfit;
+ u32 cblv;
+ u16 bclm[20];
+ u32 cpfm;
+ u32 epfm;
+ u8 plut[74];
+ u32 pfmb;
+ u32 ccdv;
+ u32 pcft;
+ u8 reserved[94];
+} __attribute__((packed)) opregion_mailbox3_t;
+
+#define IGD_BACKLIGHT_BRIGHTNESS 0xff
+#define IGD_INITIAL_BRIGHTNESS 0x64
+
+#define IGD_FIELD_VALID (1 << 31)
+#define IGD_WORD_FIELD_VALID (1 << 15)
+#define IGD_PFIT_STRETCH 6
+
+/* mailbox 4: vbt */
+typedef struct {
+ u8 gvd1[7168];
+} __attribute__((packed)) opregion_vbt_t;
+
+/* IGD OpRegion */
+typedef struct {
+ opregion_header_t header;
+ opregion_mailbox1_t mailbox1;
+ opregion_mailbox2_t mailbox2;
+ opregion_mailbox3_t mailbox3;
+ opregion_vbt_t vbt;
+} __attribute__((packed)) igd_opregion_t;
+
+/* Intel Video BIOS (Option ROM) */
+typedef struct {
+ u16 signature;
+ u8 size;
+ u8 reserved[21];
+ u16 pcir_offset;
+ u16 vbt_offset;
+} __attribute__((packed)) optionrom_header_t;
+
+#define OPROM_SIGNATURE 0xaa55
+
+typedef struct {
+ u32 signature;
+ u16 vendor;
+ u16 device;
+ u16 reserved1;
+ u16 length;
+ u8 revision;
+ u8 classcode[3];
+ u16 imagelength;
+ u16 coderevision;
+ u8 codetype;
+ u8 indicator;
+ u16 reserved2;
+} __attribute__((packed)) optionrom_pcir_t;
+
+typedef struct {
+ u8 hdr_signature[20];
+ u16 hdr_version;
+ u16 hdr_size;
+ u16 hdr_vbt_size;
+ u8 hdr_vbt_checksum;
+ u8 hdr_reserved;
+ u32 hdr_vbt_datablock;
+ u32 hdr_aim[4];
+ u8 datahdr_signature[16];
+ u16 datahdr_version;
+ u16 datahdr_size;
+ u16 datahdr_datablocksize;
+ u8 coreblock_id;
+ u16 coreblock_size;
+ u16 coreblock_biossize;
+ u8 coreblock_biostype;
+ u8 coreblock_releasestatus;
+ u8 coreblock_hwsupported;
+ u8 coreblock_integratedhw;
+ u8 coreblock_biosbuild[4];
+ u8 coreblock_biossignon[155];
+} __attribute__((packed)) optionrom_vbt_t;
+
+#define VBT_SIGNATURE 0x54425624
+
+#endif /* _GMA_H_ */
+
diff --git a/src/soc/intel/common/junk.c b/src/soc/intel/common/junk.c
new file mode 100644
index 0000000..e90c6e8
--- /dev/null
+++ b/src/soc/intel/common/junk.c
@@ -0,0 +1,21 @@
+#include <cbmem.h>
+#include <reg_script.h>
+#include <timestamp.h>
+
+int cbmem_initialize_id_size(u32 id, u64 size)
+{
+ return 0;
+}
+
+void cbmem_initialize_empty_id_size(u32 id, u64 size)
+{
+}
+
+void reg_script_run_on_dev(device_t dev, const struct reg_script *step)
+{
+}
+
+void timestamp_early_init(uint64_t base)
+{
+}
+
diff --git a/src/soc/intel/common/memmap.h b/src/soc/intel/common/memmap.h
new file mode 100644
index 0000000..840b51e
--- /dev/null
+++ b/src/soc/intel/common/memmap.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 _COMMON_MEMMAP_H_
+#define _COMMON_MEMMAP_H_
+
+#include <types.h>
+
+/*
+ * mmap_region_granluarity must to return a size which is a positive non-zero
+ * integer multiple of the SMM size when SMM is in use. When not using SMM,
+ * this value should be set to 8 MiB.
+ */
+size_t mmap_region_granluarity(void);
+void smm_region(void **start, size_t *size);
+
+#endif /* _COMMON_MEMMAP_H_ */
diff --git a/src/soc/intel/common/raminit.c b/src/soc/intel/common/raminit.c
new file mode 100644
index 0000000..4462329
--- /dev/null
+++ b/src/soc/intel/common/raminit.c
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014-2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 <cbmem.h>
+#include <console/console.h>
+#include <fsp_util.h>
+#include <lib.h> /* hexdump */
+#include <reset.h>
+#include <soc/intel/common/memmap.h>
+#include <soc/pei_data.h>
+#include <soc/romstage.h>
+#include <string.h>
+#include <timestamp.h>
+
+void raminit(struct romstage_params *params)
+{
+ const EFI_GUID bootldr_tolum_guid = FSP_BOOTLOADER_TOLUM_HOB_GUID;
+ EFI_HOB_RESOURCE_DESCRIPTOR *cbmem_root;
+ FSP_INFO_HEADER *fsp_header;
+ EFI_HOB_RESOURCE_DESCRIPTOR *fsp_memory;
+ FSP_MEMORY_INIT fsp_memory_init;
+ FSP_MEMORY_INIT_PARAMS fsp_memory_init_params;
+ const EFI_GUID fsp_reserved_guid =
+ FSP_RESERVED_MEMORY_RESOURCE_HOB_GUID;
+ void *fsp_reserved_memory_area;
+ FSP_INIT_RT_COMMON_BUFFER fsp_rt_common_buffer;
+ void *hob_list_ptr;
+ const EFI_GUID mrc_guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
+ u32 *mrc_hob;
+ u32 fsp_reserved_bytes;
+ EFI_STATUS status;
+ struct pei_data *pei_ptr;
+ VPD_DATA_REGION *vpd_ptr;
+ UPD_DATA_REGION *upd_ptr;
+ UPD_DATA_REGION upd_data_buffer;
+ int fsp_verification_failure = 0;
+#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
+ unsigned long int data;
+ EFI_PEI_HOB_POINTERS hob_ptr;
+#endif
+
+ /*
+ * Find and copy the UPD region to the stack so the platform can modify
+ * the settings if needed. Modifications to the UPD buffer are done in
+ * the platform callback code. The platform callback code is also
+ * responsible for assigning the UpdDataRngPtr to this buffer if any
+ * updates are made. The default state is to leave the UpdDataRngPtr
+ * set to NULL. This indicates that the FSP code will use the UPD
+ * region in the FSP binary.
+ */
+ post_code(0x34);
+ fsp_header = params->chipset_context;
+ vpd_ptr = (VPD_DATA_REGION *)(fsp_header->CfgRegionOffset +
+ fsp_header->ImageBase);
+ printk(BIOS_DEBUG, "VPD Data: 0x%p\n", vpd_ptr);
+ upd_ptr = (UPD_DATA_REGION *)(vpd_ptr->PcdUpdRegionOffset +
+ fsp_header->ImageBase);
+ printk(BIOS_DEBUG, "UPD Data: 0x%p\n", upd_ptr);
+ memcpy(&upd_data_buffer, upd_ptr, sizeof(upd_data_buffer));
+
+ /* Zero fill RT Buffer data and start populating fields. */
+ memset(&fsp_rt_common_buffer, 0, sizeof(fsp_rt_common_buffer));
+ pei_ptr = params->pei_data;
+ if (pei_ptr->boot_mode == SLEEP_STATE_S3) {
+ fsp_rt_common_buffer.BootMode = BOOT_ON_S3_RESUME;
+ } else if (pei_ptr->saved_data != NULL) {
+ fsp_rt_common_buffer.BootMode =
+ BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
+ } else {
+ fsp_rt_common_buffer.BootMode = BOOT_WITH_FULL_CONFIGURATION;
+ }
+ fsp_rt_common_buffer.UpdDataRgnPtr = &upd_data_buffer;
+ fsp_rt_common_buffer.BootLoaderTolumSize = CBMEM_ROOT_SIZE;
+
+ /* Get any board specific changes */
+ fsp_memory_init_params.NvsBufferPtr = (void *)pei_ptr->saved_data;
+ fsp_memory_init_params.RtBufferPtr = &fsp_rt_common_buffer;
+ fsp_memory_init_params.HobListPtr = &hob_list_ptr;
+ board_fsp_memory_init_params(params, fsp_header,
+ &fsp_memory_init_params);
+ post_code(0x36);
+
+ /* Display the UPD data */
+#if IS_ENABLED(CONFIG_DISPLAY_UPD_DATA)
+ printk(BIOS_SPEW, "Updated Product Data (UPD):\n");
+ hexdump32(BIOS_SPEW, (void *)&upd_data_buffer, sizeof(upd_data_buffer));
+#endif
+
+ /* Call FspMemoryInit to initialize RAM */
+ fsp_memory_init = (FSP_MEMORY_INIT)(fsp_header->ImageBase
+ + fsp_header->FspMemoryInitEntryOffset);
+ printk(BIOS_DEBUG, "Calling FspMemoryInit: 0x%p\n", fsp_memory_init);
+ printk(BIOS_SPEW, " 0x%p: NvsBufferPtr\n",
+ fsp_memory_init_params.NvsBufferPtr);
+ printk(BIOS_SPEW, " 0x%p: RtBufferPtr\n",
+ fsp_memory_init_params.RtBufferPtr);
+ printk(BIOS_SPEW, " 0x%p: HobListPtr\n",
+ fsp_memory_init_params.HobListPtr);
+
+ timestamp_add_now(TS_FSP_MEMORY_INIT_START);
+ status = fsp_memory_init(&fsp_memory_init_params);
+ post_code(0x37);
+ timestamp_add_now(TS_FSP_MEMORY_INIT_END);
+
+ printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status);
+ if (status != EFI_SUCCESS)
+ die("ERROR - FspMemoryInit failed to initialize memory!\n");
+
+ /* Locate the FSP reserved memory area */
+ fsp_reserved_bytes = 0;
+ fsp_memory = get_next_resource_hob(&fsp_reserved_guid, hob_list_ptr);
+ if (fsp_memory == NULL) {
+ fsp_verification_failure = 1;
+ printk(BIOS_DEBUG,
+ "7.2: FSP_RESERVED_MEMORY_RESOURCE_HOB missing!\n");
+ } else {
+ fsp_reserved_bytes = fsp_memory->ResourceLength;
+ printk(BIOS_DEBUG, "Reserving 0x%016lx bytes for FSP\n",
+ (unsigned long int)fsp_reserved_bytes);
+ }
+
+ /* Display SMM area */
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ char *smm_base;
+ size_t smm_size;
+
+ smm_region((void **)&smm_base, &smm_size);
+ printk(BIOS_DEBUG, "0x%08x: smm_size\n", (unsigned int)smm_size);
+ printk(BIOS_DEBUG, "0x%p: smm_base\n", smm_base);
+#endif
+
+ /* Migrate CAR data */
+ printk(BIOS_DEBUG, "0x%08x: CONFIG_CHIPSET_RESERVED_MEM_BYTES\n",
+ CONFIG_CHIPSET_RESERVED_MEM_BYTES);
+ printk(BIOS_DEBUG, "0x%p: cbmem_top\n", cbmem_top());
+ if (pei_ptr->boot_mode != SLEEP_STATE_S3) {
+ cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
+ fsp_reserved_bytes);
+ } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
+ fsp_reserved_bytes)) {
+#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
+ printk(BIOS_DEBUG, "Failed to recover CBMEM in S3 resume.\n");
+ /* Failed S3 resume, reset to come up cleanly */
+ hard_reset();
+#endif
+ }
+
+ /* Save the FSP runtime parameters. */
+ fsp_set_runtime(params->chipset_context, hob_list_ptr);
+
+ /* Lookup the FSP_BOOTLOADER_TOLUM_HOB */
+ cbmem_root = get_next_resource_hob(&bootldr_tolum_guid, hob_list_ptr);
+ if (cbmem_root == NULL) {
+ fsp_verification_failure = 1;
+ printk(BIOS_ERR, "7.4: FSP_BOOTLOADER_TOLUM_HOB missing!\n");
+ printk(BIOS_ERR, "BootLoaderTolumSize: 0x%08x bytes\n",
+ fsp_rt_common_buffer.BootLoaderTolumSize);
+ }
+
+#if IS_ENABLED(CONFIG_DISPLAY_HOBS)
+ if (hob_list_ptr == NULL)
+ die("ERROR - HOB pointer is NULL!\n");
+
+ /*
+ * Verify that FSP is generating the required HOBs:
+ * 7.1: FSP_BOOTLOADER_TEMP_MEMORY_HOB only produced for FSP 1.0
+ * 7.5: EFI_PEI_GRAPHICS_INFO_HOB produced by SiliconInit
+ */
+ if (NULL != cbmem_root) {
+ printk(BIOS_DEBUG,
+ "7.4: FSP_BOOTLOADER_TOLUM_HOB: 0x%p\n",
+ cbmem_root);
+ data = cbmem_root->PhysicalStart;
+ printk(BIOS_DEBUG, " 0x%016lx: PhysicalStart\n", data);
+ data = cbmem_root->ResourceLength;
+ printk(BIOS_DEBUG, " 0x%016lx: ResourceLength\n", data);
+ }
+ hob_ptr.Raw = get_next_guid_hob(&mrc_guid, hob_list_ptr);
+ if (NULL == hob_ptr.Raw) {
+ printk(BIOS_ERR, "7.3: FSP_NON_VOLATILE_STORAGE_HOB missing!\n");
+ fsp_verification_failure =
+ (params->pei_data->saved_data == NULL) ? 1 : 0;
+ } else {
+ printk(BIOS_DEBUG,
+ "7.3: FSP_NON_VOLATILE_STORAGE_HOB: 0x%p\n",
+ hob_ptr.Raw);
+ }
+ if (fsp_memory != NULL) {
+ printk(BIOS_DEBUG,
+ "7.2: FSP_RESERVED_MEMORY_RESOURCE_HOB: 0x%p\n",
+ fsp_memory);
+ data = fsp_memory->PhysicalStart;
+ printk(BIOS_DEBUG, " 0x%016lx: PhysicalStart\n", data);
+ data = fsp_memory->ResourceLength;
+ printk(BIOS_DEBUG, " 0x%016lx: ResourceLength\n", data);
+ }
+
+ /* Verify all the HOBs are present */
+ if (fsp_verification_failure)
+ printk(BIOS_DEBUG,
+ "ERROR - Missing one or more required FSP HOBs!\n");
+
+ /* Display the HOBs */
+ print_hob_type_structure(0, hob_list_ptr);
+#endif
+
+ /* Get the address of the CBMEM region for the FSP reserved memory */
+ fsp_reserved_memory_area = cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY);
+ printk(BIOS_DEBUG, "0x%p: fsp_reserved_memory_area\n",
+ fsp_reserved_memory_area);
+
+ /* Verify the order of CBMEM root and FSP memory */
+ if ((fsp_memory != NULL) && (cbmem_root != NULL) &&
+ (cbmem_root->PhysicalStart <= fsp_memory->PhysicalStart)) {
+ fsp_verification_failure = 1;
+ printk(BIOS_DEBUG,
+ "ERROR - FSP reserved memory above CBMEM root!\n");
+ }
+
+ /* Verify that the FSP memory was properly reserved */
+ if ((fsp_memory != NULL) && ((fsp_reserved_memory_area == NULL) ||
+ (fsp_memory->PhysicalStart !=
+ (unsigned int)fsp_reserved_memory_area))) {
+ fsp_verification_failure = 1;
+ printk(BIOS_DEBUG, "ERROR - Reserving FSP memory area!\n");
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ if (cbmem_root != NULL) {
+ size_t delta_bytes = (unsigned int)smm_base
+ - cbmem_root->PhysicalStart
+ - cbmem_root->ResourceLength;
+ printk(BIOS_DEBUG,
+ "0x%08x: CONFIG_CHIPSET_RESERVED_MEM_BYTES\n",
+ CONFIG_CHIPSET_RESERVED_MEM_BYTES);
+ printk(BIOS_DEBUG,
+ "0x%08x: Chipset reserved bytes reported by FSP\n",
+ (unsigned int)delta_bytes);
+ die("Please verify the chipset reserved size\n");
+ }
+#endif
+ }
+
+ /* Verify the FSP 1.1 HOB interface */
+ if (fsp_verification_failure)
+ die("ERROR - Coreboot's requirements not met by FSP binary!\n");
+
+ /* Display the memory configuration */
+ report_memory_config();
+
+ /* Locate the memory configuration data to speed up the next reboot */
+ mrc_hob = get_next_guid_hob(&mrc_guid, hob_list_ptr);
+ if (mrc_hob == NULL)
+ printk(BIOS_DEBUG,
+ "Memory Configuration Data Hob not present\n");
+ else {
+ pei_ptr->data_to_save = GET_GUID_HOB_DATA(mrc_hob);
+ pei_ptr->data_to_save_size = ALIGN(
+ ((u32)GET_HOB_LENGTH(mrc_hob)), 16);
+ }
+}
diff --git a/src/soc/intel/common/ramstage.h b/src/soc/intel/common/ramstage.h
new file mode 100644
index 0000000..e46f108
--- /dev/null
+++ b/src/soc/intel/common/ramstage.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+#ifndef _INTEL_COMMON_RAMSTAGE_H_
+#define _INTEL_COMMON_RAMSTAGE_H_
+
+#include <stdint.h>
+
+/* Perform Intel silicon init. */
+void intel_silicon_init(void);
+/* Called after the silicon init code has run. */
+void soc_after_silicon_init(void);
+/* SoC implementation for caching support code. */
+void soc_save_support_code(void *start, size_t size, void *entry);
+/* SoC implementation for restoring support code after S3 resume. Returns
+ * previously passed entry pointer from soc_save_support_code(). */
+void *soc_restore_support_code(void);
+
+#endif /* _INTEL_COMMON_RAMSTAGE_H_ */
diff --git a/src/soc/intel/common/romstage.c b/src/soc/intel/common/romstage.c
new file mode 100644
index 0000000..fd7adc9
--- /dev/null
+++ b/src/soc/intel/common/romstage.c
@@ -0,0 +1,356 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 <stddef.h>
+#include <stdint.h>
+#include <arch/cpu.h>
+#include <arch/io.h>
+#include <arch/cbfs.h>
+#include <arch/stages.h>
+#include <arch/early_variables.h>
+#include <console/console.h>
+#include <cbmem.h>
+#include <cpu/x86/mtrr.h>
+#include <ec/google/chromeec/ec.h>
+#include <ec/google/chromeec/ec_commands.h>
+#include <elog.h>
+#include <ramstage_cache.h>
+#include <reset.h>
+#include <romstage_handoff.h>
+#include <soc/intel/common/mrc_cache.h>
+#include <soc/pei_wrapper.h>
+#include <soc/pm.h>
+#include <soc/romstage.h>
+#include <soc/spi.h>
+#include <timestamp.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+
+/* Entry from cache-as-ram.inc. */
+asmlinkage void *romstage_main(unsigned int bist,
+ uint32_t tsc_low, uint32_t tsc_high,
+ void *chipset_context)
+{
+ void *top_of_stack;
+ struct pei_data pei_data;
+ struct romstage_params params = {
+ .bist = bist,
+ .pei_data = &pei_data,
+ .chipset_context = chipset_context,
+ };
+
+ post_code(0x30);
+
+ /* Save timestamp data */
+ timestamp_early_init((((uint64_t)tsc_high) << 32) | (uint64_t)tsc_low);
+ timestamp_add_now(TS_START_ROMSTAGE);
+
+ memset(&pei_data, 0, sizeof(pei_data));
+
+ /* Call into pre-console init code. */
+ soc_pre_console_init(¶ms);
+ mainboard_pre_console_init(¶ms);
+
+ /* Start console drivers */
+ console_init();
+
+ /* Display parameters */
+ printk(BIOS_SPEW, "bist: 0x%08x\n", bist);
+ printk(BIOS_SPEW, "tsc_low: 0x%08x\n", tsc_low);
+ printk(BIOS_SPEW, "tsc_hi: 0x%08x\n", tsc_high);
+ printk(BIOS_SPEW, "CONFIG_MMCONF_BASE_ADDRESS: 0x%08x\n",
+ CONFIG_MMCONF_BASE_ADDRESS);
+ printk(BIOS_INFO, "Using: %s\n",
+ IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1) ? "FSP 1.1" :
+ (IS_ENABLED(CONFIG_HAVE_MRC) ? "MRC" :
+ "No Memory Support"));
+
+ /* Display FSP banner */
+#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
+ printk(BIOS_DEBUG, "FSP TempRamInit successful\n");
+ print_fsp_info(params.chipset_context);
+#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
+
+ /* Get power state */
+ params.power_state = fill_power_state();
+
+ /* Print useful platform information */
+ report_platform_info();
+
+ /* Set CPU frequency to maximum */
+ set_max_freq();
+
+ /* Perform SOC specific initialization. */
+ soc_romstage_init(¶ms);
+
+ /* Call into mainboard. */
+ mainboard_romstage_entry(¶ms);
+ soc_after_ram_init(¶ms);
+ post_code(0x38);
+
+ top_of_stack = setup_stack_and_mtrrs();
+
+#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
+ printk(BIOS_DEBUG, "Calling FspTempRamExit API\n");
+ timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_START);
+#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
+
+ return top_of_stack;
+}
+
+/* Entry from the mainboard. */
+void romstage_common(struct romstage_params *params)
+{
+ const struct mrc_saved_data *cache;
+ struct romstage_handoff *handoff;
+ struct pei_data *pei_data;
+
+ post_code(0x32);
+
+ timestamp_add_now(TS_BEFORE_INITRAM);
+
+ pei_data = params->pei_data;
+ pei_data->boot_mode = params->power_state->prev_sleep_state;
+
+#if IS_ENABLED(CONFIG_ELOG_BOOT_COUNT)
+ if (params->power_state->prev_sleep_state != SLEEP_STATE_S3)
+ boot_count_increment();
+#endif
+
+ /* Perform remaining SOC initialization */
+ soc_pre_ram_init(params);
+ post_code(0x33);
+
+ /* Check recovery and MRC cache */
+ params->pei_data->saved_data_size = 0;
+ params->pei_data->saved_data = NULL;
+ if (!params->pei_data->disable_saved_data) {
+ if (recovery_mode_enabled()) {
+ /* Recovery mode does not use MRC cache */
+ printk(BIOS_DEBUG,
+ "Recovery mode: not using MRC cache.\n");
+ } else if (!mrc_cache_get_current(&cache)) {
+ /* MRC cache found */
+ params->pei_data->saved_data_size = cache->size;
+ params->pei_data->saved_data = &cache->data[0];
+ } else if (params->pei_data->boot_mode == SLEEP_STATE_S3) {
+ /* Waking from S3 and no cache. */
+ printk(BIOS_DEBUG,
+ "No MRC cache found in S3 resume path.\n");
+ post_code(POST_RESUME_FAILURE);
+ hard_reset();
+ } else {
+ printk(BIOS_DEBUG, "No MRC cache found.\n");
+ mainboard_check_ec_image(params);
+ }
+ }
+
+ /* Initialize RAM */
+ raminit(params);
+ timestamp_add_now(TS_AFTER_INITRAM);
+
+ /* Save MRC output */
+ printk(BIOS_DEBUG, "MRC data at %p %d bytes\n", pei_data->data_to_save,
+ pei_data->data_to_save_size);
+ if (params->pei_data->boot_mode != SLEEP_STATE_S3) {
+ if (params->pei_data->data_to_save_size != 0 &&
+ params->pei_data->data_to_save != NULL) {
+ mrc_cache_stash_data(params->pei_data->data_to_save,
+ params->pei_data->data_to_save_size);
+ }
+ }
+
+ /* Save DIMM information */
+ mainboard_save_dimm_info(params);
+
+ /* Create romstage handof information */
+ handoff = romstage_handoff_find_or_add();
+ if (handoff != NULL)
+ handoff->s3_resume = (params->power_state->prev_sleep_state ==
+ SLEEP_STATE_S3);
+ else {
+ printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+ hard_reset();
+ }
+
+#if IS_ENABLED(CONFIG_CHROMEOS)
+ /* Normalize the sleep state to what init_chromeos() wants for S3: 2 */
+ init_chromeos((params->power_state->prev_sleep_state == SLEEP_STATE_S3)
+ ? 2 : 0);
+#endif
+}
+
+asmlinkage void romstage_after_car(void *chipset_context)
+{
+ if (IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)) {
+ timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_END);
+ printk(BIOS_DEBUG, "FspTempRamExit returned successfully\n");
+ soc_after_temp_ram_exit();
+ }
+
+ timestamp_add_now(TS_END_ROMSTAGE);
+
+ /* Run vboot verification if configured. */
+ vboot_verify_firmware(romstage_handoff_find_or_add());
+
+ /* Load the ramstage. */
+ copy_and_run();
+ die("ERROR - Failed to load ramstage!");
+}
+
+#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
+__attribute__((weak)) void board_fsp_memory_init_params(
+ struct romstage_params *params,
+ FSP_INFO_HEADER *fsp_header,
+ FSP_MEMORY_INIT_PARAMS * fsp_memory_init_params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
+
+/* Initialize the power state */
+__attribute__((weak)) struct chipset_power_state *fill_power_state(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return NULL;
+}
+
+__attribute__((weak)) void mainboard_check_ec_image(
+ struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ struct pei_data *pei_data;
+
+ pei_data = params->pei_data;
+ if (params->pei_data->boot_mode == SLEEP_STATE_S0) {
+ /* Ensure EC is running RO firmware. */
+ google_chromeec_check_ec_image(EC_IMAGE_RO);
+ }
+#endif
+}
+
+/* Board initialization before the console is enabled */
+__attribute__((weak)) void mainboard_pre_console_init(
+ struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* Board initialization before and after RAM is enabled */
+__attribute__((weak)) void mainboard_romstage_entry(
+ struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+
+ post_code(0x31);
+
+ /* Initliaze memory */
+ romstage_common(params);
+}
+
+/* Used by MRC images to save DIMM information */
+__attribute__((weak)) void mainboard_save_dimm_info(
+ struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* Get the memory configuration data */
+__attribute__((weak)) int mrc_cache_get_current(
+ const struct mrc_saved_data **cache)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return -1;
+}
+
+/* Save the memory configuration data */
+__attribute__((weak)) int mrc_cache_stash_data(void *data, size_t size)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ return -1;
+}
+
+/* Transition RAM from off or self-refresh to active */
+__attribute__((weak)) void raminit(struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+ post_code(0x34);
+ die("ERROR - No RAM initialization specified!\n");
+}
+
+/* Display the memory configuration */
+__attribute__((weak)) void report_memory_config(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* Display the platform configuration */
+__attribute__((weak)) void report_platform_info(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* Choose top of stack and setup MTRRs */
+__attribute__((weak)) void *setup_stack_and_mtrrs(void)
+{
+ printk(BIOS_ERR, "WEAK: %s/%s called\n", __FILE__, __func__);
+ die("ERROR - Must specify top of stack!\n");
+ return NULL;
+}
+
+/* Speed up the CPU to the maximum frequency */
+__attribute__((weak)) void set_max_freq(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* SOC initialization after RAM is enabled */
+__attribute__((weak)) void soc_after_ram_init(struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* SOC initialization after temporary RAM is disabled */
+__attribute__((weak)) void soc_after_temp_ram_exit(void)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* SOC initialization before the console is enabled */
+__attribute__((weak)) void soc_pre_console_init(struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* SOC initialization before RAM is enabled */
+__attribute__((weak)) void soc_pre_ram_init(struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}
+
+/* SOC initialization after console is enabled */
+__attribute__((weak)) void soc_romstage_init(struct romstage_params *params)
+{
+ printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+#if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC)
+ /* Ensure the EC is in the right mode for recovery */
+ google_chromeec_early_init();
+#endif
+}
diff --git a/src/soc/intel/common/romstage.h b/src/soc/intel/common/romstage.h
new file mode 100644
index 0000000..2747665
--- /dev/null
+++ b/src/soc/intel/common/romstage.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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 _COMMON_ROMSTAGE_H_
+#define _COMMON_ROMSTAGE_H_
+
+#include <stdint.h>
+#include <arch/cpu.h>
+#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
+#include <fsp_util.h>
+#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
+#include <soc/pei_data.h>
+#include <soc/pm.h> /* chip_power_state */
+
+struct romstage_params {
+ unsigned long bist;
+ struct chipset_power_state *power_state;
+ struct pei_data *pei_data;
+ void *chipset_context;
+};
+
+/*
+ * FSP Boot Flow:
+ * 1. src/cpu/x86/16bit/reset.inc
+ * 2. src/cpu/x86/16bit/entry.inc
+ * 3. other modules
+ * 4. src/drivers/intel/fsp/fsp_1_1.inc
+ * 5. src/drivers/intel/fsp/fsp_util.c/find_fsp
+ * 6. FSP binary/TempRamInit
+ * 7. src/drivers/intel/fsp/fsp_1_1.inc - return
+ * 8. src/soc/intel/common/romstage.c/romstage_main
+ * 9 src/soc/.../romstage/.../soc_pre_console_init
+ * 10 src/console/console.c/console_init
+ * 11 src/soc/.../romstage/.../soc_romstage_init
+ * 12. src/mainboard/.../romstage.c/mainboard_romstage_entry
+ * 13. src/soc/intel/skylake/romstage/romstage.c/romstage_common
+ * 14 src/soc/.../romstage/.../soc_pre_raminit
+ * 15. FSP binary/MemoryInit
+ * 16. src/soc/intel/common/romstage.c/romstage_common - return
+ * 17. src/mainboard/.../romstage.c/mainboard_romstage_entry - return
+ * 18. src/soc/intel/common/romstage.c/romstage_main - return
+ * 19. src/soc/intel/skylake/stack.c/setup_stack_and_mttrs
+ * 20. src/drivers/intel/fsp/fsp_1_1.inc - return, cleanup
+ * after call to romstage_main
+ * 21. FSP binary/TempRamExit
+ * 22. src/soc/intel/common/romstage.c/romstage_after_car
+ * 23. FSP binary/SiliconInit
+ * 24. src/soc/intel/common/romstage.c/romstage_after_car - return
+ * 25. src/soc/intel/.../chip.c/skylake_final
+ * 26. src/drivers/intel/fsp/fsp_util.c/fsp_notify
+ * 27. FSP binary/FspNotify
+ * 28. src/soc/intel/.../ramstage.c/fsp_final
+ * 29. src/drivers/intel/fsp/fsp_util.c/fsp_notify
+ * 30. FSP binary/FspNotify
+ */
+
+#if IS_ENABLED(CONFIG_PLATFORM_USES_FSP1_1)
+void board_fsp_memory_init_params(
+ struct romstage_params *params,
+ FSP_INFO_HEADER *fsp_header,
+ FSP_MEMORY_INIT_PARAMS * fsp_memory_init_params);
+#endif /* CONFIG_PLATFORM_USES_FSP1_1 */
+void mainboard_check_ec_image(struct romstage_params *params);
+void mainboard_pre_console_init(struct romstage_params *params);
+void mainboard_romstage_entry(struct romstage_params *params);
+void mainboard_save_dimm_info(struct romstage_params *params);
+void raminit(struct romstage_params *params);
+void report_memory_config(void);
+void report_platform_info(void);
+asmlinkage void romstage_after_car(void *chipset_context);
+void romstage_common(struct romstage_params *params);
+asmlinkage void *romstage_main(unsigned int bist, uint32_t tsc_lo,
+ uint32_t tsc_high, void *chipset_context);
+void *setup_stack_and_mtrrs(void);
+void set_max_freq(void);
+void soc_after_ram_init(struct romstage_params *params);
+void soc_after_temp_ram_exit(void);
+void soc_pre_console_init(struct romstage_params *params);
+void soc_pre_ram_init(struct romstage_params *params);
+void soc_romstage_init(struct romstage_params *params);
+
+#endif /* _COMMON_ROMSTAGE_H_ */
diff --git a/src/soc/intel/common/spi_loading.c b/src/soc/intel/common/spi_loading.c
new file mode 100644
index 0000000..fe3522b
--- /dev/null
+++ b/src/soc/intel/common/spi_loading.c
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/byteorder.h>
+#include <boot/coreboot_tables.h>
+#include <cbmem.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+
+#define CACHELINE_SIZE 64
+#define INTRA_CACHELINE_MASK (CACHELINE_SIZE - 1)
+#define CACHELINE_MASK (~INTRA_CACHELINE_MASK)
+
+static void *find_mirror_buffer(int len)
+{
+ int nentries;
+ int i;
+ struct lb_memory *mem;
+ void *buffer;
+
+ len = ALIGN(len, 4096);
+
+ mem = get_lb_mem();
+ nentries = (mem->size - sizeof(*mem)) / sizeof(mem->map[0]);
+
+ /*
+ * Find the highest RAM entry that accommodates the lenth provide
+ * while falling below 4GiB.
+ */
+ buffer = NULL;
+ for (i = 0; i < nentries; i++) {
+ const uint64_t max_addr = 1ULL << 32;
+ uint64_t start;
+ uint64_t size;
+ struct lb_memory_range *r;
+
+ r = &mem->map[i];
+
+ if (r->type != LB_MEM_RAM)
+ continue;
+
+ start = unpack_lb64(r->start);
+ if (start >= max_addr)
+ continue;
+
+ size = unpack_lb64(r->size);
+ if (size < len)
+ continue;
+
+ /* Adjust size of buffer if range exceeds max address. */
+ if (start + size > max_addr)
+ size = max_addr - start;
+
+ if (size < len)
+ continue;
+
+ buffer = (void *)(uintptr_t)(start + size - len);
+ }
+
+ return buffer;
+}
+
+/*
+ * Mirror the payload file to the default SMM location if it is small enough.
+ * The default SMM region can be used since no one is using the memory at this
+ * location at this stage in the boot.
+ */
+static void *spi_mirror(void *file_start, int file_len)
+{
+ int alignment_diff;
+ char *src;
+ char *dest;
+
+ alignment_diff = (INTRA_CACHELINE_MASK & (long)file_start);
+
+ /*
+ * Adjust file length so that the start and end points are aligned to a
+ * cacheline. Coupled with the ROM caching in the CPU the SPI hardware
+ * will read and cache full length cachelines. It will also prefetch
+ * data as well. Once things are mirrored in memory all accesses should
+ * hit the CPUs cache.
+ */
+ file_len += alignment_diff;
+ file_len = ALIGN(file_len, CACHELINE_SIZE);
+
+ printk(BIOS_DEBUG, "Payload aligned size: 0x%x\n", file_len);
+
+ dest = find_mirror_buffer(file_len);
+
+ /*
+ * Just pass back the pointer to ROM space if a buffer could not
+ * be found to mirror into.
+ */
+ if (dest == NULL)
+ return file_start;
+
+ src = (void *)(CACHELINE_MASK & (long)file_start);
+ /*
+ * Note that if mempcy is not using 32-bit moves the performance will
+ * degrade because the SPI hardware prefetchers look for
+ * cacheline-aligned 32-bit accesses to kick in.
+ */
+ memcpy(dest, src, file_len);
+
+ /* Provide pointer into mirrored space. */
+ return &dest[alignment_diff];
+}
+
+void *cbfs_load_payload(struct cbfs_media *media, const char *name)
+{
+ int file_len;
+ void *file_start;
+ struct cbfs_file *file;
+
+ file_start = vboot_get_payload(&file_len);
+
+ if (file_start != NULL)
+ return spi_mirror(file_start, file_len);
+
+ file = cbfs_get_file(media, name);
+
+ if (file == NULL)
+ return NULL;
+
+ if (ntohl(file->type) != CBFS_TYPE_PAYLOAD)
+ return NULL;
+
+ file_len = ntohl(file->len);
+
+ file_start = CBFS_SUBHEADER(file);
+
+ return spi_mirror(file_start, file_len);
+}
diff --git a/src/soc/intel/common/stack.c b/src/soc/intel/common/stack.c
new file mode 100644
index 0000000..3e6e4b7
--- /dev/null
+++ b/src/soc/intel/common/stack.c
@@ -0,0 +1,173 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * 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 <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include "memmap.h"
+#include "romstage.h"
+#include "stack.h"
+#include <stdlib.h>
+
+const unsigned long romstage_ram_stack_size = CONFIG_ROMSTAGE_RAM_STACK_SIZE;
+
+/*
+ * Romstage needs quite a bit of stack for decompressing images since the lzma
+ * lib keeps its state on the stack during romstage.
+ */
+static unsigned long choose_top_of_stack(void)
+{
+ unsigned long stack_top;
+
+ /* cbmem_add() does a find() before add(). */
+ stack_top = (unsigned long)cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK,
+ romstage_ram_stack_size);
+ stack_top += romstage_ram_stack_size;
+ return stack_top;
+}
+
+/*
+ * setup_stack_and_mtrrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use.
+ */
+void *setup_stack_and_mtrrs(void)
+{
+ size_t alignment;
+ uint32_t aligned_ram;
+ uint32_t mtrr_mask_upper;
+ int num_mtrrs;
+ uint32_t *slot;
+ unsigned long top_of_stack;
+
+ /* Top of stack needs to be aligned to a 8-byte boundary. */
+ top_of_stack = choose_top_of_stack();
+ slot = (void *)top_of_stack;
+ num_mtrrs = 0;
+
+ /*
+ * The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits.
+ */
+ mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+
+ /*
+ * The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ * +0: Number of MTRRs
+ * +4: MTRR base 0 31:0
+ * +8: MTRR base 0 63:32
+ * +12: MTRR mask 0 31:0
+ * +16: MTRR mask 0 63:32
+ * +20: MTRR base 1 31:0
+ * +24: MTRR base 1 63:32
+ * +28: MTRR mask 1 31:0
+ * +32: MTRR mask 1 63:32
+ */
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /*
+ * +-------------------------+ Top of RAM (aligned)
+ * | System Management Mode |
+ * | code and data | Length: CONFIG_TSEG_SIZE
+ * | (TSEG) |
+ * +-------------------------+ SMM base (aligned)
+ * | |
+ * | Chipset Reserved Memory |
+ * | |
+ * +-------------------------+ Chipset reserved mem base (aligned)
+ * | |
+ * | FSP Reserved Memory |
+ * | |
+ * +-------------------------+ top_of_ram (not aligned)
+ * | |
+ * | CBMEM Root |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Various CBMEM Entries |
+ * | |
+ * +-------------------------+ top_of_stack (8 byte aligned)
+ * | |
+ * | stack (CBMEM Entry) |
+ * | |
+ * +-------------------------+
+ *
+ * Requirement:
+ * Chipset reserved memory base needs to be aligned to a multiple
+ * of TSEG size when SMM is in use or 8 Mib when SMM is not supported
+ * by the SOC/board configuration.
+ */
+
+ /*
+ * Cache the stack and the other CBMEM entries as well as part or all
+ * of the FSP reserved memory region.
+ */
+ alignment = mmap_region_granluarity();
+ aligned_ram = ALIGN_DOWN(top_of_stack - romstage_ram_stack_size,
+ alignment);
+
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRRphysMaskValid);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, aligned_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ void *smm_base;
+ size_t smm_size;
+ uint32_t tseg_base;
+
+ /*
+ * Cache the TSEG region at the top of ram. This region is not
+ * restricted to SMM mode until SMM has been relocated. By setting
+ * the region to cacheable it provides faster access when relocating
+ * the SMM handler as well as using the TSEG region for other purposes.
+ */
+ smm_region(&smm_base, &smm_size);
+ tseg_base = (uint32_t)smm_base;
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRRphysMaskValid);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, tseg_base | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+#endif
+
+ /*
+ * Save the number of MTRRs to setup. Return the stack location
+ * pointing to the number of MTRRs.
+ */
+ slot = stack_push32(slot, num_mtrrs);
+ return slot;
+}
+
diff --git a/src/soc/intel/common/stack.h b/src/soc/intel/common/stack.h
new file mode 100644
index 0000000..850a070
--- /dev/null
+++ b/src/soc/intel/common/stack.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc
+ * 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
+ */
+
+#ifndef _COMMON_STACK_H_
+#define _COMMON_STACK_H_
+
+#include <stdint.h>
+
+static inline void *stack_push32(void *stack, uint32_t value)
+{
+ uint32_t *stack32 = stack;
+
+ stack32 = &stack32[-1];
+ *stack32 = value;
+ return stack32;
+}
+
+#endif /* _COMMON_STACK_H_ */
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/10049
-gerrit
commit b034ef322d990fde13022d3c9ee76177685e37c9
Author: Lee Leahy <leroy.p.leahy(a)intel.com>
Date: Mon Apr 20 15:29:16 2015 -0700
DO NOT MERGE: drivers/intel: Add FSP 1.1 Driver
Add the FSP 1.1 driver files.
Updates will occur manually to these files only for FSP 1.1 support. An
fsp_x_y should be added in the future to support newer versions of the
FSP specification.
Please note that due to the interface with EDK2, these files make
references to data structures and fields that use CamelCase.
BRANCH=none
BUG=None
TEST=Build for Braswell or Skylake boards using FSP 1.1.
Change-Id: I2914c047d786a3060075356783ac9758bc41f633
Signed-off-by: Lee Leahy <leroy.p.leahy(a)intel.com>
---
src/drivers/intel/Kconfig | 1 +
src/drivers/intel/Makefile.inc | 1 +
src/drivers/intel/fsp1_1/Kconfig | 225 +++++++++++++
src/drivers/intel/fsp1_1/Makefile.inc | 65 ++++
src/drivers/intel/fsp1_1/cache_as_ram.inc | 332 +++++++++++++++++++
src/drivers/intel/fsp1_1/fastboot_cache.c | 271 ++++++++++++++++
src/drivers/intel/fsp1_1/fsp_gop.c | 100 ++++++
src/drivers/intel/fsp1_1/fsp_gop.h | 35 ++
src/drivers/intel/fsp1_1/fsp_hob.c | 512 ++++++++++++++++++++++++++++++
src/drivers/intel/fsp1_1/fsp_relocate.c | 458 ++++++++++++++++++++++++++
src/drivers/intel/fsp1_1/fsp_util.c | 252 +++++++++++++++
src/drivers/intel/fsp1_1/fsp_util.h | 122 +++++++
12 files changed, 2374 insertions(+)
diff --git a/src/drivers/intel/Kconfig b/src/drivers/intel/Kconfig
index 511cf5c..f405927 100644
--- a/src/drivers/intel/Kconfig
+++ b/src/drivers/intel/Kconfig
@@ -17,5 +17,6 @@
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
+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 dc947ff..3ddb05f 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
new file mode 100644
index 0000000..48dd74c
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/Kconfig
@@ -0,0 +1,225 @@
+##
+## 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
+##
+
+comment "Intel FSP"
+
+config PLATFORM_USES_FSP1_1
+ bool "Use Intel Firmware Support Package"
+ help
+ Does the code require the Intel Firmware Support Package?
+
+if PLATFORM_USES_FSP1_1
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfef00000
+
+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
+ 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 FSP_RESERVED_MEM_SIZE
+ hex "FSP Reserved Memory"
+ default 0x00100000
+ help
+ Memory size in bytes reserved by FSP between PEI Memory and the
+ base of TSEG.
+
+config MRC_CACHE_FILE
+ string "File containing the cached MRC values"
+ help
+ The path and filename of the cached MRC values.
+
+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 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"
+ 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 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 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
+ 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.
+
+config GOP_SUPPORT
+ bool "Enables GOP support"
+ default y
+
+config POST_IO
+ bool
+ default y
+
+config POST_IO_PORT
+ hex
+ default 0x80
+
+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
new file mode 100644
index 0000000..1b5d6ca
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/Makefile.inc
@@ -0,0 +1,65 @@
+#
+# 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
+# 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
+#
+
+romstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+romstage-$(CONFIG_GOP_SUPPORT) += fsp_gop.c
+romstage-y += fsp_hob.c
+romstage-y += fsp_util.c
+
+ramstage-$(CONFIG_ENABLE_MRC_CACHE) += fastboot_cache.c
+ramstage-$(CONFIG_GOP_SUPPORT) += fsp_gop.c
+ramstage-y += fsp_hob.c
+ramstage-y += fsp_relocate.c
+ramstage-y += fsp_util.c
+
+CPPFLAGS_common += -Isrc/drivers/intel/fsp1_1
+
+ifeq ($(CONFIG_USE_GENERIC_FSP_CAR_INC),y)
+cpu_incs-y += $(src)/drivers/intel/fsp1_1/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))
+fsp.bin-position := $(CONFIG_FSP_LOC)
+fsp.bin-type := 0xab
+endif
+
+
+# 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 := $(call strip_quotes,$(CONFIG_MRC_CACHE_FILE))
+mrc.cache-position := $(CONFIG_MRC_CACHE_LOC)
+mrc.cache-type := 0xac
+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..ef6510e
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/cache_as_ram.inc
@@ -0,0 +1,332 @@
+/*
+ * 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.
+ * 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
+ */
+
+/*
+ * 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/stack.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/post_code.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 IS_ENABLED(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 */
+
+ /*
+ * 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
+find_fsp_ret:
+ /* Save the FSP location */
+ 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 FSP */
+
+ /*
+ * Pass early init variables on a fake stack (no memory yet)
+ * as well as the return location
+ */
+ 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
+
+CAR_init_done:
+ 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
+
+ /*
+ * 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
+ */
+
+ /* Build frame for romstage_main(bist, tsc_low, tsc_hi) */
+ 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. */
+ 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)
+
+ /* 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()
+ *
+ * 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.
+ * 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
+ 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 IS_ENABLED(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 /* 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
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..91796c6
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fastboot_cache.c
@@ -0,0 +1,271 @@
+/*
+ * 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)
+{
+ const char *name = "mrc.cache";
+ int type = 0xac;
+ struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, name);
+
+ if (file == NULL) {
+ printk(BIOS_ERR, "Could not find file '%s'.\n", name);
+ return 0;
+ }
+
+ if (ntohl(file->type) != type) {
+ printk(BIOS_ERR, "File '%s' is of type %x, but we requested %x.\n",
+ name, ntohl(file->type), type);
+ return 0;
+ }
+
+ return ntohl(file->len);
+}
+
+/*
+ * 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_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",
+ __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;
+ 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);
+ 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_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",
+ __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_gop.c b/src/drivers/intel/fsp1_1/fsp_gop.c
new file mode 100644
index 0000000..1979f04
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_gop.c
@@ -0,0 +1,100 @@
+/*
+ * 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_DEBUG, "vbt data not found");
+ return NULL;
+ }
+
+ /* Validate the vbt file */
+ vbt.data = CBFS_SUBHEADER(vbt_file);
+ if (*vbt.signature != VBT_SIGNATURE) {
+ printk(BIOS_DEBUG, "FSP VBT not found!\n");
+ return NULL;
+ }
+ *vbt_len = ntohl(vbt_file->len);
+ printk(BIOS_DEBUG, "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;
+}
+
+#ifndef __PRE_RAM__
+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_DEBUG, "Graphics Data Hob is not present\n");
+ return;
+ } else {
+ printk(BIOS_DEBUG, "Graphics Data 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 /* __PRE_RAM__ */
+
diff --git a/src/drivers/intel/fsp1_1/fsp_gop.h b/src/drivers/intel/fsp1_1/fsp_gop.h
new file mode 100644
index 0000000..3446d5f
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_gop.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+#ifndef _FSP_GOP_H_
+#define _FSP_GOP_H_
+
+/* GOP support */
+#if IS_ENABLED(CONFIG_GOP_SUPPORT)
+
+#include <boot/coreboot_tables.h>
+#include <soc/intel/common/gma.h>
+
+const optionrom_vbt_t *fsp_get_vbt(uint32_t *vbt_len);
+#ifndef __PRE_RAM__
+void fsp_gop_framebuffer(struct lb_header *header);
+#endif /* __PRE_RAM__ */
+#endif /* CONFIG_GOP_SUPPORT */
+#endif /* _FSP_GOP_H_ */
+
diff --git a/src/drivers/intel/fsp1_1/fsp_hob.c b/src/drivers/intel/fsp1_1/fsp_hob.c
new file mode 100644
index 0000000..6de67f2
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_hob.c
@@ -0,0 +1,512 @@
+/******************************************************************************
+
+Copyright (C) 2013, Intel Corporation
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+
+ ******************************************************************************/
+
+/***********************************************************************
+ *
+ * fsp_hob.c
+ *
+ * HOB infrastructure code.
+ *
+ **********************************************************************/
+
+#include <arch/early_variables.h>
+#include <arch/hlt.h>
+#include <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#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;
+}
+
+/*
+ * 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.
+ *
+ * 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 *get_next_resource_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_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());
+}
+
+static void print_hob_mem_attributes(void *hob_ptr)
+{
+ 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",
+ 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)hob_mem_addr,
+ (unsigned long)hob_mem_length);
+}
+
+static void print_hob_resource_attributes(void *hob_ptr)
+{
+ 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:
+ hob_res_type_str = "EFI_RESOURCE_SYSTEM_MEMORY";
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO:
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO";
+ break;
+ case EFI_RESOURCE_IO:
+ hob_res_type_str = "EFI_RESOURCE_IO";
+ break;
+ case EFI_RESOURCE_FIRMWARE_DEVICE:
+ hob_res_type_str = "EFI_RESOURCE_FIRMWARE_DEVICE";
+ break;
+ case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT:
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_MAPPED_IO_PORT";
+ break;
+ case EFI_RESOURCE_MEMORY_RESERVED:
+ hob_res_type_str = "EFI_RESOURCE_MEMORY_RESERVED";
+ break;
+ case EFI_RESOURCE_IO_RESERVED:
+ hob_res_type_str = "EFI_RESOURCE_IO_RESERVED";
+ break;
+ case EFI_RESOURCE_MAX_MEMORY_TYPE:
+ hob_res_type_str = "EFI_RESOURCE_MAX_MEMORY_TYPE";
+ break;
+ default:
+ hob_res_type_str = "EFI_RESOURCE_UNKNOWN";
+ break;
+ }
+
+ printk(BIOS_SPEW, " Resource %s (0x%0x) has attributes 0x%0x\n",
+ hob_res_type_str, hob_res_type, hob_res_attr);
+ printk(BIOS_SPEW, " at location 0x%0lx with length 0x%0lx\n",
+ (unsigned long)hob_res_addr,
+ (unsigned long)hob_res_length);
+}
+
+static const char *get_hob_type_string(void *hob_ptr)
+{
+ 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;
+
+ hob.Header = (EFI_HOB_GENERIC_HEADER *)hob_ptr;
+ switch (hob.Header->HobType) {
+ case EFI_HOB_TYPE_HANDOFF:
+ hob_type_string = "EFI_HOB_TYPE_HANDOFF";
+ break;
+ case EFI_HOB_TYPE_MEMORY_ALLOCATION:
+ hob_type_string = "EFI_HOB_TYPE_MEMORY_ALLOCATION";
+ break;
+ case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
+ hob_type_string = "EFI_HOB_TYPE_RESOURCE_DESCRIPTOR";
+ break;
+ case EFI_HOB_TYPE_GUID_EXTENSION:
+ 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:
+ hob_type_string = "EFI_HOB_TYPE_MEMORY_POOL";
+ break;
+ case EFI_HOB_TYPE_UNUSED:
+ hob_type_string = "EFI_HOB_TYPE_UNUSED";
+ break;
+ case EFI_HOB_TYPE_END_OF_HOB_LIST:
+ hob_type_string = "EFI_HOB_TYPE_END_OF_HOB_LIST";
+ break;
+ default:
+ hob_type_string = "EFI_HOB_TYPE_UNRECOGNIZED";
+ break;
+ }
+
+ return hob_type_string;
+}
+
+/*
+ * 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 hob_type, void *hob_list_ptr)
+{
+ u32 *current_hob;
+ u32 *next_hob = 0;
+ u8 last_hob = 0;
+ u32 current_type;
+ const char *current_type_str;
+
+ current_hob = hob_list_ptr;
+
+ /*
+ * 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, "0x%p: hob_list_ptr\n", hob_list_ptr);
+ do {
+ 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 (current_type == hob_type || hob_type == 0x0000) {
+ printk(BIOS_DEBUG, "HOB 0x%0x is an %s (type 0x%0x)\n",
+ (u32)current_hob, current_type_str,
+ current_type);
+ switch (current_type) {
+ case EFI_HOB_TYPE_MEMORY_ALLOCATION:
+ print_hob_mem_attributes(current_hob);
+ break;
+ case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
+ print_hob_resource_attributes(current_hob);
+ break;
+ }
+ }
+
+ /* 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 (!last_hob);
+ printk(BIOS_DEBUG, "=== End of FSP HOB Data Structure ===\n\n");
+}
+
+#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 = 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;
+ }
+
+ 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);
+
+#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 */
+
+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_ENTRIES(fsp_hob_find) = {
+ BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
+ find_fsp_hob_update_mrc, NULL),
+};
+
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 0000000..db613ee
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_relocate.c
@@ -0,0 +1,458 @@
+/*
+ * 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. Need to subtract fixup_offset
+ * so the image could be relocated if needed. */
+ teih->ImageBase += adj - fixup_offset;
+
+ 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 FSP_INFO_HEADER *fsp_relocate_in_place(void *fsp, size_t size)
+{
+ EFI_FIRMWARE_VOLUME_HEADER *fvh;
+ EFI_FFS_FILE_HEADER *ffsfh;
+ EFI_COMMON_SECTION_HEADER *csh;
+ size_t offset;
+ size_t file_offset;
+ size_t fih_offset;
+
+ fih_offset = 0;
+ offset = 0;
+ fvh = fsp;
+
+ if (fvh->Signature != EFI_FVH_SIGNATURE)
+ return NULL;
+
+ printk(FSP_DBG_LVL, "FVH length: %zx Mapping length: %zx\n",
+ (size_t)fvh->FvLength, size);
+
+ if (fvh->FvLength != size)
+ return NULL;
+
+ if (memcmp(&fvh->FileSystemGuid, &ffs2_guid, sizeof(ffs2_guid))) {
+ printk(BIOS_ERR, "FVH not an FFS2 type.\n");
+ return NULL;
+ }
+
+ 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 == 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);
+
+ /* 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 NULL;
+ }
+
+ 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 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
new file mode 100644
index 0000000..9fa4ac4
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_util.c
@@ -0,0 +1,252 @@
+/*
+ * 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 <bootstate.h>
+#include <cbmem.h>
+#include <console/console.h>
+#include "fsp_util.h"
+#include <timestamp.h>
+
+/* Locate the FSP binary in the coreboot filesystem */
+FSP_INFO_HEADER *find_fsp(void)
+{
+ 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;
+
+#ifndef CONFIG_FSP_LOC
+#error "CONFIG_FSP_LOC must be set."
+#endif
+
+ for (;;) {
+ /* Get the FSP binary base address in CBFS */
+ fsp_ptr.u8 = (u8 *)CONFIG_FSP_LOC;
+
+ /* Check the FV signature, _FVH */
+ if (fsp_ptr.fvh->Signature != 0x4856465F) {
+ fsp_ptr.u8 = (u8 *)ERROR_NO_FV_SIG;
+ break;
+ }
+
+ /* 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;
+ }
+
+ /* Locate the Raw Section Header */
+ fsp_ptr.u8 += sizeof(EFI_FFS_FILE_HEADER);
+
+ if (fsp_ptr.rs->Type != EFI_SECTION_RAW) {
+ fsp_ptr.u8 = (u8 *)ERROR_NO_INFO_HEADER;
+ break;
+ }
+
+ /* Locate the FSP INFO Header which follows the Raw Header. */
+ fsp_ptr.u8 += sizeof(EFI_RAW_SECTION);
+
+ /* Verify that the FSP base address.*/
+ if (fsp_ptr.fih->ImageBase != CONFIG_FSP_LOC) {
+ fsp_ptr.u8 = (u8 *)ERROR_IMAGEBASE_MISMATCH;
+ break;
+ }
+
+ /* Verify the FSP Signature */
+ if (fsp_ptr.fih->Signature != FSP_SIG) {
+ fsp_ptr.u8 = (u8 *)ERROR_INFO_HEAD_SIG_MISMATCH;
+ break;
+ }
+
+ /* 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;
+ }
+
+ return fsp_ptr.fih;
+}
+
+void print_fsp_info(FSP_INFO_HEADER *fsp_header)
+{
+ 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
+}
+
+#ifndef __PRE_RAM__
+
+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;
+
+ 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");
+ }
+ }
+
+ /* 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;
+
+ timestamp_add_now(phase == EnumInitPhaseReadyToBoot ?
+ TS_FSP_BEFORE_FINALIZE : TS_FSP_BEFORE_ENUMERATE);
+
+ status = notify_phase_proc(¬ify_phase_params);
+
+ 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);
+}
+
+static void fsp_notify_boot_state_callback(void *arg)
+{
+ u32 phase = (u32)arg;
+
+ printk(BIOS_SPEW, "Calling FspNotify(0x%08x)\n", phase);
+ fsp_notify(phase);
+}
+
+BOOT_STATE_INIT_ENTRIES(fsp_bscbs) = {
+ 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)
+};
+
+#endif /* #ifndef __PRE_RAM__ */
+
+struct fsp_runtime {
+ uint32_t fih;
+ uint32_t hob_list;
+} __attribute__((packed));
+
+
+void fsp_set_runtime(FSP_INFO_HEADER *fih, void *hob_list)
+{
+ struct fsp_runtime *fspr;
+
+ fspr = cbmem_add(CBMEM_ID_FSP_RUNTIME, sizeof(*fspr));
+
+ if (fspr == NULL)
+ die("Can't save FSP runtime information.\n");
+
+ fspr->fih = (uintptr_t)fih;
+ fspr->hob_list = (uintptr_t)hob_list;
+}
+
+FSP_INFO_HEADER *fsp_get_fih(void)
+{
+ struct fsp_runtime *fspr;
+
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
+
+ if (fspr == NULL)
+ return NULL;
+
+ return (void *)(uintptr_t)fspr->fih;
+}
+
+void *fsp_get_hob_list(void)
+{
+ struct fsp_runtime *fspr;
+
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
+
+ if (fspr == NULL)
+ return NULL;
+
+ return (void *)(uintptr_t)fspr->hob_list;
+}
+
+void fsp_update_fih(FSP_INFO_HEADER *fih)
+{
+ struct fsp_runtime *fspr;
+
+ fspr = cbmem_find(CBMEM_ID_FSP_RUNTIME);
+
+ if (fspr == NULL)
+ die("Can't update FSP runtime information.\n");
+
+ 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
new file mode 100644
index 0000000..4e65bac
--- /dev/null
+++ b/src/drivers/intel/fsp1_1/fsp_util.h
@@ -0,0 +1,122 @@
+/*
+ * 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
+ * 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 <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>
+
+#if IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)
+int save_mrc_data(void *hob_start);
+void * find_and_set_fastboot_cache(void);
+#endif
+
+/* 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 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
+ * #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);
+
+void update_mrc_cache(void *unused);
+
+#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_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
+
+#endif /* FSP_UTIL_H */
Sol Boucher (solb(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10046
-gerrit
commit d2ac8c57906098fe8e065f01b859d3ad27dcd7f3
Author: Sol Boucher <solb(a)chromium.org>
Date: Thu Apr 30 18:02:08 2015 -0700
haswell: Link stage_cache_external_region into ramstage, too
When CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM is set, this
function is now linked into the ramstage as well as the romstage,
since the former makes calls to it in panther builds.
With this commit, it's possible to build panther using the config file
from the Chromium OS project[1] if you supply the appropriate Intel
descriptor and ME binary blobs and manually set
CONFIG_VBOOT_VERIFY_FIRMWARE=n, CONFIG_BUILD_WITH_FAKE_IFD=n, and
CONFIG_HAVE_ME_BIN=y. The resulting image is at least able to load a
payload, although I only tested with depthcharge, which immediately
complained, "vboot handoff pointer is NULL" and gave up the ghost.
[1] https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/…
Change-Id: Id3bb510fa60129a4d36a0117dc33e7aa62d6c742
Signed-off-by: Sol Boucher <solb(a)chromium.org>
---
src/cpu/intel/haswell/Makefile.inc | 3 +++
src/cpu/intel/haswell/romstage.c | 10 ----------
src/cpu/intel/haswell/stage_cache.c | 30 ++++++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc
index 0db0475..57f9120 100644
--- a/src/cpu/intel/haswell/Makefile.inc
+++ b/src/cpu/intel/haswell/Makefile.inc
@@ -4,9 +4,12 @@ romstage-y += romstage.c
romstage-y += tsc_freq.c
ramstage-y += acpi.c
+ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
ramstage-$(CONFIG_MONOTONIC_TIMER_MSR) += monotonic_timer.c
+romstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
+
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index b8c455b..8e4335f 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -20,7 +20,6 @@
#include <stdint.h>
#include <string.h>
#include <cbfs.h>
-#include <cbmem.h>
#include <console/console.h>
#include <arch/cpu.h>
#include <cpu/x86/bist.h>
@@ -313,15 +312,6 @@ void romstage_after_car(void)
#if IS_ENABLED(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM)
-
-void stage_cache_external_region(void **base, size_t *size)
-{
- /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
- * The top of ram is defined to be the TSEG base address. */
- *size = RESERVED_SMM_SIZE;
- *base = (void *)((uint32_t)cbmem_top() + RESERVED_SMM_OFFSET);
-}
-
void ramstage_cache_invalid(void)
{
#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE
diff --git a/src/cpu/intel/haswell/stage_cache.c b/src/cpu/intel/haswell/stage_cache.c
new file mode 100644
index 0000000..162a244
--- /dev/null
+++ b/src/cpu/intel/haswell/stage_cache.c
@@ -0,0 +1,30 @@
+/*
+ * 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 <cbmem.h>
+#include <stage_cache.h>
+#include "haswell.h"
+
+void stage_cache_external_region(void **base, size_t *size)
+{
+ /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
+ * The top of ram is defined to be the TSEG base address. */
+ *size = RESERVED_SMM_SIZE;
+ *base = (void *)((uint32_t)cbmem_top() + RESERVED_SMM_OFFSET);
+}
Sol Boucher (solb(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10046
-gerrit
commit 431f37dca1d6285edfad91f240c69efa95d73cab
Author: Sol Boucher <solb(a)chromium.org>
Date: Thu Apr 30 18:02:08 2015 -0700
haswell: Link stage_cache_external_region into ramstage, too
When CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM is set, this
function is now linked into the ramstage as well as the romstage,
since the former makes calls to it in panther builds.
With this commit, it's possible to build panther using the config file
from the Chromium OS project[1] if you supply the appropriate Intel
descriptor and ME binary blobs and manually set
CONFIG_VBOOT_VERIFY_FIRMWARE=n, CONFIG_BUILD_WITH_FAKE_IFD=n, and
CONFIG_HAVE_ME_BIN=y. The resulting image is at least able to load a
payload, although I only tested with depthcharge, which immediately
complained, "vboot handoff pointer is NULL" and gave up the ghost.
[1] https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/…
Change-Id: Id3bb510fa60129a4d36a0117dc33e7aa62d6c742
Signed-off-by: Sol Boucher <solb(a)chromium.org>
---
src/cpu/intel/haswell/Makefile.inc | 3 +++
src/cpu/intel/haswell/romstage.c | 10 ----------
src/cpu/intel/haswell/stage_cache.c | 26 ++++++++++++++++++++++++++
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/src/cpu/intel/haswell/Makefile.inc b/src/cpu/intel/haswell/Makefile.inc
index 0db0475..57f9120 100644
--- a/src/cpu/intel/haswell/Makefile.inc
+++ b/src/cpu/intel/haswell/Makefile.inc
@@ -4,9 +4,12 @@ romstage-y += romstage.c
romstage-y += tsc_freq.c
ramstage-y += acpi.c
+ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
ramstage-$(CONFIG_MONOTONIC_TIMER_MSR) += monotonic_timer.c
+romstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
+
cpu_microcode-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE) += microcode_blob.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index b8c455b..8e4335f 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -20,7 +20,6 @@
#include <stdint.h>
#include <string.h>
#include <cbfs.h>
-#include <cbmem.h>
#include <console/console.h>
#include <arch/cpu.h>
#include <cpu/x86/bist.h>
@@ -313,15 +312,6 @@ void romstage_after_car(void)
#if IS_ENABLED(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM)
-
-void stage_cache_external_region(void **base, size_t *size)
-{
- /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
- * The top of ram is defined to be the TSEG base address. */
- *size = RESERVED_SMM_SIZE;
- *base = (void *)((uint32_t)cbmem_top() + RESERVED_SMM_OFFSET);
-}
-
void ramstage_cache_invalid(void)
{
#if CONFIG_RESET_ON_INVALID_RAMSTAGE_CACHE
diff --git a/src/cpu/intel/haswell/stage_cache.c b/src/cpu/intel/haswell/stage_cache.c
new file mode 100644
index 0000000..ee945c7
--- /dev/null
+++ b/src/cpu/intel/haswell/stage_cache.c
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#include <cbmem.h>
+#include <stage_cache.h>
+#include "haswell.h"
+
+void stage_cache_external_region(void **base, size_t *size)
+{
+ /* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
+ * The top of ram is defined to be the TSEG base address. */
+ *size = RESERVED_SMM_SIZE;
+ *base = (void *)((uint32_t)cbmem_top() + RESERVED_SMM_OFFSET);
+}
Sol Boucher (solb(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9967
-gerrit
commit 87c48fb839af538fed90983cb0be2ba9fa5bf178
Author: Sol Boucher <solb(a)chromium.org>
Date: Wed Mar 18 10:13:48 2015 -0700
fmaptool: Add listing of annotated CBFS sections and generate header
The fmd compiler now processes "(CBFS)" annotations, distilling them
into a comma-separated list of the names of sections containing
CBFSes. This list is the only thing printed to standard output to
enable easy capture and machine consumption by other tools.
Additionally, the ability to generate a tiny header with a define for
the primary CBFS's size is implemented and can be requested via a
new command-line switch.
Here's an example of how to use the new features:
$ ./fmaptool -h layout.h layout_arm_8192.fmd layout.fmap 2>/dev/null
FW_MAIN_A,FW_MAIN_B,COREBOOT
The hypothetical fmd file contains three sections annotated as (CBFS),
the names of which are printed to standard output. As before, a binary
FMAP file named layout.fmap is created; however, because the command
was invoked with -h, a header #define ing the offset of its FMAP
section (i.e. where it will be relative to the base of flash once the
boot image is assembled) is also generated.
BUG=chromium:470407
TEST=Verify that fmd files without a "COREBOOT" section or with one
that isn't annotated as "(CBFS)" are not accepted. Ensure that the
list of CBFS sections matches the descriptor file's annotations and
is led by the "COREBOOT" section. Invoke with the header generation
switch and check that output file for reasonableness.
BRANCH=None
Change-Id: I496dd937f69467bfd9233c28df59c7608e89538f
Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Commit-Id: 9227698adecf675770b2983380eb570676c2b5d2
Original-Change-Id: I8b32f6ef19cabe2f6760106e676683c4565bbaad
Original-Signed-off-by: Sol Boucher <solb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/262956
Original-Reviewed-by: Duncan Laurie <dlaurie(a)chromium.org>
Original-Reviewed-by: Julius Werner <jwerner(a)chromium.org>
---
util/cbfstool/Makefile | 3 +-
util/cbfstool/Makefile.inc | 1 +
util/cbfstool/cbfs_sections.c | 122 ++++++++++++++++++++++++++++
util/cbfstool/cbfs_sections.h | 59 ++++++++++++++
util/cbfstool/fmaptool.c | 181 +++++++++++++++++++++++++++++++++++-------
5 files changed, 337 insertions(+), 29 deletions(-)
diff --git a/util/cbfstool/Makefile b/util/cbfstool/Makefile
index abacfaa..e97e7a3 100644
--- a/util/cbfstool/Makefile
+++ b/util/cbfstool/Makefile
@@ -22,7 +22,8 @@ CBFSTOOL_COMMON+=lzma/C/LzFind.o lzma/C/LzmaDec.o lzma/C/LzmaEnc.o
CBFSTOOL_COMMON:=$(addprefix $(obj)/,$(CBFSTOOL_COMMON))
FMAPTOOL_BINARY:=$(obj)/fmaptool
-FMAPTOOL_COMMON:=fmap_from_fmd.o fmd.o fmd_parser.o fmd_scanner.o
+FMAPTOOL_COMMON:=cbfs_sections.o fmap_from_fmd.o
+FMAPTOOL_COMMON+=fmd.o fmd_parser.o fmd_scanner.o
# FMAP
FMAPTOOL_COMMON+=flashmap/fmap.o
FMAPTOOL_COMMON+=flashmap/kv_pair.o flashmap/valstr.o
diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc
index b5eed70..b3377e6 100644
--- a/util/cbfstool/Makefile.inc
+++ b/util/cbfstool/Makefile.inc
@@ -19,6 +19,7 @@ cbfsobj += cbfs-payload-linux.o
fmapobj :=
fmapobj += fmaptool.o
+fmapobj += cbfs_sections.o
fmapobj += fmap_from_fmd.o
fmapobj += fmd.o
fmapobj += fmd_parser.o
diff --git a/util/cbfstool/cbfs_sections.c b/util/cbfstool/cbfs_sections.c
new file mode 100644
index 0000000..81912d5
--- /dev/null
+++ b/util/cbfstool/cbfs_sections.c
@@ -0,0 +1,122 @@
+/*
+ * fmap_sections.c, track which sections of the image will contain CBFSes
+ *
+ * Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include "cbfs_sections.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct descriptor_node {
+ const struct flashmap_descriptor *val;
+ struct descriptor_node *next;
+};
+
+static struct descriptor_list {
+ struct descriptor_node *head;
+ struct descriptor_node *tail;
+} cbfs_sections;
+
+static bool seen_primary_section = false;
+
+static void descriptor_list_prepend(struct descriptor_list *list,
+ struct descriptor_node *new_head)
+{
+ assert(list);
+ assert(new_head);
+
+ new_head->next = list->head;
+ list->head = new_head;
+ if (!list->tail)
+ list->tail = new_head;
+}
+
+static void descriptor_list_append(struct descriptor_list *list,
+ struct descriptor_node *new_tail)
+{
+ assert(list);
+ assert(new_tail);
+
+ if (list->tail)
+ list->tail->next = new_tail;
+ list->tail = new_tail;
+ if (!list->head)
+ list->head = new_tail;
+}
+
+/* Implementation of cbfs module's callback; invoked during fmd file parsing */
+bool fmd_process_annotation_impl(const struct flashmap_descriptor *node,
+ const char *annotation)
+{
+ if (strcmp(annotation, SECTION_ANNOTATION_CBFS) == 0 &&
+ node->list_len == 0) {
+ struct descriptor_node *list_node = malloc(sizeof(*list_node));
+ list_node->val = node;
+ list_node->next = NULL;
+
+ if (strcmp(node->name, SECTION_NAME_PRIMARY_CBFS) == 0) {
+ descriptor_list_prepend(&cbfs_sections, list_node);
+ seen_primary_section = true;
+ } else {
+ descriptor_list_append(&cbfs_sections, list_node);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+cbfs_section_iterator_t cbfs_sections_iterator(void)
+{
+ return cbfs_sections.head;
+}
+
+bool cbfs_sections_iterator_advance(cbfs_section_iterator_t *it)
+{
+ assert(it);
+ if (!*it)
+ return false;
+
+ *it = (*it)->next;
+ return true;
+}
+
+const struct flashmap_descriptor *cbfs_sections_iterator_deref(
+ cbfs_section_iterator_t it)
+{
+ assert(it);
+ return it->val;
+}
+
+bool cbfs_sections_primary_cbfs_accounted_for(void)
+{
+ return seen_primary_section;
+}
+
+void cbfs_sections_cleanup(void)
+{
+ for (struct descriptor_node *cur = cbfs_sections.head, *next = NULL;
+ cur; cur = next) {
+ next = cur->next;
+ free(cur);
+ }
+ cbfs_sections.head = NULL;
+ cbfs_sections.tail = NULL;
+}
diff --git a/util/cbfstool/cbfs_sections.h b/util/cbfstool/cbfs_sections.h
new file mode 100644
index 0000000..5a23899
--- /dev/null
+++ b/util/cbfstool/cbfs_sections.h
@@ -0,0 +1,59 @@
+/*
+ * fmap_sections.h, track which sections of the image will contain CBFSes
+ *
+ * Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef CBFS_SECTIONS_H_
+#define CBFS_SECTIONS_H_
+
+#include "fmd.h"
+
+#include <stdbool.h>
+
+#define SECTION_NAME_FMAP "FMAP"
+#define SECTION_NAME_PRIMARY_CBFS "COREBOOT"
+
+#define SECTION_ANNOTATION_CBFS "CBFS"
+
+typedef const struct descriptor_node *cbfs_section_iterator_t;
+
+/** @return Iterator pointing to first CBFS section, or NULL if none exist */
+cbfs_section_iterator_t cbfs_sections_iterator(void);
+
+/**
+ * Advance iterator to point to the next CBFS section.
+ * If it was already pointing to the last such section, it will be set to NULL.
+ *
+ * @param it (Non-NULL) pointer to (possibly NULL) iterator to be updated
+ * @return Whether it was successfully advanced (wasn't already NULL)
+ */
+bool cbfs_sections_iterator_advance(cbfs_section_iterator_t *it);
+
+/**
+ * @param it Iterator, which must currently be non-NULL
+ * @return Section to which it points
+ */
+const struct flashmap_descriptor *cbfs_sections_iterator_deref(
+ cbfs_section_iterator_t it);
+
+/** @return Whether a section named SECTION_NAME_PRIMARY_CBFS is in the list. */
+bool cbfs_sections_primary_cbfs_accounted_for(void);
+
+/** Reclaim the space used to store knowledge of which sections are CBFSes. */
+void cbfs_sections_cleanup(void);
+
+#endif
diff --git a/util/cbfstool/fmaptool.c b/util/cbfstool/fmaptool.c
index 961e9dc..09b68d2 100644
--- a/util/cbfstool/fmaptool.c
+++ b/util/cbfstool/fmaptool.c
@@ -18,53 +18,149 @@
*/
#include "common.h"
+#include "cbfs_sections.h"
#include "fmap_from_fmd.h"
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#define STDIN_FILENAME_SENTINEL "-"
+#define HEADER_FMAP_OFFSET "FMAP_OFFSET"
+
enum fmaptool_return {
FMAPTOOL_EXIT_SUCCESS = 0,
FMAPTOOL_EXIT_BAD_ARGS,
FMAPTOOL_EXIT_BAD_INPUT_PATH,
FMAPTOOL_EXIT_BAD_OUTPUT_PATH,
FMAPTOOL_EXIT_FAILED_DESCRIPTOR,
+ FMAPTOOL_EXIT_MISSING_FMAP_SECTION,
+ FMAPTOOL_EXIT_MISSING_PRIMARY_CBFS,
FMAPTOOL_EXIT_FAILED_FMAP_CONVERSION,
FMAPTOOL_EXIT_UNKNOWN_FMAP_SIZE,
- FMAPTOOL_EXIT_FAILED_WRITING_FILE,
+ FMAPTOOL_EXIT_FAILED_WRITING_OUTPUT,
+ FMAPTOOL_EXIT_FAILED_WRITING_HEADER,
};
-bool fmd_process_annotation_impl(unused const struct flashmap_descriptor *node,
- unused const char *annotation)
+static void usage(const char *invoked_as)
{
- // We always accept annotations, but never act on them.
+ fputs("fmaptool: Compiler for fmd (flashmap descriptor) files\n",
+ stderr);
+ fputs("\nUSAGE:\n", stderr);
+ fprintf(stderr,
+ "\t%s [-h <header output file>] <fmd input file> <binary output file>\n",
+ invoked_as);
+ fputs("\nMANDATORY ARGUMENTS:\n", stderr);
+ fprintf(stderr,
+ "<fmd input file> may be '%s' to read from standard input\n",
+ STDIN_FILENAME_SENTINEL);
+ fputs("<binary output file> must be a regular file\n", stderr);
+ fputs("\nOPTIONAL SWITCHES:\n", stderr);
+ fprintf(stderr,
+ "-h\tAlso produce a C header defining %s to the FMAP section's flash offset.\n",
+ HEADER_FMAP_OFFSET);
+ fputs("\nOUTPUT:\n", stderr);
+ fputs("A successful invocation prints a summary of work done to standard error, and a comma-separated list\n",
+ stderr);
+ fputs("of those sections that contain CBFSes, starting with the primary such section, to standard output.\n",
+ stderr);
+}
+
+static void list_cbfs_section_names(void)
+{
+ cbfs_section_iterator_t cbfs_it = cbfs_sections_iterator();
+ assert(cbfs_it);
+
+ bool subsequent = false;
+ while (cbfs_it) {
+ const char *cur_name =
+ cbfs_sections_iterator_deref(cbfs_it)->name;
+ if (cbfs_sections_iterator_advance(&cbfs_it) && subsequent)
+ putchar(',');
+ fputs(cur_name, stdout);
+ subsequent = true;
+ }
+ putchar('\n');
+}
+
+static bool write_header(const char *out_fname,
+ const struct flashmap_descriptor *root)
+{
+ assert(out_fname);
+
+ FILE *header = fopen(out_fname, "w");
+ if (!header) {
+ fprintf(stderr, "FATAL: Unable to open file '%s' for writing\n",
+ out_fname);
+ return false;
+ }
+
+ unsigned fmap_offset =
+ fmd_calc_absolute_offset(root, SECTION_NAME_FMAP);
+ assert(fmap_offset != FMD_NOTFOUND);
+
+ fputs("#ifndef FMAPTOOL_GENERATED_HEADER_H_\n", header);
+ fputs("#define FMAPTOOL_GENERATED_HEADER_H_\n\n", header);
+ fprintf(header, "#define %s %#x\n\n", HEADER_FMAP_OFFSET, fmap_offset);
+ fputs("#endif\n", header);
+
+ fclose(header);
return true;
}
+static void full_fmd_cleanup(struct flashmap_descriptor **victim)
+{
+ assert(victim);
+
+ cbfs_sections_cleanup();
+ fmd_cleanup(*victim);
+ *victim = NULL;
+}
+
int main(int argc, char **argv)
{
- if (argc != 3) {
- fputs("Convert a human-readable flashmap descriptor (fmd) file into the binary FMAP format for use in firmware images\n",
- stderr);
- fprintf(stderr,
- "USAGE: %s <fmd input file> <binary output file>\n",
- argv[0]);
- fprintf(stderr,
- "To read from standard input, provide '%s' as the input filename.\n",
- STDIN_FILENAME_SENTINEL);
+ struct {
+ // Mandatory
+ const char *fmd_filename;
+ const char *fmap_filename;
+
+ // Optional
+ const char *header_filename;
+ } args = {NULL, NULL, NULL};
+
+ bool show_usage = false;
+ int each_arg;
+ while (!show_usage && (each_arg = getopt(argc, argv, ":h:")) != -1) {
+ switch (each_arg) {
+ case 'h':
+ args.header_filename = optarg;
+ break;
+ case ':':
+ fprintf(stderr, "-%c: Expected an accompanying value\n",
+ optopt);
+ show_usage = true;
+ break;
+ default:
+ fprintf(stderr, "-%c: Unexpected command-line switch\n",
+ optopt);
+ show_usage = true;
+ }
+ }
+
+ if (show_usage || argc - optind != 2) {
+ usage(argv[0]);
return FMAPTOOL_EXIT_BAD_ARGS;
}
- const char *fmd_filename = argv[1];
- const char *fmap_filename = argv[2];
+ args.fmd_filename = argv[optind];
+ args.fmap_filename = argv[optind + 1];
FILE *fmd_file = stdin;
- if (strcmp(fmd_filename, STDIN_FILENAME_SENTINEL) != 0) {
- fmd_file = fopen(fmd_filename, "r");
+ if (strcmp(args.fmd_filename, STDIN_FILENAME_SENTINEL) != 0) {
+ fmd_file = fopen(args.fmd_filename, "r");
if (!fmd_file) {
fprintf(stderr, "FATAL: Unable to open file '%s'\n",
- fmd_filename);
+ args.fmd_filename);
return FMAPTOOL_EXIT_BAD_INPUT_PATH;
}
}
@@ -74,14 +170,32 @@ int main(int argc, char **argv)
if (!descriptor) {
fputs("FATAL: Failed while processing provided descriptor\n",
stderr);
+ full_fmd_cleanup(&descriptor);
return FMAPTOOL_EXIT_FAILED_DESCRIPTOR;
}
+ if (!fmd_find_node(descriptor, SECTION_NAME_FMAP)) {
+ fprintf(stderr,
+ "FATAL: Flashmap descriptor must have an '%s' section\n",
+ SECTION_NAME_FMAP);
+ full_fmd_cleanup(&descriptor);
+ return FMAPTOOL_EXIT_MISSING_FMAP_SECTION;
+ }
+
+ if (!cbfs_sections_primary_cbfs_accounted_for()) {
+ fprintf(stderr,
+ "FATAL: Flashmap descriptor must have a '%s' section that is annotated with '(%s)'\n",
+ SECTION_NAME_PRIMARY_CBFS,
+ SECTION_ANNOTATION_CBFS);
+ full_fmd_cleanup(&descriptor);
+ return FMAPTOOL_EXIT_MISSING_PRIMARY_CBFS;
+ }
+
struct fmap *flashmap = fmap_from_fmd(descriptor);
if (!flashmap) {
fputs("FATAL: Failed while constructing FMAP section\n",
stderr);
- fmd_cleanup(descriptor);
+ full_fmd_cleanup(&descriptor);
return FMAPTOOL_EXIT_FAILED_FMAP_CONVERSION;
}
@@ -90,16 +204,16 @@ int main(int argc, char **argv)
fputs("FATAL: Failed to determine FMAP section size\n",
stderr);
fmap_destroy(flashmap);
- fmd_cleanup(descriptor);
+ full_fmd_cleanup(&descriptor);
return FMAPTOOL_EXIT_UNKNOWN_FMAP_SIZE;
}
- FILE *fmap_file = fopen(fmap_filename, "wb");
+ FILE *fmap_file = fopen(args.fmap_filename, "wb");
if (!fmap_file) {
fprintf(stderr, "FATAL: Unable to open file '%s' for writing\n",
- fmap_filename);
+ args.fmap_filename);
fmap_destroy(flashmap);
- fmd_cleanup(descriptor);
+ full_fmd_cleanup(&descriptor);
return FMAPTOOL_EXIT_BAD_OUTPUT_PATH;
}
@@ -107,13 +221,24 @@ int main(int argc, char **argv)
fputs("FATAL: Failed to write final FMAP to file\n", stderr);
fclose(fmap_file);
fmap_destroy(flashmap);
- fmd_cleanup(descriptor);
- return FMAPTOOL_EXIT_FAILED_WRITING_FILE;
+ full_fmd_cleanup(&descriptor);
+ return FMAPTOOL_EXIT_FAILED_WRITING_OUTPUT;
}
fclose(fmap_file);
- printf("SUCCESS: Wrote %d bytes to file '%s'\n", size, fmap_filename);
-
fmap_destroy(flashmap);
- fmd_cleanup(descriptor);
+
+ if (args.header_filename &&
+ !write_header(args.header_filename, descriptor)) {
+ full_fmd_cleanup(&descriptor);
+ return FMAPTOOL_EXIT_FAILED_WRITING_HEADER;
+ }
+
+ fprintf(stderr, "SUCCESS: Wrote %d bytes to file '%s'%s\n", size,
+ args.fmap_filename,
+ args.header_filename ? " (and generated header)" : "");
+ fputs("The sections containing CBFSes are: ", stderr);
+ list_cbfs_section_names();
+
+ full_fmd_cleanup(&descriptor);
return FMAPTOOL_EXIT_SUCCESS;
}
the following patch was just integrated into master:
commit b738913ce050cd5a61d902e7024d4881cdb1ae59
Author: Dave Frodin <dave.frodin(a)se-eng.com>
Date: Fri May 1 09:17:43 2015 -0600
northbridge/intel/fsp_rangeley: Correct MMIO size setting
The Rangeley chipset has the MMIO PCI config space feature
enabled at 0xe0000000-0xefffffff. This is a 256MB space
which covers all of config space. The ACPI table for
this space only defines it as being 64MB. This change
fixes that setting.
Change-Id: I8205a9b89ea6633ac6c4b0d5a282cd2745595b2e
Signed-off-by: Dave Frodin <dave.frodin(a)se-eng.com>
Reviewed-on: http://review.coreboot.org/10047
Reviewed-by: Marc Jones <marc.jones(a)se-eng.com>
Tested-by: build bot (Jenkins)
See http://review.coreboot.org/10047 for details.
-gerrit
the following patch was just integrated into master:
commit 2eaa0d49e10e9c2314b0f61400a481447d1df892
Author: Dave Frodin <dave.frodin(a)se-eng.com>
Date: Thu Apr 23 06:04:46 2015 -0600
intel: Correct MMIO related ACPI table settings
Several of the intel platforms define the region reserved
for PCI memory resources in a location where it overlaps
with the MMIO (MCFG) region.
Using the memory map from mohon_peak as an example:
0. 0000000000000000-0000000000000fff: CONFIGURATION TABLES
1. 0000000000001000-000000000009ffff: RAM
2. 00000000000a0000-00000000000fffff: RESERVED
3. 0000000000100000-000000007fbcffff: RAM
4. 000000007fbd0000-000000007fbfffff: CONFIGURATION TABLES
5. 000000007fc00000-000000007fdfffff: RESERVED
6. 00000000e0000000-00000000efffffff: RESERVED
7. 00000000fee00000-00000000fee00fff: RESERVED
8. 0000000100000000-000000017fffffff: RAM
The ACPI table describing the space set aside for PCI memory
(not to be confused with the MMIO config space) is defined
as the region from BMBOUND (the top of DRAM below 4GB) to
a hardcoded value of 0xfebfffff. That region would overlap
the MMIO region at 0xe0000000-0xefffffff. For rangeley
the upper bound of the PCI memory space should be set
to 0xe0000000 - 1.
The MCFG regions for several of the affected chipsets are:
rangeley 0xe0000000-0xefffffff
baytrail 0xe0000000-0xefffffff
haswell 0xf0000000-0xf3ffffff
sandybridge 0xf8000000-0xfbffffff
TEST = intel/mohonpeak and intel/bayleybay.
Change-Id: Ic188a4f575494f04930dea4d0aaaeaad95df9f90
Signed-off-by: Dave Frodin <dave.frodin(a)se-eng.com>
Reviewed-on: http://review.coreboot.org/9972
Reviewed-by: Marc Jones <marc.jones(a)se-eng.com>
Tested-by: build bot (Jenkins)
See http://review.coreboot.org/9972 for details.
-gerrit