diff --git a/.gitmodules b/.gitmodules
index 2c46a8738e..40600810a6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -46,3 +46,8 @@
path = 3rdparty/cmocka
url = https://review.coreboot.org/cmocka.git
update = none
+[submodule "3rdparty/qc_blobs"]
+ path = 3rdparty/qc_blobs
+ url = ../qc_blobs.git
+ update = none
+ ignore = dirty
diff --git a/3rdparty/amd_blobs b/3rdparty/amd_blobs
index 0ac1af437d..1ac6d42bf3 160000
--- a/3rdparty/amd_blobs
+++ b/3rdparty/amd_blobs
@@ -1 +1 @@
-Subproject commit 0ac1af437d2cc461b94bd2cdaa195e86dd481d37
+Subproject commit 1ac6d42bf336af639ae849933cbb818e51b1ffd1
diff --git a/3rdparty/blobs b/3rdparty/blobs
index 7ad2d22452..bbe5d99780 160000
--- a/3rdparty/blobs
+++ b/3rdparty/blobs
@@ -1 +1 @@
-Subproject commit 7ad2d22452225a14c19b17570cb77920d8fc81a5
+Subproject commit bbe5d99780d2d085e92d9bae2c0f7b6787419d72
diff --git a/3rdparty/libgfxinit b/3rdparty/libgfxinit
index 8fc8e49a93..3318bf2680 160000
--- a/3rdparty/libgfxinit
+++ b/3rdparty/libgfxinit
@@ -1 +1 @@
-Subproject commit 8fc8e49a932c7a011429b333765c6b0ed09cd742
+Subproject commit 3318bf26803c77d41b18bef6d7ae4e051b97f9f2
diff --git a/3rdparty/libhwbase b/3rdparty/libhwbase
index bd0ed91cb9..a3edc6ef32 160000
--- a/3rdparty/libhwbase
+++ b/3rdparty/libhwbase
@@ -1 +1 @@
-Subproject commit bd0ed91cb985a697033edd9fd62d322aa017e791
+Subproject commit a3edc6ef32d09c566b7ea3555bc753458ec63039
diff --git a/3rdparty/qc_blobs b/3rdparty/qc_blobs
new file mode 160000
index 0000000000..126fef6b99
--- /dev/null
+++ b/3rdparty/qc_blobs
@@ -0,0 +1 @@
+Subproject commit 126fef6b996237403039aa603945fc4caa75c8d6
diff --git a/3rdparty/vboot b/3rdparty/vboot
index c531000f85..68de90c7e2 160000
--- a/3rdparty/vboot
+++ b/3rdparty/vboot
@@ -1 +1 @@
-Subproject commit c531000f851418520b6873f65c202d21f141eb84
+Subproject commit 68de90c7e2f4a27d3a76489199176d2ab8f56de1
diff --git a/Documentation/Intel/Board/board.html b/Documentation/Intel/Board/board.html
index 4ba51df401..0d4631ad51 100644
--- a/Documentation/Intel/Board/board.html
+++ b/Documentation/Intel/Board/board.html
@@ -222,7 +222,7 @@
Add the acpi_create_fadt routine
- fill in the ACPI header
- - Call the acpi_fill_in_fadt routine
+ - Call the acpi_fill_fadt routine
diff --git a/Documentation/Intel/SoC/soc.html b/Documentation/Intel/SoC/soc.html
index 53131c6e6f..8d565d52fe 100644
--- a/Documentation/Intel/SoC/soc.html
+++ b/Documentation/Intel/SoC/soc.html
@@ -667,7 +667,7 @@ Use the following steps to debug the call to TempRamInit:
Create a acpi.c module:
- - Add the acpi_fill_in_fadt routine and initialize the values above
+ - Add the acpi_fill_fadt routine and initialize the values above
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx
index caa8190a32..6930130cb5 100644
--- a/Documentation/Makefile.sphinx
+++ b/Documentation/Makefile.sphinx
@@ -2,7 +2,7 @@
#
# You can set these variables from the command line.
-SPHINXOPTS =
+SPHINXOPTS ?=
SPHINXBUILD = sphinx-build
SPHINXAUTOBUILD = sphinx-autobuild
PAPER =
diff --git a/Documentation/arch/x86/index.md b/Documentation/arch/x86/index.md
index 462e7e6c6e..f5546d18d5 100644
--- a/Documentation/arch/x86/index.md
+++ b/Documentation/arch/x86/index.md
@@ -42,13 +42,23 @@ At the moment *$n* is 4, which results in identity mapping the lower 4 GiB.
* Fix compilation errors - *DONE*
* Fix linker errors - *TODO*
* Add x86_64 rmodule support - *DONE*
-* Add x86_64 exception handlers - *TODO*
+* Add x86_64 exception handlers - *DONE*
* Setup page tables for long mode - *DONE*
* Add assembly code for long mode - *DONE*
+* Add assembly code for SMM - *DONE*
* Add assembly code for postcar stage - *TODO*
* Add assembly code to return to protected mode - *TODO*
* Implement reference code for mainboard `emulation/qemu-q35` - *TODO*
+## Future work
+
+1. Fine grained page tables for SMM:
+ * Must not have execute and write permissions for the same page.
+ * Must allow only that TSEG pages can be marked executable
+ * Must reside in SMRAM
+2. Support 64bit PCI BARs above 4GiB
+3. Place and run code above 4GiB
+
## Porting other boards
* Fix compilation errors
* Test how well CAR works with x86_64 and paging
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 8848ee6512..f82fa0e182 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -1,6 +1,18 @@
# -*- coding: utf-8 -*-
import subprocess
from recommonmark.parser import CommonMarkParser
+import sphinx
+
+# Get Sphinx version
+major = 0
+minor = 0
+patchlevel = 0
+version = sphinx.__version__.split(".")
+if len(version) > 1:
+ major = int(version[0])
+ minor = int(version[1])
+ if len(version) > 2:
+ patchlevel = int(version[2])
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -25,7 +37,18 @@ release = subprocess.check_output(('git', 'describe')).decode("utf-8")
# The short X.Y version.
version = release.split("-")[0]
-extensions = ['sphinxcontrib.ditaa']
+extensions = []
+# Load recommonmark, supported since 1.8+
+if major >= 2 or (major == 1 and minor >= 8):
+ extensions += ['recommonmark']
+
+# Try to load DITAA
+try:
+ import sphinxcontrib.ditaa
+except ImportError:
+ print("Error: Please install sphinxcontrib.ditaa for ASCII art conversion\n")
+else:
+ extensions += 'sphinxcontrib.ditaa'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -187,7 +210,9 @@ class MyCommonMarkParser(CommonMarkParser):
def setup(app):
from recommonmark.transform import AutoStructify
- app.add_source_parser('.md', MyCommonMarkParser)
+ # Load recommonmark on old Sphinx
+ if major == 1 and minor < 8:
+ app.add_source_parser('.md', MyCommonMarkParser)
app.add_config_value('recommonmark_config', {
'enable_auto_toc_tree': True,
diff --git a/Documentation/drivers/dptf.md b/Documentation/drivers/dptf.md
new file mode 100644
index 0000000000..327d6865b2
--- /dev/null
+++ b/Documentation/drivers/dptf.md
@@ -0,0 +1,313 @@
+# Intel DPTF implementations in coreboot
+
+## Introduction
+
+Intel Dynamic Platform and Thermal Framework is a framework that can be used to
+help regulate the thermal properties (i.e., temperature) of an Intel-based
+computer. It does this by allowing the system designer to specify the different
+components that can generate heat, and/or dissipate heat. Under DPTF, the
+different components are referred to as `participants`. The different types of
+functionality available in DPTF are specified in terms of different `policies`.
+
+## Components ("Participants")
+
+The participants that can be involved in the current implementation are:
+- CPU (monolithic from a DPTF point-of-view)
+ - Note that the CPU's internal temperature sensor is used here
+- 1 fan
+- Up to 4 temperature sensors (TSRs)
+- Battery charger
+
+## Policies
+
+In the current implementation, there are 3 different policies available:
+
+### Passive Policy
+
+The purpose of this policy is to monitor participant temperatures and is capable
+of controlling performance and throttling available on platform devices in order
+to regulate the temperatures of each participant. The temperature threshold
+points are defined by a `_PSV` ACPI object within each participant.
+
+### Critical Policy
+
+The Critical Policy is used for gracefully suspending or powering off the system
+when the temperature of participants exceeds critical threshold
+temperatures. Suspend is effected by specifying temperatures in a `_CRT` object
+for a participant, and poweroff is effected by specifying a temperature
+threshold in a `_HOT` ACPI object.
+
+### Active Policy
+
+This policy monitors the temperature of participants and controls fans to spin
+at varying speeds. These speeds are defined by the platform, and will be enabled
+depending on the various temperatures reported by participants.
+
+# Note about units
+
+ACPI uses unusual units for specifying various physical measurements. For
+example, temperatures are specified in 10ths of a degree K, and time is measured
+in tenths of a second. Those oddities are abstracted away in the DPTF library,
+by using degrees C for temperature, milliseconds for time, mW for power, and mA
+for current.
+
+## Differences from the static ASL files (soc/intel/common/acpi/dptf/*.asl)
+
+1) TCPU had many redundant methods. The many references to \_SB.CP00._* are not
+created anymore in recent SoCs and the ACPI spec says these are optional objects
+anyway. The defaults that were returned by these methods were redundant (all
+data was a 0). The following Methods were removed:
+
+* _TSS
+* _TPC
+* _PTC
+* _TSD
+* _TDL
+* _PSS
+* _PDL
+
+2) There is no more implicit inclusion of _ACn methods for TCPU (these must be
+ specified in the devicetree entries or by calling the DPTF acpigen API).
+
+# ACPI Tables
+
+DPTF relies on an assortment of ACPI tables to provide parameters to the DPTF
+application. We will discuss the more important ones here.
+
+1) _TRT - Thermal Relationship Table
+
+This table is used when the Passive Policy is enabled, and is used to represent
+the thermal relationships in the system that can be controlled passively (i.e.,
+by throttling participants). A passive policy is defined by a Source (which
+generates heat), a Target (typically a temperature sensor), a Sampling Period
+(how often to check the temperature), an activation temperature threshold (for
+when to begin throttling), and a relative priority.
+
+2) _ART - Active Relationship Table
+
+This table is used when the Active Policy is enabled, and is used to represent
+active cooling relationships (i.e., which TSRs the fan can cool). An active
+policy contains a Target (the device the fan can cool), a Weight to control
+which participant needs more attention than others, and a list of temperature /
+fan percentage pairs. The list of pairs defines the fan control percentage that
+should be applied when the TSR reaches each successive threshold (_AC0 is the
+highest threshold, and represents the highest fan control percentage).
+
+3) PPCC - Participant Power Control Capabilities
+
+This table is used to describe parameters for controlling the SoC's Running
+Average Power Limits (RAPL, see below).
+
+4) _FPS - Fan Performance States
+
+This table describes the various fan speeds available for DPTF to use, along with
+various informational properties.
+
+5) PPSS - Participant Performance Supported States
+
+This table describes performance states supported by a participant (typically
+the battery charger).
+
+# ACPI Methods
+
+The Active and Passive policies also provide for short Methods to define
+different kinds of temperature thresholds.
+
+1) _AC0, _AC1, _AC2, _AC3, ..., _AC9
+
+These Methods can provide up to 10 temperature thresholds. What these do is set
+temperatures which act as the thresholds to active rows (fan speeds) in the
+ART. _AC0 is intended to be the highest temperature thresholds, and the lowest
+one can be any of them; leave the rest defined as 0 and they will be omitted
+from the output.
+
+These are optional and are enabled by selecting the Active Policy.
+
+2) _PSV
+
+_PSV is a temperature threshold that is used to indicate to DPTF that it should
+begin taking passive measures (i.e., throttling of the Source) in order to
+reduce the temperature of the Target in question. It will check on the
+temperature according to the given sampling period.
+
+This is optional and is enabled by selecting the Passive Policy.
+
+3) _CRT and _HOT
+
+When the temperature of the Source reaches the threshold specified in _CRT, then
+the system is supposed to execute a "graceful suspend". Similarly, when the Source
+reaches the temperature specified in _HOT, then the system is supposed to execute
+a "graceful shutdown".
+
+These are optional, and are enabled by selecting the Critical Policy.
+
+# How to use the devicetree entries
+
+The `drivers/intel/dptf` chip driver is organized into several sections:
+- Policies
+- Controls
+- Options
+
+The Policies section (`policies.active`, `policies.passive`, and
+`policies.critical`) is where the components of each policy are defined.
+
+## Active Policy
+
+Each Active Policy is defined in terms of 4 parts:
+1) A Source (this is implicitly defined as TFN1, the system fan)
+2) A Target (this is the device that can be affected by the policy, i.e.,
+ this is a device that can be cooled by the fan)
+3) A 'Weight', which is defined as the Source's contribution to the Target's
+ cooling capability (as a percentage, 0-100, often just left at 100).
+4) A list of temperature-fan percentage pairs, which define temperature
+ thresholds that, when the Target reaches, the fan is defined to spin
+ at the corresponding percentage of full duty cycle.
+
+An example definition in the devicetree:
+```C
+register "policies.active[0]" = "{
+ .target=DPTF_CPU,
+ .weight=100,
+ .thresholds={TEMP_PCT(85, 90),
+ TEMP_PCT(80, 69),
+ TEMP_PCT(75, 56),
+ TEMP_PCT(70, 46),
+ TEMP_PCT(65, 36),}}"
+```
+
+This example sets up a policy wherein the CPU temperature sensor can be cooled
+by the fan. The 'weight' of this policy is 100% (this policy contributes 100% of
+the CPU's active cooling capability). When the CPU temperature first crosses
+65C, the fan is defined to spin at 36% of its duty cycle, and so forth up the
+rest of the table (note that it *must* be defined from highest temperature/
+percentage on down to the lowest).
+
+## Passive Policy
+
+Each Passive Policy is defined in terms of 5 parts:
+1) Source - The device that can be throttled
+2) Target - The device that controls the amount of throttling
+3) Period - How often to check the temperature of the Target
+4) Trip point - What temperature threshold to start throttling
+5) Priority - A number indicating the relative priority between different
+ Policies
+
+An example definition in the devicetree:
+```C
+register "policies.passive[0]" = "DPTF_PASSIVE(CHARGER, TEMP_SENSOR_1, 65, 60000)"
+```
+
+This example sets up a policy to begin throttling the charger performance when
+temperature sensor 1 reaches 65C. The sampling period here is 60000 ms (60 s).
+The Priority is defaulted to 100 in this case.
+
+## Critical Policy
+
+Each Critical Policy is defined in terms of 3 parts:
+1) Source - A device that can trigger a critical event
+2) Type - What type of critical event to trigger (S4-entry or shutdown)
+3) Temperature - The temperature threshold that will cause the entry into S4 or
+ to shutdown the system.
+
+An example definition in the devicetree:
+
+```C
+register "policies.critical[1]" = "DPTF_CRITICAL(CPU, 75, SHUTDOWN)"
+```
+
+This example sets up a policy wherein ACPI will cause the system to shutdown
+(in a "graceful" manner) when the CPU temperature reaches 75C.
+
+## Power Limits
+
+Control over the SoC's Running Average Power Limits (RAPL) is one of the tools
+that DPTF uses to enact Passive policies. DPTF can control both PL1 and PL2, if
+the PPCC table is provided for the TCPU object. Each power limit is given the
+following options:
+1) Minimum power (in mW)
+2) Maximum power (in mW)
+3) Minimum time window (in ms)
+4) Maximum time window (in ms)
+5) Granularity, or minimum step size to control limits (in mW)
+
+An example:
+```C
+register "controls.power_limits.pl1" = "{
+ .min_power = 3000,
+ .max_power = 15000,
+ .time_window_min = 28 * MSECS_PER_SEC,
+ .time_window_max = 32 * MSECS_PER_SEC,
+ .granularity = 200,}"
+```
+
+This example allow DPTF to control the SoC's PL1 level to between 3W and 15W,
+over a time interval ranging from 28 to 32 seconds, and it can move PL1 in
+increments of 200 mW.
+
+## Charger Performance
+
+The battery charger can be a large contributor of unwanted heat in a system that
+has one. Controlling the rate of charging is another tool that DPTF uses to enact
+Passive Policies. Each entry in the PPSS table consists of:
+1) A 'Control' value - an opaque value that the platform firmware uses
+ to initiate a transition to the specified performance state. DPTF will call an
+ ACPI method called `TCHG.SPPC` (Set Participant Performance Capability) if
+ applicable, and will pass this opaque control value as its argument.
+2) The intended charging rate (in mA).
+
+Example:
+```C
+register "controls.charger_perf[0]" = "{ 255, 1700 }"
+register "controls.charger_perf[1]" = "{ 24, 1500 }"
+register "controls.charger_perf[2]" = "{ 16, 1000 }"
+register "controls.charger_perf[3]" = "{ 8, 500 }"
+```
+
+In this example, when DPTF decides to throttle the charger, it has four different
+performance states to choose from.
+
+## Fan Performance
+
+When using DPTF, the system fan (`TFN1`) is the device responsible for actively
+cooling the other temperature sensors on the mainboard. A fan speed table can be
+provided to DPTF to assist with fan control. Each entry holds the following:
+1) Percentage of full duty to spin the fan at
+2) Speed - Speed of the fan at that percentage; informational only, but given in
+ RPM
+3) Noise - Amount of noise created by the fan at that percentage; informational
+ only, but given in tenths of a decibel (centibel).
+4) Power - Amount of power consumed by the fan at that percentage; informational
+ only, but given in mA.
+
+Example:
+```C
+register "controls.fan_perf[0]" = "{ 90, 6700, 220, 2200, }"
+register "controls.fan_perf[1]" = "{ 80, 5800, 180, 1800, }"
+register "controls.fan_perf[2]" = "{ 70, 5000, 145, 1450, }"
+register "controls.fan_perf[3]" = "{ 60, 4900, 115, 1150, }"
+register "controls.fan_perf[4]" = "{ 50, 3838, 90, 900, }"
+register "controls.fan_perf[5]" = "{ 40, 2904, 55, 550, }"
+register "controls.fan_perf[6]" = "{ 30, 2337, 30, 300, }"
+register "controls.fan_perf[7]" = "{ 20, 1608, 15, 150, }"
+register "controls.fan_perf[8]" = "{ 10, 800, 10, 100, }"
+register "controls.fan_perf[9]" = "{ 0, 0, 0, 50, }"
+```
+
+In this example, the fan has 10 different performance states, each in an even
+increment of 10 percentage points. This is common when specifying fine-grained
+control of the fan, wherein DPTF will interpolate between the percentages in the
+table for a given temperature threshold.
+
+## Options
+
+### Fan
+1) Fine-grained control - a boolean (see Fan Performance section above)
+2) Step-size - Recommended minimum step size (in percentage points) to adjust
+ the fan speed when using fine-grained control (ranges from 1 - 9).
+3) Low-speed notify - If true, the platform will issue a `Notify (0x80)` to the
+ fan device if a low fan speed is detected.
+
+### Temperature sensors
+1) Hysteresis - The amount of hysteresis implemented in either circuitry or
+ the firmware that reads the temperature sensor (in degrees C).
+2) Name - This name is applied to the _STR property of the sensor
diff --git a/Documentation/drivers/smmstore.md b/Documentation/drivers/smmstore.md
index 53bac4dc9e..70827477df 100644
--- a/Documentation/drivers/smmstore.md
+++ b/Documentation/drivers/smmstore.md
@@ -5,7 +5,7 @@ storage driver.
## SMMSTORE
-SMMSTORE is a SMM mediated driver to read from, write to and erase a
+SMMSTORE is a [SMM] mediated driver to read from, write to and erase a
predefined region in flash. It can be enabled by setting
`CONFIG_SMMSTORE=y` in menuconfig.
@@ -117,7 +117,18 @@ INPUT:
- `val`: pointer to the value data
- `valsize`: size of the value data
+#### Security
+
+Pointers provided by the payload or OS are checked to not overlap with the SMM.
+That protects the SMM handler from being manipulated.
+
+*However there's no validation done on the source or destination pointing to
+DRAM. A malicious application that is able to issue SMIs could extract arbitrary
+data or modify the currently running kernel.*
+
## External links
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDKI](https://software.intel.com/sites/default/files/managed/cf/ea/a_tour_beyond_bios_implementing_uefi_authenticated_variables_in_smm_with_edkii.pdf)
Note, this differs significantly from coreboot's implementation.
+
+[SMM]: ../security/smm.md
diff --git a/Documentation/lib/fw_config.md b/Documentation/lib/fw_config.md
new file mode 100644
index 0000000000..63a56dcd7b
--- /dev/null
+++ b/Documentation/lib/fw_config.md
@@ -0,0 +1,353 @@
+# Firmware Configuration Interface in coreboot
+
+## Motivation
+
+The firmware configuration interface in coreboot is designed to support a wide variety of
+configuration options in that are dictated by the hardware at runtime. This allows a single
+BIOS image to be used across a wide variety of devices which may have key differences but are
+otherwise similar enough to use the same coreboot build target.
+
+The initial implementation is designed to take advantage of a bitmask returned by the Embedded
+Controller on Google Chrome OS devices which allows the manufacturer to use the same firmware
+image across multiple devices by selecting various options at runtime. See the Chromium OS
+[Firmware Config][1] documentation for more information.
+
+This firmware configuration interface differs from the CMOS option interface in that this
+bitmask value is not intended as a user-configurable setting as the configuration values must
+match the actual hardware. In the case where a user was to swap their hardware this value
+would need to be updated or overridden.
+
+## Device Presence
+
+One common example of why a firmware configuration interface is important is determining if a
+device is present in the system. With some bus topologies and hardware mechanisms it is
+possible to probe and enumerate this at runtime:
+
+- PCI is a self-discoverable bus and is very easy to handle.
+- I2C devices can often be probed with a combination of bus and address.
+- The use of GPIOs with external strap to ground or different voltages can be used to detect
+presence of a device.
+
+However there are several cases where this is insufficient:
+
+- I2C peripherals that require different drivers but have the same bus address cannot be
+uniquely identified at runtime.
+- A mainboard may be designed with multiple daughter board combinations which contain devices
+and configurations that cannot be detected.
+- While presence detect GPIOs are a convenient way for a single device presence, they are
+unable to distinguish between different devices so it can require a large number of GPIOs to
+support relatively few options.
+
+This presence detection can impact different stages of boot:
+
+### ACPI
+
+Devices that are not present should not provide an ACPI device indicating that they are
+present or the operating system may not be able to handle it correctly.
+
+The ACPI devices are largely driven by chips defined in the mainboard `devicetree.cb` and
+the variant overridetree.cb. This means it is important to be able to specify when a device
+is present or not directly in `devicetree.cb` itself. Otherwise each mainboard needs custom
+code to parse the tree and disable unused devices.
+
+### GPIO
+
+GPIOs with multiple functions may need to be configured correctly depending on the attached
+device. Given the wide variety of GPIO configuration possibilities it is not feasible to
+specify all combinations directly in `devicetree.cb` and it is best left to code provided by
+the mainboard.
+
+### FSP UPD
+
+Enabling and disabling devices may require altering FSP UPD values that are provided to the
+various stages of FSP. These options are also not easy to specify multiple times for
+different configurations in `devicetree.cb` and can be provided by the mainboard as code.
+
+## Firmware Configuration Interface
+
+The firmware configuration interface can be enabled by selecting `CONFIG_FW_CONFIG` and also
+providing a source for the value by defining an additional Kconfig option defined below.
+
+If the firmware configuration interface is disabled via Kconfig then all probe attempts will
+return true.
+
+## Firmware Configuration Value
+
+The 32bit value used as the firmware configuration bitmask is meant to be determined at runtime
+but could also be defined at compile time if needed.
+
+There are two supported sources for providing this information to coreboot.
+
+### CBFS
+
+The value can be provided with a 32bit raw value in CBFS that is read by coreboot. The value
+can be set at build time but also adjusted in an existing image with `cbfstool`.
+
+To enable this select the `CONFIG_FW_CONFIG_CBFS` option in the build configuration and add a
+raw 32bit value to CBFS with the name of the current prefix at `CONFIG_FW_PREFIX/fw_config`.
+
+When `fw_config_probe_device()` or `fw_config_probe()` is called it will look for the specified
+file in CBFS use the value it contains when matching fields and options.
+
+### Embedded Controller
+
+Google Chrome OS devices support an Embedded Controller interface for reading and writing the
+firmware configuration value, along with other board-specific information. It is possible for
+coreboot to read this value at boot on systems that support this feature.
+
+This option is selected by default for the mainboards that use it with
+`CONFIG_FW_CONFIG_CHROME_EC_CBI` and it is not typically necessary to adjust the value. It is
+possible by enabling the CBFS source and coreboot will look in CBFS first for a valid value
+before asking the embedded controller.
+
+It is also possible to adjust the value in the embedded controller *(after disabling write
+protection)* with the `ectool` command in a Chrome OS environment.
+
+For more information on the firmware configuration field on Chrome OS devices see the Chromium
+documentation for [Firmware Config][1] and [Board Info][2].
+
+[1]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/firmware_config.md
+[2]: http://chromium.googlesource.com/chromiumos/docs/+/master/design_docs/cros_board_info.md
+
+## Firmware Configuration Table
+
+The firmware configuration table itself is defined in the mainboard `devicetree.cb` with
+special tokens for defining fields and options.
+
+The table itself is enclosed in a `fw_config` token and terminated with `end` and it contains
+a mix of field and option definitions.
+
+Each field is defined by providing the field name and the start and end bit marking the exact
+location in the bitmask. Field names must be at least three characters long in order to
+satisfy the sconfig parser requirements and they must be unique with non-overlapping masks.
+
+ field [option...] end
+
+For single-bit fields only one number is needed:
+
+ field [option...] end
+
+Each `field` definition starts a new block that can be composed of zero or more field options,
+and it is terminated with `end`.
+
+Inside the field block the options can be defined by providing the option name and the field
+value that this option represents when the bit offsets are used to apply a mask and shift.
+Option names must also be at least three characters for the sconfig parser.
+
+ option
+
+It is possible for there to be multiple `fw_config` blocks and for subsequent `field` blocks
+to add additional `option` definitions to the existing field. These subsequent definitions
+should not provide the field bitmask as it has already been defined earlier in the file and
+this is just matching an existing field by name.
+
+ field [option...] end
+
+This allows a baseboard to define the major fields and options in `devicetree.cb` and a board
+variant to add specific options to fields in or define new fields in the unused bitmask in
+`overridetree.cb`.
+
+It is not possible to redefine a field mask or override the value of an existing option this
+way, only to add new options to a field or new fields to the table.
+
+### Firmware Configuration Table Example
+
+In this example a baseboard defines a simple boolean feature that is enabled or disabled
+depending on the value of bit 0, and a field at bits 1-2 that indicates which daughter board
+is attached.
+
+The baseboard itself defines one daughter board and the variant adds two more possibilities.
+This way each variant can support multiple possible daughter boards in addition to the one
+that was defined by the baseboard.
+
+#### devicetree.cb
+
+ fw_config
+ field FEATURE 0
+ option DISABLED 0
+ option ENABLED 1
+ end
+ field DAUGHTER_BOARD 1 2
+ option NONE 0
+ option REFERENCE_DB 1
+ end
+ end
+
+#### overridetree.cb
+
+ fw_config
+ field DAUGHTER_BOARD
+ option VARIANT_DB_ONE 2
+ option VARIANT_DB_TWO 3
+ end
+ end
+
+The result of this table defined in `devicetree.cb` is a list of constants that can be used
+to check if fields match the firmware configuration options determined at runtime with a
+simple check of the field mask and the option value.
+
+#### static.h
+
+```c
+/* field: FEATURE */
+#define FW_CONFIG_FIELD_FEATURE_NAME "FEATURE"
+#define FW_CONFIG_FIELD_FEATURE_MASK 0x00000001
+#define FW_CONFIG_FIELD_FEATURE_OPTION_DISABLED_NAME "DISABLED"
+#define FW_CONFIG_FIELD_FEATURE_OPTION_DISABLED_VALUE 0x00000000
+#define FW_CONFIG_FIELD_FEATURE_OPTION_ENABLED_NAME "ENABLED"
+#define FW_CONFIG_FIELD_FEATURE_OPTION_ENABLED_VALUE 0x00000001
+
+/* field: DAUGHTER_BOARD */
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME "DAUGHTER_BOARD"
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK 0x00000006
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_NONE_NAME "NONE"
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_NONE_VALUE 0x00000000
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_REFERENCE_DB_NAME "REFERENCE_DB"
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_REFERENCE_DB_VALUE 0x00000002
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME "VARIANT_DB_ONE"
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE 0x00000004
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME "VARIANT_DB_TWO"
+#define FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE 0x00000006
+```
+
+## Device Probing
+
+One use of the firmware configuration interface in devicetree is to allow device probing to be
+specified directly with the devices themselves. A new `probe` token is introduced to allow a
+device to be probed by field and option name. Multiple `probe` entries may be present for
+each device and any successful probe will consider the device to be present.
+
+### Probing Example
+
+Continuing with the previous example this device would be considered present if the field
+`DAUGHTER_BOARD` was set to either `VARIANT_DB_ONE` or `VARIANT_DB_TWO`:
+
+#### overridetree.cb
+
+ chip drivers/generic/example
+ device generic 0 on
+ probe DAUGHTER_BOARD VARIANT_DB_ONE
+ probe DAUGHTER_BOARD VARIANT_DB_TWO
+ end
+ end
+
+If the field were set to any other option, including `NONE` and `REFERENCE_DB` and any
+undefined value then the device would be disabled.
+
+### Probe Overrides
+
+When a device is declared with a probe in the baseboard `devicetree.cb` and the same device
+is also present in the `overridetree.cb` then the probing information from the baseboard
+is discarded and the override device must provide all necessary probing information.
+
+In this example a device is listed in the baseboard with `DAUGHTER_BOARD` field probing for
+`REFERENCE_DB` as a field option, It is also defined as an override device with the field
+probing for the `VARIANT_DB_ONE` option instead.
+
+In this case only the probe listed in the override is checked and a field option of
+`REFERENCE_DB` will not mark this device present. If both options are desired then the
+override device must list both. This allows an override device to remove a probe entry that
+was defined in the baseboard.
+
+#### devicetree.cb
+
+ chip drivers/generic/example
+ device generic 0 on
+ probe DAUGHTER_BOARD REFERENCE_DB
+ end
+ end
+
+#### overridetree.cb
+
+ chip drivers/generic/example
+ device generic 0 on
+ probe DAUGHTER_BOARD VARIANT_DB_ONE
+ end
+ end
+
+### Automatic Device Probing
+
+At boot time the firmware configuration interface will walk the device tree and apply any
+probe entries that were defined in `devicetree.cb`. This probing takes effect before the
+`BS_DEV_ENUMERATE` step during the boot state machine in ramstage.
+
+Devices that have a probe list but do do not find a match are disabled by setting
+`dev->enabled = 0` but the chip `enable_dev()` and device `enable()` handlers will still
+be executed to allow any device disable code to execute.
+
+The result of this probe definition is to provide an array of structures describing each
+field and option to check.
+
+#### fw_config.h
+
+```c
+/**
+ * struct fw_config - Firmware configuration field and option.
+ * @field_name: Name of the field that this option belongs to.
+ * @option_name: Name of the option within this field.
+ * @mask: Bitmask of the field.
+ * @value: Value of the option within the mask.
+ */
+struct fw_config {
+ const char *field_name;
+ const char *option_name;
+ uint32_t mask;
+ uint32_t value;
+};
+```
+
+#### static.c
+
+```c
+STORAGE struct fw_config __devN_probe_list[] = {
+ {
+ .field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
+ .option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_NAME,
+ .mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
+ .value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_ONE_VALUE
+ },
+ {
+ .field_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_NAME,
+ .option_name = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_NAME,
+ .mask = FW_CONFIG_FIELD_DAUGHTER_BOARD_MASK,
+ .value = FW_CONFIG_FIELD_DAUGHTER_BOARD_OPTION_VARIANT_DB_TWO_VALUE
+ },
+ { }
+};
+```
+
+### Runtime Probing
+
+The device driver probing allows for seamless integration with the mainboard but it is only
+effective in ramstage and for specific devices declared in devicetree.cb. There are other
+situations where code may need to probe or check the value of a field in romstage or at other
+points in ramstage. For this reason it is also possible to use the firmware configuration
+interface directly.
+
+```c
+/**
+ * fw_config_probe() - Check if field and option matches.
+ * @match: Structure containing field and option to probe.
+ *
+ * Return %true if match is found, %false if match is not found.
+ */
+bool fw_config_probe(const struct fw_config *match);
+```
+
+The argument provided to this function can be created from a macro for easy use:
+
+ FW_CONFIG(field, option)
+
+This example has a mainboard check if a feature is disabled and set an FSP UPD before memory
+training. This example expects that the default value of this `register` is set to `true` in
+`devicetree.cb` and this code is disabling that feature before FSP is executed.
+
+```c
+#include
+
+void mainboard_memory_init_params(FSPM_UPD *mupd)
+{
+ if (fw_config_probe_one(FW_CONFIG(FEATURE, DISABLED))
+ mupd->ExampleFeature = false;
+}
+```
diff --git a/Documentation/lib/index.md b/Documentation/lib/index.md
index 99b8061325..d64b4e999e 100644
--- a/Documentation/lib/index.md
+++ b/Documentation/lib/index.md
@@ -3,7 +3,7 @@
This section contains documentation about coreboot internal technical
information and libraries.
-## Structure and layout
- [Flashmap and Flashmap Descriptor](flashmap.md)
- [ABI data consumption](abi-data-consumption.md)
- [Timestamps](timestamp.md)
+- [Firmware Configuration Interface](fw_config.md)
diff --git a/Documentation/mainboard/gigabyte/ga-h61m-s2pv.md b/Documentation/mainboard/gigabyte/ga-h61m-s2pv.md
index 84b72ce24b..0632585c73 100644
--- a/Documentation/mainboard/gigabyte/ga-h61m-s2pv.md
+++ b/Documentation/mainboard/gigabyte/ga-h61m-s2pv.md
@@ -15,7 +15,7 @@ from [Gigabyte].
+---------------------+------------+
| Size | 4 MiB |
+---------------------+------------+
-| In circuit flashing | Yes |
+| In circuit flashing | No |
+---------------------+------------+
| Package | SOIC-8 |
+---------------------+------------+
diff --git a/Documentation/mainboard/google/dragonegg.md b/Documentation/mainboard/google/dragonegg.md
deleted file mode 100644
index ef7e61b710..0000000000
--- a/Documentation/mainboard/google/dragonegg.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# Google Dragonegg (Chromebook)
-
-This page describes how to run coreboot on the google dragonegg board.
-
-Dragonegg is based on Intel Ice Lake platform, please refer to below link to get more details
-```eval_rst
-:doc:`../../soc/intel/icelake/iceLake_coreboot_development`
-```
-
-## Building coreboot
-
-* Follow build instructions mentioned in Ice Lake document
-```eval_rst
-:doc:`../../soc/intel/icelake/iceLake_coreboot_development`
-```
-
-* The default options for this board should result in a fully working image:
-```bash
- # echo "CONFIG_VENDOR_GOOGLE=y" > .config
- # echo "CONFIG_BOARD_GOOGLE_DRAGONEGG=y" >> .config
- # make olddefconfig && make
-```
-
-## Flashing coreboot
-
-```eval_rst
-+---------------------+------------+
-| Type | Value |
-+=====================+============+
-| Socketed flash | no |
-+---------------------+------------+
-| Vendor | Winbond |
-+---------------------+------------+
-| Size | 32 MiB |
-+---------------------+------------+
-| Internal flashing | yes |
-+---------------------+------------+
-| External flashing | yes |
-+---------------------+------------+
-```
diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md
index 584deb42ee..3a7dd31742 100644
--- a/Documentation/mainboard/index.md
+++ b/Documentation/mainboard/index.md
@@ -51,10 +51,6 @@ The boards in this section are not real mainboards, but emulators.
- [GA-H61M-S2PV](gigabyte/ga-h61m-s2pv.md)
-## Google
-
-- [Dragonegg](google/dragonegg.md)
-
## HP
- [Compaq 8200 Elite SFF](hp/compaq_8200_sff.md)
@@ -102,6 +98,7 @@ The boards in this section are not real mainboards, but emulators.
- [W530](lenovo/w530.md)
- [T430 / T530 / X230 / W530 common](lenovo/Ivy_Bridge_series.md)
- [T431s](lenovo/t431s.md)
+- [X230s](lenovo/x230s.md)
- [Internal flashing](lenovo/ivb_internal_flashing.md)
### Haswell series
@@ -116,6 +113,10 @@ The boards in this section are not real mainboards, but emulators.
- [MS-7707](msi/ms7707/ms7707.md)
+## OCP
+
+- [Tioga Pass](ocp/tiogapass.md)
+
## Open Cellular
- [Elgon](opencellular/elgon.md)
@@ -130,6 +131,10 @@ The boards in this section are not real mainboards, but emulators.
- [PQ7-M107](portwell/pq7-m107.md)
+## Prodrive
+
+- [Hermes](prodrive/hermes.md)
+
## Protectli
- [FW2B / FW4B](protectli/fw2b_fw4b.md)
diff --git a/Documentation/mainboard/lenovo/Ivy_Bridge_series.md b/Documentation/mainboard/lenovo/Ivy_Bridge_series.md
index f4f0efff6c..5f151663c4 100644
--- a/Documentation/mainboard/lenovo/Ivy_Bridge_series.md
+++ b/Documentation/mainboard/lenovo/Ivy_Bridge_series.md
@@ -1,6 +1,6 @@
# Lenovo Ivy Bridge series
-This information is valid for all supported models, except T430s and T431s.
+This information is valid for all supported models, except T430s, [T431s](t431s.md) and [X230s](x230s.md).
## Flashing coreboot
```eval_rst
diff --git a/Documentation/mainboard/lenovo/x230s.md b/Documentation/mainboard/lenovo/x230s.md
new file mode 100644
index 0000000000..845410e17b
--- /dev/null
+++ b/Documentation/mainboard/lenovo/x230s.md
@@ -0,0 +1,19 @@
+# ThinkPad Lenovo X230s
+
+## Disassembly Instructions
+
+You must remove the following parts to access the SPI flash chip:
+
+
+
+* Base cover
+
+The [Hardware Maintenance Manual](https://download.lenovo.com/ibmdl/pub/pc/pccbbs/
+mobiles_pdf/x230s_hmm_en_0c10860_01.pdf) could be used as a guidance of disassembly.
+
+The SPI flash chip (W25Q128.V in the form of SOIC-8 for the author's X230s, but varying is possible)
+is located at the circled place.
+
+Unlike [most Ivy Bridge ThinkPads](Ivy_Bridge_series.md), X230s has a single 16MiB SPI flash chip.
+
+The general [flashing tutorial](../../flash_tutorial/index.md) has more details.
diff --git a/Documentation/mainboard/lenovo/x230s_bc_removed.jpg b/Documentation/mainboard/lenovo/x230s_bc_removed.jpg
new file mode 100644
index 0000000000..1735e8100b
Binary files /dev/null and b/Documentation/mainboard/lenovo/x230s_bc_removed.jpg differ
diff --git a/Documentation/mainboard/ocp/deltalake.md b/Documentation/mainboard/ocp/deltalake.md
new file mode 100644
index 0000000000..c4c3284b8f
--- /dev/null
+++ b/Documentation/mainboard/ocp/deltalake.md
@@ -0,0 +1,128 @@
+# OCP Delta Lake
+
+This page describes coreboot support status for the [OCP] (Open Compute Project)
+Delta Lake server platform.
+
+## Introduction
+
+OCP Delta Lake server platform is a component of multi-host server system
+Yosemite-V3. Both were announced by Facebook and Intel in [OCP virtual summit 2020].
+
+Delta Lake server is a single socket Cooper Lake Scalable Processor server.
+
+Yosemite-V3 has multiple configurations. Depending on configurations, it may
+host up to 4 Delta Lake servers in one sled.
+
+Yosemite-V3 and Delta Lake are currently in DVT phase. Facebook, Intel and partners
+jointly develop FSP/coreboot/LinuxBoot stack on Delta Lake as an alternative solution.
+
+## Required blobs
+
+This board currently requires:
+- FSP blob: The blob (Intel Cooper Lake Scalable Processor Firmware Support Package)
+ is not yet available to the public. It will be made public some time after the MP
+ (Mass Production) of CooperLake Scalable Processor when the FSP is mature.
+- Microcode: Not yet available to the public.
+- ME binary: Not yet available to the public.
+
+## Payload
+- LinuxBoot: This is necessary only if you use LinuxBoot as coreboot payload.
+ U-root as initramfs, is used in the joint development. It can be built
+ following [All about u-root].
+
+## Flashing coreboot
+
+To do in-band FW image update, use [flashrom]:
+ flashrom -p internal:ich_spi_mode=hwseq -c "Opaque flash chip" --ifd \
+ -i bios --noverify-all -w
+
+From OpenBMC, to update FW image:
+ fw-util slotx --update bios
+
+To power off/on the host:
+ power-util slotx off
+ power-util slotx on
+
+To connect to console through SOL (Serial Over Lan):
+ sol-util slotx
+
+## Working features
+The solution is developed using LinuxBoot payload with Linux kernel 5.2.9, and [u-root]
+as initramfs.
+- SMBIOS:
+ - Type 0 -- BIOS Information
+ - Type 1 -- System Information
+ - Type 2 -- Baseboard Information
+ - Type 3 -- System Enclosure or Chassis
+ - Type 4 -- Processor Information
+ - Type 8 -- Port Connector Information
+ - Type 9 -- PCI Slot Information
+ - Type 11 -- OEM String
+ - Type 13 -- BIOS Language Information
+ - Type 16 -- Physical Memory Array
+ - Type 19 -- Memory Array Mapped Address
+ - Type 127 -- End-of-Table
+
+- BMC integration:
+ - BMC readiness check
+ - IPMI commands
+ - watchdog timer
+ - POST complete pin acknowledgement
+- SEL record generation
+- Early serial output
+- port 80h direct to GPIO
+- ACPI tables: APIC/DSDT/FACP/FACS/HPET/MCFG/SPMI/SRAT/SLIT/SSDT
+- Skipping memory training upon subsequent reboots by using MRC cache
+- BMC crash dump
+- Error injection through ITP
+
+## Firmware configurations
+[ChromeOS VPD] is used to store most of the firmware configurations.
+RO_VPD region holds default values, while RW_VPD region holds customized
+values.
+
+VPD variables supported are:
+- firmware_version: This variable holds overall firmware version. coreboot
+ uses that value to populate smbios type 1 version field.
+
+## Known issues
+- Even though CPX-SP FSP is based on FSP 2.2 framework, it does not
+ support FSP_USES_CB_STACK. An IPS ticket is filed with Intel.
+- VT-d is not supported. An IPS ticket is filed with Intel.
+- PCIe bifuration is not supported. An IPS ticket is filed with Intel.
+- ME based power capping. This is a bug in ME. An IPS ticket is filed
+ with Intel.
+- RO_VPD region as well as other RO regions are not write protected.
+- HECI is not set up correctly, so BMC is not able to get PCH and DIMM
+ temperature sensor readings.
+
+## Feature gaps
+- Delta Lake DVT is not supported, as we only have Delta Lake EVT servers
+ at the moment.
+- SMBIOS:
+ - Type 7 -- Cache Information
+ - Type 17 -- Memory Device
+ - Type 38 -- IPMI Device Information
+ - Type 41 -- Onboard Devices Extended Information
+- ACPI:
+ - DMAR
+- PFR/CBnT
+
+## Technology
+
+```eval_rst
++------------------------+---------------------------------------------+
+| Processor (1 socket) | Intel Cooper Lake Scalable Processor |
++------------------------+---------------------------------------------+
+| BMC | Aspeed AST 2500 |
++------------------------+---------------------------------------------+
+| PCH | Intel Lewisburg C621 |
++------------------------+---------------------------------------------+
+```
+
+[OCP]: https://www.opencompute.org
+[OCP virtual summit 2020]: https://www.opencompute.org/summit/virtual-summit/schedule
+[flashrom]: https://flashrom.org/Flashrom
+[All about u-root]: https://github.com/linuxboot/book/tree/master/u-root
+[u-root]: https://u-root.org/
+[ChromeOS VPD]: https://chromium.googlesource.com/chromiumos/platform/vpd/+/master/README.md
diff --git a/Documentation/mainboard/ocp/tiogapass.md b/Documentation/mainboard/ocp/tiogapass.md
new file mode 100644
index 0000000000..6d6afb1920
--- /dev/null
+++ b/Documentation/mainboard/ocp/tiogapass.md
@@ -0,0 +1,100 @@
+# OCP Tioga Pass
+
+This page describes coreboot support status for the [OCP] (Open Compute Project)
+Tioga Pass server platform.
+
+## Introduction
+
+OCP Tioga Pass server platform was contributed by Facebook, and was accepted
+in 2019. The design collateral including datasheet can be found at [OCP Tioga Pass].
+
+Since complete EE design collateral is open sourced, anyone can build server
+as-is or a variant based on the original design. It can also be purchased from [OCP Market Place].
+An off-the-shelf version is available, as well as rack ready version. With the
+off-the-shelf version, the server can be plugged into wall power outlet.
+
+With the off-the-shelf version of Tioga Pass, a complete software solution is
+available. [Off-the-shelf Host Firmware] takes the approach of UEFI/Linuxboot.
+
+coreboot as of release 4.13 is a proof-of-concept project between Facebook,
+Intel, Wiwynn and Quanta. The context is described at [OCP Tioga Pass POC Blog].
+
+## Required blobs
+
+This board currently requires:
+- FSP blob: The blob (Intel Skylake Scalable Processor Firmware Support Package)
+ is not yet available to the public. The binary is at POC status, hopefully
+ someday an IBV is able to obtain the privilege to maintain it.
+- Microcode: `3rdparty/intel-microcode/intel-ucode/06-55-04`
+- ME binary: The binary can be extracted from [Off-the-shelf Host Firmware].
+
+## Payload
+- Linuxboot: This is necessary only if you use Linuxboot as coreboot payload.
+ U-root as initramfs, is used in the POC activity. It can be extracted from
+ [Off-the-shelf Host Firmware], or it can be built following [All about u-root].
+
+## Flashing coreboot
+
+To do in-band FW image update, use [flashrom]:
+ flashrom -p internal:ich_spi_mode=hwseq -c "Opaque flash chip" --ifd \
+ -i bios --noverify-all -w
+
+From OpenBMC, to update FW image:
+ fw-util mb --force --update
+
+To power off/on the host:
+ power-util mb off
+ power-util mb on
+
+To connect to console through SOL (Serial Over Lan):
+ sol-util mb
+
+## Known issues / feature gaps
+- C6 state is not supported. Workaround is to disable C6 support through
+ target OS and Linuxboot kernel paramter, such as "cpuidle.off=1".
+- SMI handlers are not implemented.
+- xSDT tables are not fully populated, such as processor/socket devices,
+ PCIe bridge devices.
+- There is boot stability issue. Occasionally the boot hangs at ramstage
+ with following message "BIOS PCU Misc Config Read timed out."
+- If [CB 40500 patchset] is not merged, when PCIe riser card is used,
+ boot fails.
+- PCIe devices connected to socket 1 may not work, because FSP
+ does not support PCIe topology input for socket 1.k
+- SMBIOS type 7 and type 17 are not populated.
+
+## Working
+The solution was developed using Linuxboot payload. The Linuxboot
+kernel versions tried are 4.16.18 and 5.2.9. The initramfs image is
+u-root.
+- Most SMBIOS types
+- BMC integration:
+ - BMC readiness check
+ - IPMI commands
+ - watchdog timer
+ - POST complete pin acknowledgement
+- SEL record generation
+- Early serial output
+- port 80h direct to GPIO
+- ACPI tables: APIC/DMAR/DSDT/FACP/FACS/HPET/MCFG/SPMI/SRAT/SLIT/SSDT
+
+## Technology
+
+```eval_rst
++------------------------+---------------------------------------------+
+| Processor (2 sockets) | Intel Skylake Scalable Processor LGA3647 |
++------------------------+---------------------------------------------+
+| BMC | Aspeed AST 2500 |
++------------------------+---------------------------------------------+
+| PCH | Intel Lewisburg C621 |
++------------------------+---------------------------------------------+
+```
+
+[flashrom]: https://flashrom.org/Flashrom
+[OCP]: https://www.opencompute.org/
+[OCP Tioga Pass]: https://www.opencompute.org/contributions?query=Tioga%20Pass%20v1.0
+[OCP Market Place]: https://www.opencompute.org/products/109/wiwynn-tioga-pass-advanced-2u-ocp-server-up-to-768gb-12-dimm-slots-4-ssds-for-io-performance
+[Off-the-shelf Host Firmware]: https://github.com/linuxboot/book/blob/master/case_studies/TiogaPass/README.md
+[OCP Tioga Pass POC Blog]: https://www.opencompute.org/blog/linux-firmware-boots-up-server-powered-by-intelr-xeonr-scalable-processor
+[All about u-root]: https://github.com/linuxboot/book/tree/master/u-root
+[CB 40500 patchset]: https://review.coreboot.org/c/coreboot/+/40500
diff --git a/Documentation/mainboard/prodrive/hermes.md b/Documentation/mainboard/prodrive/hermes.md
new file mode 100644
index 0000000000..6a12c3ab66
--- /dev/null
+++ b/Documentation/mainboard/prodrive/hermes.md
@@ -0,0 +1,54 @@
+# Hermes
+
+Hermes is a regular ATX board designed for workstation PCs.
+
+The board features:
+* 5 PCIe 16x Gen3 slots
+* 4 ECC capable DDR4 DIMMs
+* 5 dedicated Ethernet ports
+* 1 BMC Ethernet port
+* VGA
+* COM port
+* 2 COM port headers
+* 4 SATA ports,
+* NVMe M2 slot
+* CNVi M2 slot
+* 3 optional DisplayPort outputs
+* optional TPM2
+
+## Required proprietary blobs
+
+- [Intel FSP2.0]
+- Intel SPS
+
+## Flashing coreboot
+
+* The BIOS flash can be updated over the BMC, but the update file has a proprietary format
+* For development a dediprog compatible pinheader is present which allows to use an EM100
+
+## Known issues
+
+- MRC caching does not work on cold boot with Intel SPS (see [Intel FSP2.0])
+
+## Technology
+
+```eval_rst
++------------------+--------------------------------------------------+
+| CPU | CoffeeLake + CoffeeLake R (Core + Xeon) |
++------------------+--------------------------------------------------+
+| PCH | Intel C246 |
++------------------+--------------------------------------------------+
+| Coprocessor | Intel SPS (server version of the ME) |
++------------------+--------------------------------------------------+
+| Super I/O | none |
++------------------+--------------------------------------------------+
+| BMC | Aspeed AST2500 |
++------------------+--------------------------------------------------+
+```
+
+## Extra links
+
+[flashrom]: https://flashrom.org/Flashrom
+[flashing tutorial]: ../../../../flash_tutorial/ext_power.md
+[Intel FSP2.0]: ../../../../soc/intel/fsp/index.md
+[AST2500]: https://www.aspeedtech.com/products.php?fPath=20&rId=440
diff --git a/Documentation/mainboard_io_trap_handler_sample.c b/Documentation/mainboard_io_trap_handler_sample.c
index 558e12f877..a949009c20 100644
--- a/Documentation/mainboard_io_trap_handler_sample.c
+++ b/Documentation/mainboard_io_trap_handler_sample.c
@@ -20,7 +20,7 @@ int mainboard_io_trap_handler(int smif)
switch (smif) {
case 0x99:
printk(BIOS_DEBUG, "Sample\n");
- smm_get_gnvs()->smif = 0;
+ gnvs->smif = 0;
break;
default:
return 0;
@@ -32,6 +32,6 @@ int mainboard_io_trap_handler(int smif)
* For now, we force the return value to 0 and log all traps to
* see what's going on.
*/
- //smm_get_gnvs()->smif = 0;
+ //gnvs->smif = 0;
return 1;
}
diff --git a/Documentation/releases/coreboot-4.13-relnotes.md b/Documentation/releases/coreboot-4.13-relnotes.md
index 94e93bb75b..2910867f78 100644
--- a/Documentation/releases/coreboot-4.13-relnotes.md
+++ b/Documentation/releases/coreboot-4.13-relnotes.md
@@ -13,4 +13,30 @@ Update this document with changes that should be in the release notes.
Significant changes
-------------------
+### Hidden PCI devices
+
+This new functionality takes advantage of the existing 'hidden' keyword in the
+devicetree. Since no existing boards were using the keyword, its usage was
+repurposed to make dealing with some unique PCI devices easier. The particular
+case here is Intel's PMC (Power Management Controller). During the FSP-S run,
+the PMC device is made hidden, meaning that its config space looks as if there
+is no device there (Vendor ID reads as 0xFFFF_FFFF). However, the device does
+have fixed resources, both MMIO and I/O. These were previously recorded in
+different places (MMIO was typically an SA fixed resource, and I/O was treated
+as an LPC resource). With this change, when a device in the tree is marked as
+'hidden', it is not probed (`pci_probe_dev()`) but rather assumed to exist so
+that its resources can be placed in a more natural location. This also adds the
+ability for the device to participate in SSDT generation.
+
+### Tools for generating SPDs for LP4x memory on TGL and JSL
+
+A set of new tools `gen_spd.go` and `gen_part_id.go` are added to automate the
+process of generating SPDs for LP4x memory and assigning hardware strap IDs for
+memory parts used on TGL and JSL based boards. The SPD data obtained from memory
+part vendors has to be massaged to format it correctly as per JEDEC and Intel MRC
+expectations. These tools take a list of memory parts describing their physical
+attributes as per their datasheet and convert those attributes into SPD files for
+the platforms. More details about the tools are added in
+[README.md](https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/master/util/spd_tools/intel/lp4x/README.md).
+
### Add significant changes here
diff --git a/Documentation/security/index.md b/Documentation/security/index.md
index d5d4e2b93e..c9cb4a77de 100644
--- a/Documentation/security/index.md
+++ b/Documentation/security/index.md
@@ -13,3 +13,7 @@ This section describes documentation about the security architecture of coreboot
- [Intel TXT in general](intel/txt.md)
- [Intel TXT Initial Boot Block](intel/txt_ibb.md)
- [Intel Authenticated Code Modules](intel/acm.md)
+
+## SMM
+
+- [System Management Mode](smm.md)
diff --git a/Documentation/security/smm.md b/Documentation/security/smm.md
new file mode 100644
index 0000000000..4e95427b86
--- /dev/null
+++ b/Documentation/security/smm.md
@@ -0,0 +1,29 @@
+# x86 System Managment Mode
+
+## Introduction
+
+The code running in System Management Mode (SMM) provides runtime services
+to applications running in [ring0]. It has a higher privilege level than
+[ring0] and resides in the SMRAM region which cannot be accessed from [ring0].
+
+SMM can be entered by issuing System Managment Interrupts (SMIs).
+
+## Secure data exchange
+
+In order to not leak SMM internals or accidentally overwrite parts of SMM,
+[ring0] provided data (pointers, offsets, sizes, ...) must be checked before
+using them in SMM.
+
+There exist two methods to verify data:
+
+```C
+/* Returns true if the region overlaps with the SMM */
+bool smm_region_overlaps_handler(struct region *r);
+```
+
+```C
+/* Returns true if the memory pointed to overlaps with SMM reserved memory. */
+static inline bool smm_points_to_smram(const void *ptr, const size_t len);
+```
+
+[ring0]: https://en.wikipedia.org/wiki/Protection_ring
diff --git a/Documentation/tutorial/part2.md b/Documentation/tutorial/part2.md
index 5ab210a591..4ac857473d 100644
--- a/Documentation/tutorial/part2.md
+++ b/Documentation/tutorial/part2.md
@@ -108,8 +108,7 @@ in the source files. To see errors that are already present, build the files in
the repository by running `make lint` in the coreboot directory. Alternatively,
if you want to run `make lint` on a specific directory, run:
- for file in $(git ls-files | grep ); do \
- util/lint/checkpatch.pl --file $file --terse; done
+ util/lint/lint-007-checkpatch
where `filepath` is the filepath of the directory (ex. `src/cpu/amd/car`).
diff --git a/MAINTAINERS b/MAINTAINERS
index 353129240b..810f7b9609 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -133,65 +133,101 @@ Maintainers List (try to look for most precise areas first)
-----------------------------------
-RISC-V ARCHITECTURE
-M: Ronald Minnich
-R: Philipp Hug
-S: Maintained
-F: src/arch/riscv/
-F: src/soc/sifive/
-F: src/soc/ucb/
-F: src/mainboard/emulation/*-riscv/
-F: src/mainboard/sifive/
-F: util/riscv/
-
-PPC64 ARCHITECTURE
-M: Ronald Minnich
-M: Timothy Pearson
-S: Maintained
-F: src/arch/ppc64/
-F: src/cpu/qemu-power8/
-F: src/mainboard/emulation/qemu-power8/
-
-LENOVO EC
-M: Alexander Couzens
-S: Maintained
-F: src/ec/lenovo/
-
-LENOVO MAINBOARDS
-M: Alexander Couzens
-M: Patrick Rudolph
-S: Maintained
-F: src/mainboard/lenovo/
-
-LENOVO G505S MAINBOARD
-M: Mike Banon
-S: Maintained
-F: src/mainboard/lenovo/g505s/
+################################################################################
+# Mainboards
+################################################################################
APPLE MAINBOARDS
M: Evgeny Zinoviev
S: Maintained
F: src/mainboard/apple/
+
+
+ASROCK B85M PRO4 MAINBOARD
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asrock/b85m_pro4/
+
+ASROCK G41C-GS MAINBOARD & VARIANTS
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asrock/g41c-gs/
+
+ASROCK H81M-HDS MAINBOARD
+M: Tristan Corrick
+S: Maintained
+F: src/mainboard/asrock/h81m-hds/
+
+
+
+ASUS AM1I-A MAINBOARD
+M: Mike Banon
+S: Maintained
+F: src/mainboard/asus/am1i-a/
+
+ASUS MAXIMUS IV GENE-Z MAINBOARD
+M: Tristan Corrick
+S: Maintained
+F: src/mainboard/asus/maximus_iv_gene-z/
+
+ASUS P5QC PRO MAINBOARD & VARIANTS
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asus/p5qc/
+
+ASUS P5QPL-AM MAINBOARD & VARIANTS
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asus/p5qpl-am/
+
+ASUS P8H61-M LX MAINBOARD
+M: Tristan Corrick
+S: Maintained
+F: src/mainboard/asus/p8h61-m_lx/
+
+ASUS P8H61-M LX3 R2.0 MAINBOARD
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asus/p8h61-m_lx3_r2_0/
+
+ASUS P8H61-M PRO MAINBOARD
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asus/p8h61-m_pro/
+
+ASUS P8Z77-M PRO MAINBOARD
+M: Vlado Cibic
+S: Maintained
+F: src/mainboard/asus/p8z77-m_pro/
+
+ASUS P8Z77-V LX2 MAINBOARD
+M: Angel Pons
+S: Maintained
+F: src/mainboard/asus/p8z77-v_lx2/
+
+
+
+FACEBOOK FBG1701 MAINBOARD
+M: Frans Hendriks
+M: Wim Vervoorn
+S: Maintained
+F: src/mainboard/facebook/fbg1701/
+
+FACEBOOK MONOLITH MAINBOARD
+M: Frans Hendriks
+M: Wim Vervoorn
+S: Maintained
+F: src/mainboard/facebook/monolith/
+
+
+
GETAC P470 MAINBOARD
M: Patrick Georgi
S: Maintained
F: src/mainboard/getac/p470
-INTEL PINEVIEW CHIPSET
-M: Damien Zammit
-S: Odd Fixes
-F: src/northbridge/intel/pineview/
-INTEL D510MO MAINBOARD
-M: Damien Zammit
-S: Odd Fixes
-F: src/mainboard/intel/d510mo
-
-INTEL X4X CHIPSET
-M: Damien Zammit
-S: Odd Fixes
-F: src/northbridge/intel/x4x/
GIGABYTE GA-G41M-ES2L MAINBOARD
M: Damien Zammit
@@ -203,6 +239,8 @@ M: Angel Pons
S: Maintained
F: src/mainboard/gigabyte/ga-h61m-series
+
+
GOOGLE PANTHER MAINBOARD
M: Stefan Reinauer
S: Supported
@@ -222,23 +260,232 @@ F: src/mainboard/google/parrot/
F: src/mainboard/google/slippy/
F: src/mainboard/google/stout/
+
+
+INTEL D510MO MAINBOARD
+M: Damien Zammit
+S: Odd Fixes
+F: src/mainboard/intel/d510mo
+
+INTEL STRAGO MAINBOARD
+M: Hannah Williams
+S: Supported
+F: /src/mainboard/intel/strago/
+
+
+
+LENOVO MAINBOARDS
+M: Alexander Couzens
+M: Patrick Rudolph
+S: Maintained
+F: src/mainboard/lenovo/
+
+LENOVO G505S MAINBOARD
+M: Mike Banon
+S: Maintained
+F: src/mainboard/lenovo/g505s/
+
+
+
+LIBRETREND LT1000 MAINBOARD
+M: Piotr Król
+M: Michał Żygowski
+S: Maintained
+F: src/mainboard/libretrend/lt1000
+
+
+OCP DELTALAKE MAINBOARD
+M: Jonathan Zhang
+M: Reddy Chagam
+M: Johnny Lin
+M: Morgan Jang
+M: Ryback Hung <
+M: Bryant Ou
+S: Supported
+F: src/mainboard/ocp/deltalake
+
+OCP TIOGAPASS MAINBOARD
+M: Jonathan Zhang
+M: Reddy Chagam
+M: Johnny Lin
+M: Morgan Jang
+M: Ryback Hung <
+M: Bryant Ou
+S: Maintained
+F: src/mainboard/ocp/tiogapass
+
+
+
OPENCELLULAR MAINBOARDS
M: Christian Walter
M: Patrick Rudolph
S: Supported
F: src/mainboard/opencellular/elgon/
+
+
+PC ENGINES ALL MAINBOARDS
+M: Piotr Król
+M: Michał Żygowski
+S: Supported
+F: src/mainboard/pcengines/
+
+
+
+PORTWELL PQ-M107 MAINBOARD
+M: Frans Hendriks
+M: Wim Vervoorn
+S: Maintained
+F: src/mainboard/portwell/m107/
+
+
+
+PROTECTLI ALL MAINBOARDS
+M: Piotr Król
+M: Michał Żygowski
+S: Maintained
+F: src/mainboard/protectli/
+
+
+
+PRODRIVE HERMES MAINBOARD
+M: Christian Walter
+M: Patrick Rudolph
+S: Maintained
+F: src/mainboard/prodrive/hermes
+
+
+
PURISM MAINBOARDS
M: Matt DeVillier
S: Supported
F: src/mainboard/purism
+
+
SAMSUNG CHROMEOS MAINBOARDS
M: Matt DeVillier
S: Maintained
F: src/mainboard/samsung/lumpy/
F: src/mainboard/samsung/stumpy/
+
+
+SIEMENS MC_xxxx MAINBOARDS
+M: Werner Zeh
+S: Maintained
+F: src/mainboard/siemens/mc_apl1/
+
+
+
+SUPERMICRO X10SLM+-F MAINBOARD
+M: Tristan Corrick
+S: Maintained
+F: src/mainboard/supermicro/x10slm-f/
+
+SUPERMICRO X11-LGA1151-SERIES
+M: Michael Niewöhner
+S: Maintained
+F: src/mainboard/supermicro/x11-lga1151-series
+
+################################################################################
+# Architectures
+################################################################################
+
+ARM ARCHITECTURE
+M: Julius Werner
+S: Supported
+F: src/arch/arm/
+F: src/arch/arm64/
+F: src/soc/mediatek/
+F: src/soc/nvidia/
+F: src/soc/rockchip/
+F: util/nvidia/
+F: util/rockchip/
+
+PPC64 ARCHITECTURE
+M: Ronald Minnich
+M: Timothy Pearson
+S: Maintained
+F: src/arch/ppc64/
+F: src/cpu/qemu-power8/
+F: src/mainboard/emulation/qemu-power8/
+
+RISC-V ARCHITECTURE
+M: Ronald Minnich
+R: Philipp Hug
+S: Maintained
+F: src/arch/riscv/
+F: src/soc/sifive/
+F: src/soc/ucb/
+F: src/mainboard/emulation/*-riscv/
+F: src/mainboard/sifive/
+F: util/riscv/
+
+X86 ARCHITECTURE
+F: src/arch/x86/
+F: src/cpu/x86/
+F: src/drivers/pc80/
+F: src/include/pc80/
+F: src/include/cpu/x86/
+
+################################################################################
+# Embedded Controllers
+################################################################################
+
+LENOVO EC
+M: Alexander Couzens
+S: Maintained
+F: src/ec/lenovo/
+
+################################################################################
+# Northbridges
+################################################################################
+
+INTEL HASWELL NORTHBRIDGE
+M: Angel Pons
+S: Maintained
+F: src/northbridge/intel/haswell/
+
+INTEL PINEVIEW CHIPSET
+M: Damien Zammit
+M: Angel Pons
+S: Odd Fixes
+F: src/northbridge/intel/pineview/
+
+INTEL SANDYBRIDGE NORTHBRIDGE
+M: Angel Pons
+S: Maintained
+F: src/northbridge/intel/sandybridge/
+
+INTEL X4X CHIPSET
+M: Damien Zammit
+M: Angel Pons
+S: Odd Fixes
+F: src/northbridge/intel/x4x/
+
+################################################################################
+# Platforms
+################################################################################
+
+AMD SUPPORT
+F: src/vendorcode/amd/
+F: src/cpu/amd/
+F: src/northbridge/amd/
+F: src/southbridge/amd/
+F: src/include/cpu/amd/
+
+INTEL SUPPORT
+M: Patrick Rudolph
+S: Maintained
+F: src/vendorcode/intel/
+F: src/cpu/intel/
+F: src/northbridge/intel/
+F: src/southbridge/intel/
+F: src/soc/intel/
+F: src/drivers/intel/
+F: src/include/cpu/intel/
+
INTEL FSP DENVERTON-NS SOC & HARCUVAR CRB
M: Vanessa Eusebio
M: David Guckian
@@ -259,10 +506,14 @@ M: Andrey Petrov
S: Maintained
F: src/drivers/intel/fsp2_0/
-INTEL STRAGO MAINBOARD
-M: Hannah Williams
-S: Supported
-F: /src/mainboard/intel/strago/
+################################################################################
+# Systems on a Chip
+################################################################################
+
+INTEL APOLLOLAKE_SOC
+M: Andrey Petrov
+S: Maintained
+F: src/soc/intel/apollolake/
INTEL BRASWELL SOC
M: Piotr Król
@@ -272,146 +523,17 @@ S: Maintained
F: /src/soc/intel/braswell
F: /src/vendorcode/intel/fsp/fsp1_1/braswell
-INTEL APOLLOLAKE_SOC
-M: Andrey Petrov
-S: Maintained
-F: src/soc/intel/apollolake/
-
-ASROCK G41C-GS MAINBOARD & VARIANTS
-M: Angel Pons
-S: Maintained
-F: src/mainboard/asrock/g41c-gs/
-
-ASROCK H81M-HDS MAINBOARD
-M: Tristan Corrick
-S: Maintained
-F: src/mainboard/asrock/h81m-hds/
-
-ASUS AM1I-A MAINBOARD
-M: Mike Banon
-S: Maintained
-F: src/mainboard/asus/am1i-a/
-
-ASUS MAXIMUS IV GENE-Z MAINBOARD
-M: Tristan Corrick
-S: Maintained
-F: src/mainboard/asus/maximus_iv_gene-z/
-
-ASUS P5QC PRO MAINBOARD & VARIANTS
-M: Angel Pons
-S: Maintained
-F: src/mainboard/asus/p5qc/
-
-ASUS P8H61-M LX MAINBOARD
-M: Tristan Corrick
-S: Maintained
-F: src/mainboard/asus/p8h61-m_lx/
-
-ASUS P8H61-M PRO MAINBOARD
-M: Angel Pons
-S: Maintained
-F: src/mainboard/asus/p8h61-m_pro/
-
-ASUS P8Z77-M PRO MAINBOARD
-M: Vlado Cibic
-S: Maintained
-F: src/mainboard/asus/p8z77-m_pro/
-
-LIBRETREND LT1000 MAINBOARD
-M: Piotr Król
-M: Michał Żygowski
-S: Maintained
-F: src/mainboard/libretrend/lt1000
-
-PC ENGINES ALL MAINBOARDS
-M: Piotr Król
-M: Michał Żygowski
-S: Supported
-F: src/mainboard/pcengines/
-
-PROTECTLI ALL MAINBOARDS
-M: Piotr Król
-M: Michał Żygowski
-S: Maintained
-F: src/mainboard/protectli/
-
-SIEMENS MC_xxxx MAINBOARDS
-M: Werner Zeh
-S: Maintained
-F: src/mainboard/siemens/mc_apl1/
-
-SUPERMICRO X10SLM+-F MAINBOARD
-M: Tristan Corrick
-S: Maintained
-F: src/mainboard/supermicro/x10slm-f/
-
-SUPERMICRO X11-LGA1151-SERIES
-M: Michael Niewöhner
-S: Maintained
-F: src/mainboard/supermicro/x11-lga1151-series
-
-FACEBOOK FBG1701 MAINBOARD
-M: Frans Hendriks
-M: Wim Vervoorn
-S: Maintained
-F: src/mainboard/facebook/fbg1701/
-
-FACEBOOK MONOLITH MAINBOARD
-M: Frans Hendriks
-M: Wim Vervoorn
-S: Maintained
-F: src/mainboard/facebook/monolith/
-
-OCP TIOGAPASS MAINBOARD
+INTEL Xeon Sacalable Processor Family
M: Jonathan Zhang
M: Reddy Chagam
M: Johnny Lin
M: Morgan Jang
M: Ryback Hung <
M: Bryant Ou
-S: Maintained
-F: src/mainboard/ocp/tiogapass
-
-PORTWELL PQ-M107 MAINBOARD
-M: Frans Hendriks
-M: Wim Vervoorn
-S: Maintained
-F: src/mainboard/portwell/m107/
-
-ASPEED AST2050 DRIVER & COMMON CODE
-M: Timothy Pearson
S: Supported
-F: src/drivers/aspeed/common/
-F: src/drivers/aspeed/ast2050/
-
-ABUILD
-M: Patrick Georgi
-M: Martin Roth
-S: Supported
-F: util/abuild/
-
-ACPI
-F: src/acpi/
-F: src/arch/x86/acpi/
-F: util/acpi/
-
-LZ4 COMPRESSION
-M: Julius Werner
-S: Supported
-F: src/commonlib/lz4*
-F: payloads/libpayload/liblz4/
-F: util/cbfstool/lz4/
-
-ARM ARCHITECTURE
-M: Julius Werner
-S: Supported
-F: src/arch/arm/
-F: src/arch/arm64/
-F: src/soc/mediatek/
-F: src/soc/nvidia/
-F: src/soc/rockchip/
-F: util/nvidia/
-F: util/rockchip/
+F: src/soc/intel/xeon_sp
+F: src/vendorcode/intel/fsp/fsp2_0/skylake_sp
+F: src/vendorcode/intel/fsp/fsp2_0/copperlake_sp
ORPHANED ARM SOCS
S: Orphaned
@@ -422,30 +544,67 @@ F: src/soc/samsung/
F: util/exynos/
F: util/ipqheader/
-X86 ARCHITECTURE
-F: src/arch/x86/
-F: src/cpu/x86/
-F: src/drivers/pc80/
-F: src/include/pc80/
-F: src/include/cpu/x86/
+################################################################################
+# Payloads
+################################################################################
-INTEL SUPPORT
-M: Patrick Rudolph
-S: Maintained
-F: src/vendorcode/intel/
-F: src/cpu/intel/
-F: src/northbridge/intel/
-F: src/southbridge/intel/
-F: src/soc/intel/
-F: src/drivers/intel/
-F: src/include/cpu/intel/
+NVRAM
+F: util/nvramtool/
+F: payloads/nvramcui/
-AMD SUPPORT
-F: src/vendorcode/amd/
-F: src/cpu/amd/
-F: src/northbridge/amd/
-F: src/southbridge/amd/
-F: src/include/cpu/amd/
+LIBPAYLOAD
+F: payloads/libpayload/
+
+COREINFO PAYLOAD
+F: payloads/coreinfo/
+
+EXTERNAL PAYLOADS INTEGRATION
+M: Stefan Reinauer
+M: Martin Roth
+F: payloads/external
+
+LINUXBOOT PAYLOAD INTEGRATION
+M: Christian Walter
+M: Marcello Sylvester Bauer
+S: Supported
+F: payloads/external/LinuxBoot
+
+################################################################################
+# Utilities
+################################################################################
+
+ABUILD
+M: Patrick Georgi
+M: Martin Roth
+S: Supported
+F: util/abuild/
+
+BOARD STATUS
+F: util/board_status/
+
+BUILD SYSTEM
+M: Patrick Georgi
+M: Martin Roth
+S: Supported
+F: Makefile
+F: *.inc
+F: src/include/kconfig.h
+F: util/kconfig/
+F: util/sconfig/
+F: util/xcompile/
+F: util/genbuild_h/
+
+TOOLCHAIN
+F: util/crossgcc/
+
+DOCKER
+M: Martin Roth
+S: Supported
+F: util/docker/
+
+GIT
+F: .git*
+F: /util/gitconfig
LINT SCRIPTS
M: Patrick Georgi
@@ -453,6 +612,10 @@ M: Martin Roth
S: Supported
F: util/lint/
+IFDTOOL
+M: Stefan Reinauer
+F: util/ifdtool/
+
INTELTOOL
M: Stefan Reinauer
F: util/inteltool/
@@ -467,24 +630,27 @@ W: https://github.com/corna/me_cleaner
S: Maintained
F: util/me_cleaner/
-IFDTOOL
-M: Stefan Reinauer
-F: util/ifdtool/
+################################################################################
+# Miscellaneous
+################################################################################
-BUILD SYSTEM
-M: Patrick Georgi
-M: Martin Roth
+ASPEED AST2050 DRIVER & COMMON CODE
+M: Timothy Pearson
S: Supported
-F: Makefile
-F: *.inc
-F: src/include/kconfig.h
-F: util/kconfig/
-F: util/sconfig/
-F: util/xcompile/
-F: util/genbuild_h/
+F: src/drivers/aspeed/common/
+F: src/drivers/aspeed/ast2050/
-BOARD STATUS
-F: util/board_status/
+ACPI
+F: src/acpi/
+F: src/arch/x86/acpi/
+F: util/acpi/
+
+LZ4 COMPRESSION
+M: Julius Werner
+S: Supported
+F: src/commonlib/lz4*
+F: payloads/libpayload/liblz4/
+F: util/cbfstool/lz4/
BINARY OBJECTS
F: 3rdparty/blobs/
@@ -518,27 +684,6 @@ F: src/console/
F: src/include/console/
F: src/drivers/uart/
-NVRAM
-F: util/nvramtool/
-F: payloads/nvramcui/
-
-LIBPAYLOAD
-F: payloads/libpayload/
-
-COREINFO PAYLOAD
-F: payloads/coreinfo/
-
-EXTERNAL PAYLOADS INTEGRATION
-M: Stefan Reinauer
-M: Martin Roth
-F: payloads/external
-
-LINUXBOOT PAYLOAD INTEGRATION
-M: Christian Walter
-M: Marcello Sylvester Bauer
-S: Supported
-F: payloads/external/LinuxBoot
-
VERIFIED BOOT 2
M: Aaron Durbin
F: src/security/vboot/
@@ -549,18 +694,6 @@ S: Supported
F: src/drivers/*/tpm/
F: src/security/tpm
-DOCKER
-M: Martin Roth
-S: Supported
-F: util/docker/
-
-TOOLCHAIN
-F: util/crossgcc/
-
-GIT
-F: .git*
-F: /util/gitconfig
-
SUPERIOS & SUPERIOTOOL
M: Felix Held
S: Maintained
diff --git a/Makefile b/Makefile
index 2bc2a6fe63..2705c66b51 100644
--- a/Makefile
+++ b/Makefile
@@ -61,8 +61,6 @@ endif
# Disable implicit/built-in rules to make Makefile errors fail fast.
.SUFFIXES:
-HOSTCC := $(if $(shell type gcc 2>/dev/null),gcc,cc)
-HOSTCXX = g++
HOSTCFLAGS := -g
HOSTCXXFLAGS := -g
@@ -83,6 +81,8 @@ help_coreboot help::
@echo ' distclean - Remove build artifacts and config files'
@echo ' doxygen - Build doxygen documentation for coreboot'
@echo ' doxyplatform - Build doxygen documentation for the current platform'
+ @echo ' sphinx - Build sphinx documentation for coreboot'
+ @echo ' sphinx-lint - Build sphinx documenttion for coreboot with warnings as errors'
@echo ' filelist - Show files used in current build'
@echo ' printall - print makefile info for debugging'
@echo ' gitconfig - set up git to submit patches to coreboot'
@@ -103,7 +103,7 @@ ifeq ($(strip $(HAVE_DOTCONFIG)),)
NOCOMPILE:=1
endif
ifneq ($(MAKECMDGOALS),)
-ifneq ($(filter %config %clean cross% clang iasl gnumake lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
+ifneq ($(filter %config %clean cross% clang iasl lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
NOCOMPILE:=1
endif
ifneq ($(filter %clean lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
@@ -126,6 +126,11 @@ endif
rm -f $@.tmp
ifeq ($(NOCOMPILE),1)
+# We also don't use .xcompile in the no-compile situations, so
+# provide some reasonable defaults.
+HOSTCC ?= $(if $(shell type gcc 2>/dev/null),gcc,cc)
+HOSTCXX ?= g++
+
include $(TOPLEVEL)/Makefile.inc
include $(TOPLEVEL)/payloads/Makefile.inc
include $(TOPLEVEL)/util/testing/Makefile.inc
@@ -419,6 +424,12 @@ cscope-project: clean-cscope $(obj)/project_filelist.txt
cscope:
cscope -bR
+sphinx:
+ $(MAKE) -C Documentation -f Makefile.sphinx html
+
+sphinx-lint:
+ $(MAKE) SPHINXOPTS=-W -C Documentation -f Makefile.sphinx html
+
doxy: doxygen
doxygen:
$(DOXYGEN) Documentation/Doxyfile.coreboot
@@ -465,5 +476,5 @@ distclean: clean clean-ctags clean-cscope distclean-payloads distclean-utils
rm -rf coreboot-builds coreboot-builds-chromeos
rm -f abuild*.xml junit.xml* util/lint/junit.xml
-.PHONY: $(PHONY) clean clean-for-update clean-cscope cscope distclean doxygen doxy doxygen_simple
+.PHONY: $(PHONY) clean clean-for-update clean-cscope cscope distclean doxygen doxy doxygen_simple sphinx sphinx-lint
.PHONY: ctags-project cscope-project clean-ctags
diff --git a/Makefile.inc b/Makefile.inc
index 86467a66a8..89bb3e4239 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -13,6 +13,7 @@ CONFIG_CBFS_PREFIX:=$(call strip_quotes,$(CONFIG_CBFS_PREFIX))
CONFIG_FMDFILE:=$(call strip_quotes,$(CONFIG_FMDFILE))
CONFIG_DEVICETREE:=$(call strip_quotes, $(CONFIG_DEVICETREE))
CONFIG_OVERRIDE_DEVICETREE:=$(call strip_quotes, $(CONFIG_OVERRIDE_DEVICETREE))
+CONFIG_MEMLAYOUT_LD_FILE:=$(call strip_quotes, $(CONFIG_MEMLAYOUT_LD_FILE))
#######################################################################
# misleadingly named, this is the coreboot version
@@ -98,6 +99,13 @@ classes-y := ramstage romstage bootblock decompressor postcar smm smmstub cpu_mi
$(call add-special-class,all)
all-handler = $(foreach class,bootblock verstage romstage postcar ramstage,$(eval $(class)-y += $(2)))
+$(call add-special-class,verstage_x86)
+ifeq ($(CONFIG_ARCH_VERSTAGE_X86_32)$(CONFIG_ARCH_VERSTAGE_X86_64),y)
+verstage_x86-handler = $(eval verstage-y += $(2))
+else
+verstage_x86-handler =
+endif
+
# Add dynamic classes for rmodules
$(foreach supported_arch,$(ARCH_SUPPORTED), \
$(eval $(call define_class,rmodules_$(supported_arch),$(supported_arch))))
@@ -188,12 +196,15 @@ ifeq ($(CONFIG_USE_BLOBS),y)
# until expressly requested and enabled with --checkout
forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/blobs))
forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/intel-microcode))
-ifeq ($(CONFIG_PLATFORM_USES_FSP1_0)$(CONFIG_PLATFORM_USES_FSP1_1)$(CONFIG_PLATFORM_USES_FSP2_0),y)
+ifeq ($(CONFIG_FSP_USE_REPO),y)
forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/fsp))
endif
ifeq ($(CONFIG_USE_AMD_BLOBS),y)
forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/amd_blobs))
endif
+ifeq ($(CONFIG_USE_QC_BLOBS),y)
+forgetthis:=$(if $(GIT),$(shell git submodule update --init --checkout 3rdparty/qc_blobs))
+endif
endif
UPDATED_SUBMODULES:=1
COREBOOT_EXPORTS += UPDATED_SUBMODULES
@@ -609,6 +620,13 @@ smm-c-deps+=$(DEVICETREE_STATIC_C)
.PHONY: devicetree
devicetree: $(DEVICETREE_STATIC_C)
+ramstage-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+romstage-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+bootblock-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+verstage-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+postcar-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+decompressor-y += $(CONFIG_MEMLAYOUT_LD_FILE)
+
#######################################################################
# Clean up rules
clean-abuild:
@@ -1169,11 +1187,10 @@ $(CONFIG_CBFS_PREFIX)/romstage-options := -S ".car.data"
ifneq ($(CONFIG_NO_XIP_EARLY_STAGES),y)
$(CONFIG_CBFS_PREFIX)/romstage-options += --xip
-# If XIP_ROM_SIZE isn't being used don't overly constrain romstage by passing
-# -P with a default value.
-ifneq ($(CONFIG_NO_FIXED_XIP_ROM_SIZE),y)
-$(CONFIG_CBFS_PREFIX)/romstage-options += -P $(CONFIG_XIP_ROM_SIZE)
-endif # CONFIG_NO_FIXED_XIP_ROM_SIZE
+# For efficient MTRR utilisation use natural alignment for romstage.
+ifeq ($(CONFIG_SETUP_XIP_CACHE),y)
+$(CONFIG_CBFS_PREFIX)/romstage-options += --pow2page
+endif # CONFIG_SETUP_XIP_CACHE
endif # CONFIG_NO_XIP_EARLY_STAGES
endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
diff --git a/configs/builder/config.lenovo_t420 b/configs/builder/config.lenovo_t420
index e4e4b9b2a4..5ac036d98d 100644
--- a/configs/builder/config.lenovo_t420
+++ b/configs/builder/config.lenovo_t420
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_t420s b/configs/builder/config.lenovo_t420s
index 7593b7a740..f0b312b42e 100644
--- a/configs/builder/config.lenovo_t420s
+++ b/configs/builder/config.lenovo_t420s
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_t430s b/configs/builder/config.lenovo_t430s
index b21dbbaf07..682b17eb2a 100644
--- a/configs/builder/config.lenovo_t430s
+++ b/configs/builder/config.lenovo_t430s
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_t520 b/configs/builder/config.lenovo_t520
index 1d7816e909..4bbbb255b8 100644
--- a/configs/builder/config.lenovo_t520
+++ b/configs/builder/config.lenovo_t520
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_t530 b/configs/builder/config.lenovo_t530
index 0106bbc22a..635e3554c9 100644
--- a/configs/builder/config.lenovo_t530
+++ b/configs/builder/config.lenovo_t530
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_x220 b/configs/builder/config.lenovo_x220
index da5a474277..29d9639bd9 100644
--- a/configs/builder/config.lenovo_x220
+++ b/configs/builder/config.lenovo_x220
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_x220i b/configs/builder/config.lenovo_x220i
index 5612f5b22e..24e381d12c 100644
--- a/configs/builder/config.lenovo_x220i
+++ b/configs/builder/config.lenovo_x220i
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.lenovo_x230 b/configs/builder/config.lenovo_x230
index d897f44ec8..5040145aac 100644
--- a/configs/builder/config.lenovo_x230
+++ b/configs/builder/config.lenovo_x230
@@ -12,7 +12,6 @@ CONFIG_NO_POST=y
CONFIG_GBE_BIN_PATH="site-local/gbe.bin"
CONFIG_PCIEXP_CLK_PM=y
CONFIG_PCIEXP_L1_SUB_STATE=y
-CONFIG_LPC_TPM=y
CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000
CONFIG_PAYLOAD_NONE=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
diff --git a/configs/builder/config.ocp.deltalake b/configs/builder/config.ocp.deltalake
new file mode 100644
index 0000000000..4a8cda1c7f
--- /dev/null
+++ b/configs/builder/config.ocp.deltalake
@@ -0,0 +1,17 @@
+# type this to get working .config:
+# make defconfig KBUILD_DEFCONFIG=configs/builder/config.ocp.deltalake
+
+CONFIG_VENDOR_OCP=y
+CONFIG_BOARD_OCP_DELTALAKE=y
+CONFIG_HAVE_IFD_BIN=y
+CONFIG_HAVE_ME_BIN=y
+CONFIG_DO_NOT_TOUCH_DESCRIPTOR_REGION=y
+CONFIG_USE_CPU_MICROCODE_CBFS_BINS=y
+CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_BINS=y
+CONFIG_CPU_UCODE_BINARIES="site-local/deltalake/mbf5065a.mcb"
+CONFIG_ADD_FSP_BINARIES=y
+CONFIG_FSP_T_FILE="site-local/deltalake/Server_T.fd"
+CONFIG_FSP_M_FILE="site-local/deltalake/Server_M.fd"
+CONFIG_FSP_S_FILE="site-local/deltalake/Server_S.fd"
+CONFIG_ME_BIN_PATH="site-local/deltalake/flashregion_2_intel_me.bin"
+CONFIG_IFD_BIN_PATH="site-local/deltalake/flashregion_0_flashdescriptor.bin"
diff --git a/payloads/external/Makefile.inc b/payloads/external/Makefile.inc
index 46d70c4d13..ef0990c9b7 100644
--- a/payloads/external/Makefile.inc
+++ b/payloads/external/Makefile.inc
@@ -19,7 +19,7 @@ endif
ifeq ($(CONFIG_PAYLOAD_DEPTHCHARGE),y)
PAYLOAD_CONFIG=payloads/external/depthcharge/depthcharge/.config
$(PAYLOAD_CONFIG): payloads/external/depthcharge/depthcharge/build/depthcharge.elf
-ifeq ($(call strip_quotes,$(CONFIG_MAINBOARD_DEPTHCHARGE))),)
+ifeq ($(call strip_quotes,$(CONFIG_MAINBOARD_DEPTHCHARGE)),)
BOARD=$(call ws_to_under,$(call strip_quotes,$(call tolower,$(CONFIG_MAINBOARD_PART_NUMBER))))
else
BOARD=$(CONFIG_MAINBOARD_DEPTHCHARGE)
@@ -253,7 +253,7 @@ payloads/external/iPXE/ipxe/ipxe.rom ipxe: $(DOTCONFIG) $(PXE_CONFIG_SCRIPT)
CONFIG_TTYS0_BAUD=$(CONFIG_TTYS0_BAUD) \
CONFIG_SCRIPT=$(PXE_CONFIG_SCRIPT) \
CONFIG_HAS_SCRIPT=$(CONFIG_PXE_ADD_SCRIPT) \
- CONFIG_PXE_NO_PROMT=$(CONFIG_PXE_NO_PROMT) \
+ CONFIG_PXE_NO_PROMPT=$(CONFIG_PXE_NO_PROMPT) \
CONFIG_PXE_HAS_HTTPS=$(CONFIG_PXE_HAS_HTTPS) \
MFLAGS= MAKEFLAGS=
diff --git a/payloads/external/depthcharge/Makefile b/payloads/external/depthcharge/Makefile
index c4dd1bf14b..60aa92d55c 100644
--- a/payloads/external/depthcharge/Makefile
+++ b/payloads/external/depthcharge/Makefile
@@ -50,8 +50,7 @@ fetch: $(project_dir)
# Check out the requested version of the tree
# Don't write a file for master branch so the latest remote version is always used
-$(project_dir)/.version_$(TAG-y):
- $(MAKE) fetch
+$(project_dir)/.version_$(TAG-y): fetch
echo " Checking out $(project_name) revision $(TAG-y)"
rm -f $(project_dir)/.version_*
cd $(project_dir); \
diff --git a/payloads/external/iPXE/Kconfig b/payloads/external/iPXE/Kconfig
index 2aa9dbee46..0b81d183e9 100644
--- a/payloads/external/iPXE/Kconfig
+++ b/payloads/external/iPXE/Kconfig
@@ -78,7 +78,7 @@ config PXE_SERIAL_CONSOLE
Unselect to let only SeaBIOS handle printing output.
-config PXE_NO_PROMT
+config PXE_NO_PROMPT
bool "Do not show prompt to boot from PXE"
default n
depends on BUILD_IPXE
diff --git a/payloads/external/iPXE/Makefile b/payloads/external/iPXE/Makefile
index c426bd3f89..2a9e8c9b64 100644
--- a/payloads/external/iPXE/Makefile
+++ b/payloads/external/iPXE/Makefile
@@ -45,14 +45,14 @@ ifeq ($(CONSOLE_SERIAL),yy)
sed 's|#define\s*COMCONSOLE.*|#define COMCONSOLE $(IPXE_UART)|' "$(project_dir)/src/config/serial.h" > "$(project_dir)/src/config/serial.h.tmp"
sed 's|#define\s*COMSPEED.*|#define COMSPEED $(CONFIG_TTYS0_BAUD)|' "$(project_dir)/src/config/serial.h.tmp" > "$(project_dir)/src/config/serial.h"
endif
-ifneq ($(filter y,$(CONFIG_HAS_SCRIPT) $(CONFIG_PXE_NO_PROMT)),)
+ifneq ($(filter y,$(CONFIG_HAS_SCRIPT) $(CONFIG_PXE_NO_PROMPT)),)
cp "$(project_dir)/src/config/general.h" "$(project_dir)/src/config/general.h.cb"
endif
ifeq ($(CONFIG_HAS_SCRIPT),y)
sed 's|//#define\s*IMAGE_SCRIPT.*|#define IMAGE_SCRIPT|' "$(project_dir)/src/config/general.h" > "$(project_dir)/src/config/general.h.tmp"
mv "$(project_dir)/src/config/general.h.tmp" "$(project_dir)/src/config/general.h"
endif
-ifeq ($(CONFIG_PXE_NO_PROMT),y)
+ifeq ($(CONFIG_PXE_NO_PROMPT),y)
sed 's|#define\s*BANNER_TIMEOUT.*|#define BANNER_TIMEOUT 0|' "$(project_dir)/src/config/general.h" > "$(project_dir)/src/config/general.h.tmp"
mv "$(project_dir)/src/config/general.h.tmp" "$(project_dir)/src/config/general.h"
endif
@@ -74,7 +74,7 @@ ifeq ($(CONSOLE_SERIAL),yy)
cp "$(project_dir)/src/config/console.h.cb" "$(project_dir)/src/config/console.h"
cp "$(project_dir)/src/config/serial.h.cb" "$(project_dir)/src/config/serial.h"
endif
-ifneq ($(filter y,$(CONFIG_HAS_SCRIPT) $(CONFIG_PXE_NO_PROMT)),)
+ifneq ($(filter y,$(CONFIG_HAS_SCRIPT) $(CONFIG_PXE_NO_PROMPT)),)
cp "$(project_dir)/src/config/general.h.cb" "$(project_dir)/src/config/general.h"
endif
diff --git a/payloads/external/tianocore/Makefile b/payloads/external/tianocore/Makefile
index 635c0d6c58..9945411880 100644
--- a/payloads/external/tianocore/Makefile
+++ b/payloads/external/tianocore/Makefile
@@ -69,7 +69,7 @@ update: $(project_dir)
else \
echo " Working directory not clean; will not overwrite"; \
fi; \
- git submodule update --init --recursive
+ git submodule update --init
checktools:
echo "Checking uuid-dev..."
diff --git a/payloads/libpayload/Kconfig b/payloads/libpayload/Kconfig
index 7e506d9100..b5dc9a3c8b 100644
--- a/payloads/libpayload/Kconfig
+++ b/payloads/libpayload/Kconfig
@@ -334,6 +334,19 @@ config FONT_SCALE_FACTOR
By default (value of 0), the scale factor is automatically
calculated to ensure at least 130 columns (when possible).
+config CBGFX_FAST_RESAMPLE
+ bool "CBGFX: use faster (less pretty) image scaling"
+ default n
+ help
+ When payloads use the CBGFX library to draw .BMPs on the screen,
+ they will be resampled with an anti-aliasing filter to scale to the
+ requested output size. The default implementation should normally be
+ fast enough, but if desired this option can make it about 50-100%
+ faster at the cost of quality. (It changes the 'a' parameter in the
+ Lanczos resampling algorithm from 3 to 2.)
+
+ Only affects .BMPs that aren't already provided at the right size.
+
config PC_I8042
bool "A common PC i8042 driver"
default y if PC_KEYBOARD || PC_MOUSE
diff --git a/payloads/libpayload/arch/arm64/exception.c b/payloads/libpayload/arch/arm64/exception.c
index 94e7990e23..21ed1c2661 100644
--- a/payloads/libpayload/arch/arm64/exception.c
+++ b/payloads/libpayload/arch/arm64/exception.c
@@ -32,7 +32,6 @@
u64 exception_stack[2*KiB] __attribute__((aligned(16)));
u64 *exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack);
-extern unsigned int test_exc;
struct exception_handler_info
{
@@ -111,13 +110,7 @@ void exception_dispatch(struct exception_state *state, int idx)
/* Few words below SP in case we need state from a returned function. */
dump_stack(state->sp - 32, 512);
- if (test_exc) {
- state->elr += 4;
- test_exc = 0;
- printf("returning back now\n");
- }
- else
- halt();
+ halt();
}
void exception_init(void)
diff --git a/payloads/libpayload/arch/arm64/libpayload.ldscript b/payloads/libpayload/arch/arm64/libpayload.ldscript
index 8ebafce9fa..f9fb771da6 100644
--- a/payloads/libpayload/arch/arm64/libpayload.ldscript
+++ b/payloads/libpayload/arch/arm64/libpayload.ldscript
@@ -28,7 +28,7 @@
*/
OUTPUT_FORMAT("elf64-littleaarch64","elf64-littleaarch64", "elf64-littleaarch64")
-OUTPUT_ARCH(arm64)
+OUTPUT_ARCH(aarch64)
ENTRY(_entry)
diff --git a/payloads/libpayload/arch/arm64/main.c b/payloads/libpayload/arch/arm64/main.c
index 1311a866d9..374c8b18e2 100644
--- a/payloads/libpayload/arch/arm64/main.c
+++ b/payloads/libpayload/arch/arm64/main.c
@@ -35,19 +35,6 @@ int main_argc; /**< The argc value to pass to main() */
/** The argv value to pass to main() */
char *main_argv[MAX_ARGC_COUNT];
-unsigned int test_exc;
-
-static int test_exception(void)
-{
- uint64_t *a = (uint64_t *)0xfffffffff0000000ULL;
-
- test_exc = 1;
-
- printf("%llx\n", *a);
-
- return 0;
-}
-
/*
* Func: pre_sysinfo_scan_mmu_setup
* Desc: We need to setup and enable MMU before we can go to scan coreboot
@@ -126,10 +113,8 @@ void start_main(void)
console_init();
#endif
- printf("ARM64: Libpayload %s\n",__func__);
exception_init();
- test_exception();
/*
* Any other system init that has to happen before the
* user gets control goes here.
diff --git a/payloads/libpayload/arch/x86/apic.c b/payloads/libpayload/arch/x86/apic.c
index a484163054..62011612a5 100644
--- a/payloads/libpayload/arch/x86/apic.c
+++ b/payloads/libpayload/arch/x86/apic.c
@@ -104,7 +104,7 @@ uint8_t apic_id(void)
return id;
}
-void apic_delay(unsigned int usec)
+void apic_start_delay(unsigned int usec)
{
die_if(!ticks_per_ms, "apic_init_timer was not run.");
die_if(timer_waiting, "timer already started.");
@@ -124,9 +124,17 @@ void apic_delay(unsigned int usec)
timer_waiting = 1;
apic_write32(APIC_TIMER_INIT_COUNT, ticks);
+ enable_interrupts();
+}
+
+void apic_wait_delay(void)
+{
/* Loop in case another interrupt has fired and resumed execution. */
- do {
+ disable_interrupts();
+ /* Note: when we test timer_waiting, interrupts are disabled by the line
+ * above and the cli below. */
+ while (timer_waiting) {
asm volatile(
"sti\n\t"
"hlt\n\t"
@@ -134,15 +142,22 @@ void apic_delay(unsigned int usec)
* between checking timer_waiting and executing the hlt
* instruction again. */
"cli\n\t");
- } while (timer_waiting);
+ }
/* Leave hardware interrupts enabled. */
enable_interrupts();
}
+void apic_delay(unsigned int usec)
+{
+ apic_start_delay(usec);
+ apic_wait_delay();
+}
+
static void timer_interrupt_handler(u8 vector)
{
timer_waiting = 0;
+ apic_eoi(APIC_TIMER_VECTOR);
}
static void suprious_interrupt_handler(u8 vector) {}
@@ -204,6 +219,7 @@ static void apic_reset_all_lvts(void)
uint8_t max = apic_max_lvt_entries();
for (int i = 0; i <= max; ++i) {
uint32_t offset = APIC_LVT_TIMER + APIC_LVT_SIZE * i;
+ apic_eoi(i);
apic_write32(offset, APIC_MASKED_BIT);
}
}
@@ -248,6 +264,16 @@ static void apic_init_timer(void)
apic_write32(APIC_LVT_TIMER, APIC_TIMER_VECTOR);
}
+static void apic_sw_disable(void)
+{
+ uint32_t reg = apic_read32(APIC_SPURIOUS);
+
+ reg &= ~APIC_SW_ENABLED_BIT;
+ printf("%s: writing %#x to %#x\n", __func__, reg, APIC_SPURIOUS);
+
+ apic_write32(APIC_SPURIOUS, reg);
+}
+
static void apic_sw_enable(void)
{
uint32_t reg = apic_read32(APIC_SPURIOUS);
@@ -280,6 +306,7 @@ void apic_init(void)
die_if(!(apic_capabilities() & XACPI), "APIC is not supported");
apic_bar_reg = _rdmsr(APIC_BASE_MSR);
+ printf("apic_bar_reg is 0x%llx\n", apic_bar_reg);
die_if(!(apic_bar_reg & XAPIC_ENABLED_BIT), "APIC is not enabled");
die_if(apic_bar_reg & X2APIC_ENABLED_BIT,
@@ -287,6 +314,7 @@ void apic_init(void)
apic_bar = (uint32_t)(apic_bar_reg & APIC_BASE_MASK);
+ apic_sw_disable();
apic_reset_all_lvts();
apic_set_task_priority(0);
apic_setup_spurious();
diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c
index accb228b95..b14abb4b35 100644
--- a/payloads/libpayload/drivers/usb/usb.c
+++ b/payloads/libpayload/drivers/usb/usb.c
@@ -86,6 +86,10 @@ usb_poll (void)
{
if (usb_hcs == 0)
return;
+
+ if (usb_poll_prepare)
+ usb_poll_prepare();
+
hci_t *controller = usb_hcs;
while (controller != NULL) {
int i;
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index 07d5b16486..749ff0a066 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -129,7 +129,12 @@ xhci_switchback_ppt_ports(pcidev_t addr)
static long
xhci_handshake(volatile u32 *const reg, u32 mask, u32 wait_for, long timeout_us)
{
- while ((*reg & mask) != wait_for && timeout_us--) udelay(1);
+ if (timeout_us <= 0)
+ return 0;
+ while ((*reg & mask) != wait_for && timeout_us != 0) {
+ --timeout_us;
+ udelay(1);
+ }
return timeout_us;
}
diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c
index 81d2bb9e55..54d3dfa2b2 100644
--- a/payloads/libpayload/drivers/video/graphics.c
+++ b/payloads/libpayload/drivers/video/graphics.c
@@ -28,6 +28,7 @@
#include
#include
+#include
#include
#include "bitmap.h"
@@ -60,6 +61,37 @@ static const struct vector vzero = {
.y = 0,
};
+struct blend_value {
+ uint8_t alpha;
+ struct rgb_color rgb;
+};
+
+static struct blend_value blend = {
+ .alpha = 0,
+ .rgb.red = 0,
+ .rgb.green = 0,
+ .rgb.blue = 0,
+};
+
+int set_blend(const struct rgb_color *rgb, uint8_t alpha)
+{
+ if (rgb == NULL)
+ return CBGFX_ERROR_INVALID_PARAMETER;
+
+ blend.alpha = alpha;
+ blend.rgb = *rgb;
+
+ return CBGFX_SUCCESS;
+}
+
+void clear_blend(void)
+{
+ blend.alpha = 0;
+ blend.rgb.red = 0;
+ blend.rgb.green = 0;
+ blend.rgb.blue = 0;
+}
+
static void add_vectors(struct vector *out,
const struct vector *v1, const struct vector *v2)
{
@@ -85,13 +117,9 @@ static void add_fractions(struct fraction *out,
n = (int64_t)f1->n * f2->d + (int64_t)f2->n * f1->d;
d = (int64_t)f1->d * f2->d;
/* Simplest way to reduce the fraction until fitting in int32_t */
- shift = log2(MAX(ABS(n), ABS(d)) >> 31);
- if (shift > 0) {
- n >>= shift;
- d >>= shift;
- }
- out->n = n;
- out->d = d;
+ shift = log2(MAX(ABS(n), ABS(d)) >> 31) + 1;
+ out->n = n >> shift;
+ out->d = d >> shift;
}
static void add_scales(struct scale *out,
@@ -113,37 +141,58 @@ static int transform_vector(struct vector *out,
{
if (!is_valid_scale(a))
return CBGFX_ERROR_INVALID_PARAMETER;
- out->x = a->x.n * in->x / a->x.d + offset->x;
- out->y = a->y.n * in->y / a->y.d + offset->y;
+ out->x = (int64_t)a->x.n * in->x / a->x.d + offset->x;
+ out->y = (int64_t)a->y.n * in->y / a->y.d + offset->y;
return CBGFX_SUCCESS;
}
/*
* Returns 1 if v is exclusively within box, 0 if v is inclusively within box,
- * or -1 otherwise. Note that only the right and bottom edges are examined.
+ * or -1 otherwise.
*/
static int within_box(const struct vector *v, const struct rect *bound)
{
- if (v->x < bound->offset.x + bound->size.width &&
- v->y < bound->offset.y + bound->size.height)
+ if (v->x > bound->offset.x &&
+ v->y > bound->offset.y &&
+ v->x < bound->offset.x + bound->size.width &&
+ v->y < bound->offset.y + bound->size.height)
return 1;
- else if (v->x <= bound->offset.x + bound->size.width &&
- v->y <= bound->offset.y + bound->size.height)
+ else if (v->x >= bound->offset.x &&
+ v->y >= bound->offset.y &&
+ v->x <= bound->offset.x + bound->size.width &&
+ v->y <= bound->offset.y + bound->size.height)
return 0;
else
return -1;
}
+/*
+ * Helper function that applies color and opacity from blend struct
+ * into the color.
+ */
+static inline uint8_t apply_blend(uint8_t color, uint8_t blend_color)
+{
+ if (blend.alpha == 0 || color == blend_color)
+ return color;
+
+ return (color * (256 - blend.alpha) +
+ blend_color * blend.alpha) / 256;
+}
+
static inline uint32_t calculate_color(const struct rgb_color *rgb,
uint8_t invert)
{
uint32_t color = 0;
- color |= (rgb->red >> (8 - fbinfo->red_mask_size))
- << fbinfo->red_mask_pos;
- color |= (rgb->green >> (8 - fbinfo->green_mask_size))
- << fbinfo->green_mask_pos;
- color |= (rgb->blue >> (8 - fbinfo->blue_mask_size))
- << fbinfo->blue_mask_pos;
+
+ color |= (apply_blend(rgb->red, blend.rgb.red)
+ >> (8 - fbinfo->red_mask_size))
+ << fbinfo->red_mask_pos;
+ color |= (apply_blend(rgb->green, blend.rgb.green)
+ >> (8 - fbinfo->green_mask_size))
+ << fbinfo->green_mask_pos;
+ color |= (apply_blend(rgb->blue, blend.rgb.blue)
+ >> (8 - fbinfo->blue_mask_size))
+ << fbinfo->blue_mask_pos;
if (invert)
color ^= 0xffffffff;
return color;
@@ -468,33 +517,116 @@ int clear_screen(const struct rgb_color *rgb)
return CBGFX_SUCCESS;
}
-/*
- * Bi-linear Interpolation
- *
- * It estimates the value of a middle point (tx, ty) using the values from four
- * adjacent points (q00, q01, q10, q11).
- */
-static uint32_t bli(uint32_t q00, uint32_t q10, uint32_t q01, uint32_t q11,
- struct fraction *tx, struct fraction *ty)
+static int pal_to_rgb(uint8_t index, const struct bitmap_palette_element_v3 *pal,
+ size_t palcount, struct rgb_color *out)
{
- uint32_t r0 = (tx->n * q10 + (tx->d - tx->n) * q00) / tx->d;
- uint32_t r1 = (tx->n * q11 + (tx->d - tx->n) * q01) / tx->d;
- uint32_t p = (ty->n * r1 + (ty->d - ty->n) * r0) / ty->d;
- return p;
+ if (index >= palcount) {
+ LOG("Color index %d exceeds palette boundary\n", index);
+ return CBGFX_ERROR_BITMAP_DATA;
+ }
+
+ out->red = pal[index].red;
+ out->green = pal[index].green;
+ out->blue = pal[index].blue;
+ return CBGFX_SUCCESS;
+}
+
+/*
+ * We're using the Lanczos resampling algorithm to rescale images to a new size.
+ * Since output size is often not cleanly divisible by input size, an output
+ * pixel (ox,oy) corresponds to a point that lies in the middle between several
+ * input pixels (ix,iy), meaning that if you transformed the coordinates of the
+ * output pixel into the input image space, they would be fractional. To sample
+ * the color of this "virtual" pixel with fractional coordinates, we gather the
+ * 6x6 grid of nearest real input pixels in a sample array. Then we multiply the
+ * color values for each of those pixels (separately for red, green and blue)
+ * with a "weight" value that was calculated from the distance between that
+ * input pixel and the fractional output pixel coordinates. This is done for
+ * both X and Y dimensions separately. The combined weights for all 36 sample
+ * pixels add up to 1.0, so by adding up the multiplied color values we get the
+ * interpolated color for the output pixel.
+ *
+ * The CONFIG_LP_CBGFX_FAST_RESAMPLE option let's the user change the 'a'
+ * parameter from the Lanczos weight formula from 3 to 2, which effectively
+ * reduces the size of the sample array from 6x6 to 4x4. This is a bit faster
+ * but doesn't look as good. Most use cases should be fine without it.
+ */
+#if CONFIG(LP_CBGFX_FAST_RESAMPLE)
+#define LNCZ_A 2
+#else
+#define LNCZ_A 3
+#endif
+
+/*
+ * When walking the sample array we often need to start at a pixel close to our
+ * fractional output pixel (for convenience we choose the pixel on the top-left
+ * which corresponds to the integer parts of the output pixel coordinates) and
+ * then work our way outwards in both directions from there. Arrays in C must
+ * start at 0 but we'd really prefer indexes to go from -2 to 3 (for 6x6)
+ * instead, so that this "start pixel" could be 0. Since we cannot do that,
+ * define a constant for the index of that "0th" pixel instead.
+ */
+#define S0 (LNCZ_A - 1)
+
+/* The size of the sample array, which we need a lot. */
+#define SSZ (LNCZ_A * 2)
+
+/*
+ * This is implementing the Lanczos kernel according to:
+ * https://en.wikipedia.org/wiki/Lanczos_resampling
+ *
+ * / 1 if x = 0
+ * L(x) = < a * sin(pi * x) * sin(pi * x / a) / (pi^2 * x^2) if -a < x <= a
+ * \ 0 otherwise
+ */
+static fpmath_t lanczos_weight(fpmath_t in, int off)
+{
+ /*
+ * |in| is the output pixel coordinate scaled into the input pixel
+ * space. |off| is the offset in the sample array for the pixel whose
+ * weight we're calculating. (off - S0) is the distance from that
+ * sample pixel to the S0 pixel, and the fractional part of |in|
+ * (in - floor(in)) is by definition the distance between S0 and the
+ * output pixel.
+ *
+ * So (off - S0) - (in - floor(in)) is the distance from the sample
+ * pixel to S0 minus the distance from S0 to the output pixel, aka
+ * the distance from the sample pixel to the output pixel.
+ */
+ fpmath_t x = fpisub(off - S0, fpsubi(in, fpfloor(in)));
+
+ if (fpequals(x, fp(0)))
+ return fp(1);
+
+ /* x * 2 / a can save some instructions if a == 2 */
+ fpmath_t x2a = x;
+ if (LNCZ_A != 2)
+ x2a = fpmul(x, fpfrac(2, LNCZ_A));
+
+ fpmath_t x_times_pi = fpmul(x, fppi());
+
+ /*
+ * Rather than using sinr(pi*x), we leverage the "one-based" sine
+ * function (see ) with sin1(2*x) so that the pi is eliminated
+ * since multiplication by an integer is a slightly faster operation.
+ */
+ fpmath_t tmp = fpmuli(fpdiv(fpsin1(fpmuli(x, 2)), x_times_pi), LNCZ_A);
+ return fpdiv(fpmul(tmp, fpsin1(x2a)), x_times_pi);
}
static int draw_bitmap_v3(const struct vector *top_left,
- const struct scale *scale,
const struct vector *dim,
const struct vector *dim_org,
const struct bitmap_header_v3 *header,
const struct bitmap_palette_element_v3 *pal,
- const uint8_t *pixel_array,
- uint8_t invert)
+ const uint8_t *pixel_array, uint8_t invert)
{
const int bpp = header->bits_per_pixel;
int32_t dir;
struct vector p;
+ int32_t ox, oy; /* output (resampled) pixel coordinates */
+ int32_t ix, iy; /* input (source image) pixel coordinates */
+ int sx, sy; /* index into |sample| (not ringbuffer adjusted) */
if (header->compression) {
LOG("Compressed bitmaps are not supported\n");
@@ -508,10 +640,6 @@ static int draw_bitmap_v3(const struct vector *top_left,
LOG("Unsupported bits per pixel: %d\n", bpp);
return CBGFX_ERROR_BITMAP_FORMAT;
}
- if (scale->x.n == 0 || scale->y.n == 0) {
- LOG("Scaling out of range\n");
- return CBGFX_ERROR_SCALE_OUT_OF_RANGE;
- }
const int32_t y_stride = ROUNDUP(dim_org->width * bpp / 8, 4);
/*
@@ -530,63 +658,202 @@ static int draw_bitmap_v3(const struct vector *top_left,
p.y += dim->height - 1;
dir = -1;
}
- /*
- * Plot pixels scaled by the bilinear interpolation. We scan over the
- * image on canvas (using d) and find the corresponding pixel in the
- * bitmap data (using s0, s1).
- *
- * When d hits the right bottom corner, s0 also hits the right bottom
- * corner of the pixel array because that's how scale->x and scale->y
- * have been set. Since the pixel array size is already validated in
- * parse_bitmap_header_v3, s0 is guaranteed not to exceed pixel array
- * boundary.
- */
- struct vector s0, s1, d;
- struct fraction tx, ty;
- for (d.y = 0; d.y < dim->height; d.y++, p.y += dir) {
- s0.y = d.y * scale->y.d / scale->y.n;
- s1.y = s0.y;
- if (s1.y + 1 < dim_org->height)
- s1.y++;
- ty.d = scale->y.n;
- ty.n = (d.y * scale->y.d) % scale->y.n;
- const uint8_t *data0 = pixel_array + s0.y * y_stride;
- const uint8_t *data1 = pixel_array + s1.y * y_stride;
- p.x = top_left->x;
- for (d.x = 0; d.x < dim->width; d.x++, p.x++) {
- s0.x = d.x * scale->x.d / scale->x.n;
- s1.x = s0.x;
- if (s1.x + 1 < dim_org->width)
- s1.x++;
- tx.d = scale->x.n;
- tx.n = (d.x * scale->x.d) % scale->x.n;
- uint8_t c00 = data0[s0.x];
- uint8_t c10 = data0[s1.x];
- uint8_t c01 = data1[s0.x];
- uint8_t c11 = data1[s1.x];
- if (c00 >= header->colors_used
- || c10 >= header->colors_used
- || c01 >= header->colors_used
- || c11 >= header->colors_used) {
- LOG("Color index exceeds palette boundary\n");
- return CBGFX_ERROR_BITMAP_DATA;
+
+ /* Don't waste time resampling when the scale is 1:1. */
+ if (dim_org->width == dim->width && dim_org->height == dim->height) {
+ for (oy = 0; oy < dim->height; oy++, p.y += dir) {
+ p.x = top_left->x;
+ for (ox = 0; ox < dim->width; ox++, p.x++) {
+ struct rgb_color rgb;
+ if (pal_to_rgb(pixel_array[oy * y_stride + ox],
+ pal, header->colors_used, &rgb))
+ return CBGFX_ERROR_BITMAP_DATA;
+ set_pixel(&p, calculate_color(&rgb, invert));
}
- const struct rgb_color rgb = {
- .red = bli(pal[c00].red, pal[c10].red,
- pal[c01].red, pal[c11].red,
- &tx, &ty),
- .green = bli(pal[c00].green, pal[c10].green,
- pal[c01].green, pal[c11].green,
- &tx, &ty),
- .blue = bli(pal[c00].blue, pal[c10].blue,
- pal[c01].blue, pal[c11].blue,
- &tx, &ty),
+ }
+ return CBGFX_SUCCESS;
+ }
+
+ /* Precalculate the X-weights for every possible ox so that we only have
+ to multiply weights together in the end. */
+ fpmath_t (*weight_x)[SSZ] = malloc(sizeof(fpmath_t) * SSZ * dim->width);
+ if (!weight_x)
+ return CBGFX_ERROR_UNKNOWN;
+ for (ox = 0; ox < dim->width; ox++) {
+ for (sx = 0; sx < SSZ; sx++) {
+ fpmath_t ixfp = fpfrac(ox * dim_org->width, dim->width);
+ weight_x[ox][sx] = lanczos_weight(ixfp, sx);
+ }
+ }
+
+ /*
+ * For every sy in the sample array, we directly cache a pointer into
+ * the .BMP pixel array for the start of the corresponding line. On the
+ * edges of the image (where we don't have any real pixels to fill all
+ * lines in the sample array), we just reuse the last valid lines inside
+ * the image for all lines that would lie outside.
+ */
+ const uint8_t *ypix[SSZ];
+ for (sy = 0; sy < SSZ; sy++) {
+ if (sy <= S0)
+ ypix[sy] = pixel_array;
+ else if (sy - S0 >= dim_org->height)
+ ypix[sy] = ypix[sy - 1];
+ else
+ ypix[sy] = &pixel_array[y_stride * (sy - S0)];
+ }
+
+ /* iy and ix track the input pixel corresponding to sample[S0][S0]. */
+ iy = 0;
+ for (oy = 0; oy < dim->height; oy++, p.y += dir) {
+ struct rgb_color sample[SSZ][SSZ];
+
+ /* Like with X weights, we also cache all Y weights. */
+ fpmath_t iyfp = fpfrac(oy * dim_org->height, dim->height);
+ fpmath_t weight_y[SSZ];
+ for (sy = 0; sy < SSZ; sy++)
+ weight_y[sy] = lanczos_weight(iyfp, sy);
+
+ /*
+ * If we have a new input pixel line between the last oy and
+ * this one, we have to adjust iy forward. When upscaling, this
+ * is not always the case for each new output line. When
+ * downscaling, we may even cross more than one line per output
+ * pixel.
+ */
+ while (fpfloor(iyfp) > iy) {
+ iy++;
+
+ /* Shift ypix array up to center around next iy line. */
+ for (sy = 0; sy < SSZ - 1; sy++)
+ ypix[sy] = ypix[sy + 1];
+
+ /* Calculate the last ypix that is being shifted in,
+ but beware of reaching the end of the input image. */
+ if (iy + LNCZ_A < dim_org->height)
+ ypix[SSZ - 1] = &pixel_array[y_stride *
+ (iy + LNCZ_A)];
+ }
+
+ /*
+ * Initialize the sample array for this line. For pixels to the
+ * left of S0 there are no corresponding input pixels so just
+ * copy the S0 values over.
+ *
+ * Also initialize the equals counter, which counts how many of
+ * the latest pixels were exactly equal. We know the columns
+ * left of S0 must be equal to S0, so start with that number.
+ */
+ int equals = S0 * SSZ;
+ uint8_t last_equal = ypix[0][0];
+ for (sy = 0; sy < SSZ; sy++) {
+ for (sx = S0; sx < SSZ; sx++) {
+ if (sx >= dim_org->width) {
+ sample[sx][sy] = sample[sx - 1][sy];
+ equals++;
+ continue;
+ }
+ uint8_t i = ypix[sy][sx - S0];
+ if (pal_to_rgb(i, pal, header->colors_used,
+ &sample[sx][sy]))
+ goto bitmap_error;
+ if (i == last_equal) {
+ equals++;
+ } else {
+ last_equal = i;
+ equals = 1;
+ }
+ }
+ for (sx = S0 - 1; sx >= 0; sx--)
+ sample[sx][sy] = sample[S0][sy];
+ }
+
+ ix = 0;
+ p.x = top_left->x;
+ for (ox = 0; ox < dim->width; ox++, p.x++) {
+ /* Adjust ix forward, same as iy above. */
+ fpmath_t ixfp = fpfrac(ox * dim_org->width, dim->width);
+ while (fpfloor(ixfp) > ix) {
+ ix++;
+
+ /*
+ * We want to reuse the sample columns we
+ * already have, but we don't want to copy them
+ * all around for every new column either.
+ * Instead, treat the X dimension of the sample
+ * array like a ring buffer indexed by ix. rx is
+ * the ringbuffer-adjusted offset of the new
+ * column in sample (the rightmost one) we're
+ * trying to fill.
+ */
+ int rx = (SSZ - 1 + ix) % SSZ;
+ for (sy = 0; sy < SSZ; sy++) {
+ if (ix + LNCZ_A >= dim_org->width) {
+ sample[rx][sy] = sample[(SSZ - 2
+ + ix) % SSZ][sy];
+ equals++;
+ continue;
+ }
+ uint8_t i = ypix[sy][ix + LNCZ_A];
+ if (i == last_equal) {
+ if (equals++ >= (SSZ * SSZ))
+ continue;
+ } else {
+ last_equal = i;
+ equals = 1;
+ }
+ if (pal_to_rgb(i, pal,
+ header->colors_used,
+ &sample[rx][sy]))
+ goto bitmap_error;
+ }
+ }
+
+ /* If all pixels in sample are equal, fast path. */
+ if (equals >= (SSZ * SSZ)) {
+ set_pixel(&p, calculate_color(&sample[0][0],
+ invert));
+ continue;
+ }
+
+ fpmath_t red = fp(0);
+ fpmath_t green = fp(0);
+ fpmath_t blue = fp(0);
+ for (sy = 0; sy < SSZ; sy++) {
+ for (sx = 0; sx < SSZ; sx++) {
+ int rx = (sx + ix) % SSZ;
+ fpmath_t weight = fpmul(weight_x[ox][sx],
+ weight_y[sy]);
+ red = fpadd(red, fpmuli(weight,
+ sample[rx][sy].red));
+ green = fpadd(green, fpmuli(weight,
+ sample[rx][sy].green));
+ blue = fpadd(blue, fpmuli(weight,
+ sample[rx][sy].blue));
+ }
+ }
+
+ /*
+ * Weights *should* sum up to 1.0 (making this not
+ * necessary) but just to hedge against rounding errors
+ * we should clamp color values to their legal limits.
+ */
+ struct rgb_color rgb = {
+ .red = MAX(0, MIN(UINT8_MAX, fpround(red))),
+ .green = MAX(0, MIN(UINT8_MAX, fpround(green))),
+ .blue = MAX(0, MIN(UINT8_MAX, fpround(blue))),
};
+
set_pixel(&p, calculate_color(&rgb, invert));
}
}
+ free(weight_x);
return CBGFX_SUCCESS;
+
+bitmap_error:
+ free(weight_x);
+ return CBGFX_ERROR_BITMAP_DATA;
}
static int get_bitmap_file_header(const void *bitmap, size_t size,
@@ -780,7 +1047,6 @@ int draw_bitmap(const void *bitmap, size_t size,
const struct bitmap_palette_element_v3 *palette;
const uint8_t *pixel_array;
struct vector top_left, dim, dim_org;
- struct scale scale;
int rv;
const uint8_t pivot = flags & PIVOT_MASK;
const uint8_t invert = (flags & INVERT_COLORS) >> INVERT_SHIFT;
@@ -799,12 +1065,6 @@ int draw_bitmap(const void *bitmap, size_t size,
if (rv)
return rv;
- /* Calculate self scale */
- scale.x.n = dim.width;
- scale.x.d = dim_org.width;
- scale.y.n = dim.height;
- scale.y.d = dim_org.height;
-
/* Calculate coordinate */
rv = calculate_position(&dim, pos_rel, pivot, &top_left);
if (rv)
@@ -816,7 +1076,7 @@ int draw_bitmap(const void *bitmap, size_t size,
return rv;
}
- return draw_bitmap_v3(&top_left, &scale, &dim, &dim_org,
+ return draw_bitmap_v3(&top_left, &dim, &dim_org,
&header, palette, pixel_array, invert);
}
@@ -827,7 +1087,6 @@ int draw_bitmap_direct(const void *bitmap, size_t size,
const struct bitmap_palette_element_v3 *palette;
const uint8_t *pixel_array;
struct vector dim;
- struct scale scale;
int rv;
if (cbgfx_init())
@@ -839,19 +1098,13 @@ int draw_bitmap_direct(const void *bitmap, size_t size,
if (rv)
return rv;
- /* Calculate self scale */
- scale.x.n = 1;
- scale.x.d = 1;
- scale.y.n = 1;
- scale.y.d = 1;
-
rv = check_boundary(top_left, &dim, &screen);
if (rv) {
LOG("Bitmap image exceeds screen boundary\n");
return rv;
}
- return draw_bitmap_v3(top_left, &scale, &dim, &dim,
+ return draw_bitmap_v3(top_left, &dim, &dim,
&header, palette, pixel_array, 0);
}
diff --git a/payloads/libpayload/gdb/stub.c b/payloads/libpayload/gdb/stub.c
index 694577e8d7..019f27fcac 100644
--- a/payloads/libpayload/gdb/stub.c
+++ b/payloads/libpayload/gdb/stub.c
@@ -73,7 +73,8 @@ static void gdb_output_write(const void *buffer, size_t count)
if (!gdb_state.resumed) {
/* Must be a die_if() in GDB (or a bug), so bail out and die. */
gdb_exit(-1);
- video_console_init();
+ if (CONFIG(LP_VIDEO_CONSOLE))
+ video_console_init();
puts("GDB died, redirecting its last words to the screen:\n");
console_write(buffer, count);
} else {
diff --git a/payloads/libpayload/include/cbgfx.h b/payloads/libpayload/include/cbgfx.h
index 869f272722..84e76f26d1 100644
--- a/payloads/libpayload/include/cbgfx.h
+++ b/payloads/libpayload/include/cbgfx.h
@@ -210,3 +210,33 @@ int draw_bitmap_direct(const void *bitmap, size_t size,
* in the original size are returned.
*/
int get_bitmap_dimension(const void *bitmap, size_t sz, struct scale *dim_rel);
+
+/**
+ * Setup alpha and rgb values for alpha blending. When alpha is != 0,
+ * this enables a translucent layer of color (defined by rgb) to be
+ * blended at a given translucency (alpha) to all things drawn. Call
+ * clear_blend() to disable alpha blending.
+ *
+ * @param[in] rgb Color for transparency
+ * @param[in] alpha Opacity of color, from 0-255 where
+ * 0 = completely transparent (no blending)
+ * 255 = max alpha argument
+ *
+ * @return CBGFX_* error codes
+ */
+int set_blend(const struct rgb_color *rgb, uint8_t alpha);
+
+/**
+ * Clear alpha and rgb values, thus disabling any alpha blending.
+ *
+ * @return CBGFX_* error codes
+ */
+void clear_blend(void);
+
+/**
+ * For calculating Alpha value from % opacity
+ * For reference:
+ * 255 = max alpha argument
+ * 0 = min alpha argument, 0% opacity
+ */
+#define ALPHA(percentage) MIN(255, (256 * percentage / 100))
diff --git a/payloads/libpayload/include/fpmath.h b/payloads/libpayload/include/fpmath.h
new file mode 100644
index 0000000000..48e900402e
--- /dev/null
+++ b/payloads/libpayload/include/fpmath.h
@@ -0,0 +1,234 @@
+/*
+ *
+ * Copyright (C) 2020 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include
+
+/*
+ * This file implements operations for a simple 32.32 fixed-point math type.
+ * This is intended for speed-critical stuff (e.g. graphics) so there are
+ * intentionally no overflow checks or assertions, and operations are written
+ * to prefer speed over precision (e.g. multiplying by 1 may lose precision).
+ * For best results, only use for applications where 16.16 would fit.
+ */
+
+typedef struct { /* wrap in struct to prevent direct access */
+ int64_t v;
+} fpmath_t;
+
+#define FPMATH_SHIFT 32 /* define where to place the decimal point */
+
+/* Turn an integer into an fpmath_t. */
+static inline fpmath_t fp(int32_t a)
+{
+ return (fpmath_t){ .v = (int64_t)a << FPMATH_SHIFT };
+}
+
+/* Create an fpmath_t from a fraction. (numerator / denominator) */
+static inline fpmath_t fpfrac(int32_t numerator, int32_t denominator)
+{
+ return (fpmath_t){ .v = ((int64_t)numerator << FPMATH_SHIFT) / denominator };
+}
+
+/* Turn an fpmath_t back into an integer, rounding towards -INF. */
+static inline int32_t fpfloor(fpmath_t a)
+{
+ return a.v >> FPMATH_SHIFT;
+}
+
+/* Turn an fpmath_t back into an integer, rounding towards nearest. */
+static inline int32_t fpround(fpmath_t a)
+{
+ return (a.v + ((int64_t)1 << (FPMATH_SHIFT - 1))) >> FPMATH_SHIFT;
+}
+
+/* Turn an fpmath_t back into an integer, rounding towards +INF. */
+static inline int32_t fpceil(fpmath_t a)
+{
+ return (a.v + ((int64_t)1 << FPMATH_SHIFT) - 1) >> FPMATH_SHIFT;
+}
+
+/* Add two fpmath_t. (a + b) */
+static inline fpmath_t fpadd(fpmath_t a, fpmath_t b)
+{
+ return (fpmath_t){ .v = a.v + b.v };
+}
+
+/* Add an fpmath_t and an integer. (a + b) */
+static inline fpmath_t fpaddi(fpmath_t a, int32_t b)
+{
+ return (fpmath_t){ .v = a.v + ((int64_t)b << FPMATH_SHIFT) };
+}
+
+/* Subtract one fpmath_t from another. (a + b) */
+static inline fpmath_t fpsub(fpmath_t a, fpmath_t b)
+{
+ return (fpmath_t){ .v = a.v - b.v };
+}
+
+/* Subtract an integer from an fpmath_t. (a - b) */
+static inline fpmath_t fpsubi(fpmath_t a, int32_t b)
+{
+ return (fpmath_t){ .v = a.v - ((int64_t)b << FPMATH_SHIFT) };
+}
+
+/* Subtract an fpmath_t from an integer. (a - b) */
+static inline fpmath_t fpisub(int32_t a, fpmath_t b)
+{
+ return (fpmath_t){ .v = ((int64_t)a << FPMATH_SHIFT) - b.v };
+}
+
+/* Multiply two fpmath_t. (a * b)
+ Looses 16 bits fractional precision on each. */
+static inline fpmath_t fpmul(fpmath_t a, fpmath_t b)
+{
+ return (fpmath_t){ .v = (a.v >> (FPMATH_SHIFT/2)) * (b.v >> (FPMATH_SHIFT/2)) };
+}
+
+/* Multiply an fpmath_t and an integer. (a * b) */
+static inline fpmath_t fpmuli(fpmath_t a, int32_t b)
+{
+ return (fpmath_t){ .v = a.v * b };
+}
+
+/* Divide an fpmath_t by another. (a / b)
+ Truncates integral part of a to 16 bits! Careful with this one! */
+static inline fpmath_t fpdiv(fpmath_t a, fpmath_t b)
+{
+ return (fpmath_t){ .v = (a.v << (FPMATH_SHIFT/2)) / (b.v >> (FPMATH_SHIFT/2)) };
+}
+
+/* Divide an fpmath_t by an integer. (a / b) */
+static inline fpmath_t fpdivi(fpmath_t a, int32_t b)
+{
+ return (fpmath_t){ .v = a.v / b };
+}
+
+/* Calculate absolute value of an fpmath_t. (ABS(a)) */
+static inline fpmath_t fpabs(fpmath_t a)
+{
+ return (fpmath_t){ .v = (a.v < 0 ? -a.v : a.v) };
+}
+
+/* Return true iff two fpmath_t are exactly equal. (a == b)
+ Like with floats, you probably don't want to use this most of the time. */
+static inline int fpequals(fpmath_t a, fpmath_t b)
+{
+ return a.v == b.v;
+}
+
+/* Return true iff one fpmath_t is less than another. (a < b) */
+static inline int fpless(fpmath_t a, fpmath_t b)
+{
+ return a.v < b.v;
+}
+
+/* Return true iff one fpmath_t is more than another. (a > b) */
+static inline int fpmore(fpmath_t a, fpmath_t b)
+{
+ return a.v > b.v;
+}
+
+/* Return the smaller of two fpmath_t. (MIN(a, b)) */
+static inline fpmath_t fpmin(fpmath_t a, fpmath_t b)
+{
+ if (a.v < b.v)
+ return a;
+ else
+ return b;
+}
+
+/* Return the larger of two fpmath_t. (MAX(a, b)) */
+static inline fpmath_t fpmax(fpmath_t a, fpmath_t b)
+{
+ if (a.v > b.v)
+ return a;
+ else
+ return b;
+}
+
+/* Return the constant PI as an fpmath_t. */
+static inline fpmath_t fppi(void)
+{
+ /* Rounded (uint64_t)(M_PI * (1UL << 60)) to nine hex digits. */
+ return (fpmath_t){ .v = 0x3243f6a89 };
+}
+
+/*
+ * Returns the "one-based" sine of an fpmath_t, meaning the input is interpreted as if the range
+ * 0.0-1.0 corresponded to 0.0-PI/2 for radians. This is mostly here as the base primitives for
+ * the other trig stuff, but it may be useful to use directly if your input value already needs
+ * to be multiplied by some factor of PI and you want to save the instructions (and precision)
+ * for multiplying it in just so that the trig functions can divide it right out again.
+ */
+fpmath_t fpsin1(fpmath_t x);
+
+/* Returns the "one-based" cosine of an fpmath_t (analogous definition to fpsin1()). */
+static inline fpmath_t fpcos1(fpmath_t x)
+{
+ return fpsin1(fpaddi(x, 1));
+}
+
+/* Returns the sine of an fpmath_t interpreted as radians. */
+static inline fpmath_t fpsinr(fpmath_t radians)
+{
+ return fpsin1(fpdiv(radians, fpdivi(fppi(), 2)));
+}
+
+/* Returns the sine of an fpmath_t interpreted as degrees. */
+static inline fpmath_t fpsind(fpmath_t degrees)
+{
+ return fpsin1(fpdivi(degrees, 90));
+}
+
+/* Returns the cosine of an fpmath_t interpreted as radians. */
+static inline fpmath_t fpcosr(fpmath_t radians)
+{
+ return fpcos1(fpdiv(radians, fpdivi(fppi(), 2)));
+}
+
+/* Returns the cosine of an fpmath_t interpreted as degrees. */
+static inline fpmath_t fpcosd(fpmath_t degrees)
+{
+ return fpcos1(fpdivi(degrees, 90));
+}
+
+/* Returns the tangent of an fpmath_t interpreted as radians.
+ No guard rails, don't call this at the poles or you'll divide by 0! */
+static inline fpmath_t fptanr(fpmath_t radians)
+{
+ fpmath_t one_based = fpdiv(radians, fpdivi(fppi(), 2));
+ return fpdiv(fpsin1(one_based), fpcos1(one_based));
+}
+
+/* Returns the tangent of an fpmath_t interpreted as degrees.
+ No guard rails, don't call this at the poles or you'll divide by 0! */
+static inline fpmath_t fptand(fpmath_t degrees)
+{
+ fpmath_t one_based = fpdivi(degrees, 90);
+ return fpdiv(fpsin1(one_based), fpcos1(one_based));
+}
diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h
index 8f3169ef09..f79fc27711 100644
--- a/payloads/libpayload/include/usb/usb.h
+++ b/payloads/libpayload/include/usb/usb.h
@@ -344,6 +344,13 @@ static inline void usb_debug(const char *fmt, ...)
#endif
}
+/**
+ * To be implemented by libpayload-client. It's called by the USB
+ * stack just before iterating over known devices to poll them for
+ * status change.
+ */
+void __attribute__((weak)) usb_poll_prepare (void);
+
/**
* To be implemented by libpayload-client. It's called by the USB stack
* when a new USB device is found which isn't claimed by a built in driver,
diff --git a/payloads/libpayload/include/x86/arch/apic.h b/payloads/libpayload/include/x86/arch/apic.h
index 3c9877cb54..eedf1b4b2b 100644
--- a/payloads/libpayload/include/x86/arch/apic.h
+++ b/payloads/libpayload/include/x86/arch/apic.h
@@ -40,5 +40,7 @@ uint8_t apic_id(void);
void apic_eoi(uint8_t vector);
void apic_delay(unsigned int usec);
+void apic_start_delay(unsigned int usec);
+void apic_wait_delay(void);
#endif /* __ARCH_X86_INCLUDES_ARCH_APIC_H__ */
diff --git a/payloads/libpayload/libc/Makefile.inc b/payloads/libpayload/libc/Makefile.inc
index 2999023da8..f9006ae471 100644
--- a/payloads/libpayload/libc/Makefile.inc
+++ b/payloads/libpayload/libc/Makefile.inc
@@ -38,3 +38,4 @@ libc-$(CONFIG_LP_LIBC) += hexdump.c
libc-$(CONFIG_LP_LIBC) += die.c
libc-$(CONFIG_LP_LIBC) += coreboot.c
libc-$(CONFIG_LP_LIBC) += fmap.c
+libc-$(CONFIG_LP_LIBC) += fpmath.c
diff --git a/payloads/libpayload/libc/fpmath.c b/payloads/libpayload/libc/fpmath.c
new file mode 100644
index 0000000000..89a99f86aa
--- /dev/null
+++ b/payloads/libpayload/libc/fpmath.c
@@ -0,0 +1,149 @@
+/*
+ *
+ * Copyright (C) 2020 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include
+
+/*
+ * This table represents one ascending arc of the sine curve, i.e. the values sin(x) for
+ * 0.0 <= x < PI/2. We divide that range into 256 equidistant points and store the corresponding
+ * sine values for those points. Since the values lie in the range 0.0 <= sin(x) < 1.0, in order
+ * to make the most use of the bytes we store, we map them to the range from 0 to 2^16.
+ *
+ * Generated with:
+ *
+ * for (i = 0; i < 256; i++) {
+ * double s = sin((double)i * M_PI / 2 / 256);
+ * uint16_t u = fmin(round(s * (1 << 16)), (1 << 16));
+ * printf("0x%04x,%s", u, i % 8 == 7 ? "\n" : " ");
+ * }
+ *
+ * In order to make sure the second access for linear interpolation (see below) cannot overrun
+ * the array, we stick a final 257th value 0xffff at the end. (It should really be 0x10000,
+ * but... this is good enough.)
+ */
+
+/* Table size as power of two. If we ever want to change the table size, updating this value
+ should make everything else fall back into place again (hopefully). */
+#define TP2 8
+
+static const uint16_t fpsin_table[(1 << TP2) + 1] = {
+ 0x0000, 0x0192, 0x0324, 0x04b6, 0x0648, 0x07da, 0x096c, 0x0afe,
+ 0x0c90, 0x0e21, 0x0fb3, 0x1144, 0x12d5, 0x1466, 0x15f7, 0x1787,
+ 0x1918, 0x1aa8, 0x1c38, 0x1dc7, 0x1f56, 0x20e5, 0x2274, 0x2402,
+ 0x2590, 0x271e, 0x28ab, 0x2a38, 0x2bc4, 0x2d50, 0x2edc, 0x3067,
+ 0x31f1, 0x337c, 0x3505, 0x368e, 0x3817, 0x399f, 0x3b27, 0x3cae,
+ 0x3e34, 0x3fba, 0x413f, 0x42c3, 0x4447, 0x45cb, 0x474d, 0x48cf,
+ 0x4a50, 0x4bd1, 0x4d50, 0x4ecf, 0x504d, 0x51cb, 0x5348, 0x54c3,
+ 0x563e, 0x57b9, 0x5932, 0x5aaa, 0x5c22, 0x5d99, 0x5f0f, 0x6084,
+ 0x61f8, 0x636b, 0x64dd, 0x664e, 0x67be, 0x692d, 0x6a9b, 0x6c08,
+ 0x6d74, 0x6edf, 0x7049, 0x71b2, 0x731a, 0x7480, 0x75e6, 0x774a,
+ 0x78ad, 0x7a10, 0x7b70, 0x7cd0, 0x7e2f, 0x7f8c, 0x80e8, 0x8243,
+ 0x839c, 0x84f5, 0x864c, 0x87a1, 0x88f6, 0x8a49, 0x8b9a, 0x8ceb,
+ 0x8e3a, 0x8f88, 0x90d4, 0x921f, 0x9368, 0x94b0, 0x95f7, 0x973c,
+ 0x9880, 0x99c2, 0x9b03, 0x9c42, 0x9d80, 0x9ebc, 0x9ff7, 0xa130,
+ 0xa268, 0xa39e, 0xa4d2, 0xa605, 0xa736, 0xa866, 0xa994, 0xaac1,
+ 0xabeb, 0xad14, 0xae3c, 0xaf62, 0xb086, 0xb1a8, 0xb2c9, 0xb3e8,
+ 0xb505, 0xb620, 0xb73a, 0xb852, 0xb968, 0xba7d, 0xbb8f, 0xbca0,
+ 0xbdaf, 0xbebc, 0xbfc7, 0xc0d1, 0xc1d8, 0xc2de, 0xc3e2, 0xc4e4,
+ 0xc5e4, 0xc6e2, 0xc7de, 0xc8d9, 0xc9d1, 0xcac7, 0xcbbc, 0xccae,
+ 0xcd9f, 0xce8e, 0xcf7a, 0xd065, 0xd14d, 0xd234, 0xd318, 0xd3fb,
+ 0xd4db, 0xd5ba, 0xd696, 0xd770, 0xd848, 0xd91e, 0xd9f2, 0xdac4,
+ 0xdb94, 0xdc62, 0xdd2d, 0xddf7, 0xdebe, 0xdf83, 0xe046, 0xe107,
+ 0xe1c6, 0xe282, 0xe33c, 0xe3f4, 0xe4aa, 0xe55e, 0xe610, 0xe6bf,
+ 0xe76c, 0xe817, 0xe8bf, 0xe966, 0xea0a, 0xeaab, 0xeb4b, 0xebe8,
+ 0xec83, 0xed1c, 0xedb3, 0xee47, 0xeed9, 0xef68, 0xeff5, 0xf080,
+ 0xf109, 0xf18f, 0xf213, 0xf295, 0xf314, 0xf391, 0xf40c, 0xf484,
+ 0xf4fa, 0xf56e, 0xf5df, 0xf64e, 0xf6ba, 0xf724, 0xf78c, 0xf7f1,
+ 0xf854, 0xf8b4, 0xf913, 0xf96e, 0xf9c8, 0xfa1f, 0xfa73, 0xfac5,
+ 0xfb15, 0xfb62, 0xfbad, 0xfbf5, 0xfc3b, 0xfc7f, 0xfcc0, 0xfcfe,
+ 0xfd3b, 0xfd74, 0xfdac, 0xfde1, 0xfe13, 0xfe43, 0xfe71, 0xfe9c,
+ 0xfec4, 0xfeeb, 0xff0e, 0xff30, 0xff4e, 0xff6b, 0xff85, 0xff9c,
+ 0xffb1, 0xffc4, 0xffd4, 0xffe1, 0xffec, 0xfff5, 0xfffb, 0xffff,
+ 0xffff,
+};
+
+/* x is in the "one-based" scale, so x == 1.0 is the top of the curve (PI/2 in radians). */
+fpmath_t fpsin1(fpmath_t x)
+{
+ /*
+ * When doing things like sin(x)/x, tiny errors can quickly become big problems, so just
+ * returning the nearest table value we have is not good enough (our fpmath_t has four
+ * times as much fractional precision as the sine table). A good and fast enough remedy
+ * is to linearly interpolate between the two nearest table values v1 and v2.
+ * (There are better but slower interpolations so we intentionally choose this one.)
+ *
+ * Most of this math can be done in 32 bits (because we're just operating on fractional
+ * parts in the 0.0-1.0 range anyway), so to help our 32-bit platforms a bit we keep it
+ * there as long as possible and only go back to an int64_t at the end.
+ */
+ uint32_t v1, v2;
+
+ /*
+ * Since x is "one-based" the part that maps to our curve (0.0 to PI/2 in radians) just
+ * happens to be exactly the fractional part of the fpmath_t, easy to extract.
+ */
+ int index = (x.v >> (FPMATH_SHIFT - TP2)) & ((1 << TP2) - 1);
+
+ /*
+ * In our one-based input domain, the period of the sine function is exactly 4.0. By
+ * extracting the first bit of the integral part of the fpmath_t we can check if it is
+ * odd-numbered (1.0-2.0, 3.0-4.0, etc.) or even numbered (0.0-1.0, 2.0-3.0, etc.), and
+ * that tells us whether we are in a "rising" (away from 0) or "falling" (towards 0)
+ * part of the sine curve. Our table curve is rising, so for the falling parts we have
+ * to mirror the curve horizontally by using the complement of our input index.
+ */
+ if (x.v & ((int64_t)1 << FPMATH_SHIFT)) {
+ v1 = fpsin_table[(1 << TP2) - index];
+ v2 = fpsin_table[(1 << TP2) - index - 1];
+ } else {
+ v1 = fpsin_table[index];
+ v2 = fpsin_table[index + 1];
+ }
+
+ /*
+ * Linear interpolation: sin(x) is interpolated as the closest number sin(x0) to the
+ * left of x we have in our table, plus the distance of that value to the closest number
+ * to the right of x (sin(x1)) times the fractional distance of x to x0. Since the table
+ * is conveniently exactly 256 values, x0 is exactly the upper 8 bits of the fractional
+ * part of x, meaning all fractional bits below that represent exactly the distance we
+ * need to interpolate over. (There are 24 of them but we need to multiply them with
+ * 16-bit table values to fit exactly 32 bits, so we discard the lowest 8 bits.)
+ */
+ uint32_t val = (v1 << (FPMATH_SHIFT - 16)) +
+ (v2 - v1) * ((x.v >> (16 - TP2)) & 0xffff);
+
+ /*
+ * Just like the first integral bit told us whether we need to mirror horizontally, the
+ * second can tell us to mirror vertically. In 2.0-4.0, 6.0-8.0, etc. of the input range
+ * the sine is negative, and in 0.0-2.0, 4.0-6.0, etc. it is positive.
+ */
+ if (x.v & ((int64_t)2 << FPMATH_SHIFT))
+ return (fpmath_t){ .v = -(int64_t)val };
+ else
+ return (fpmath_t){ .v = val };
+}
diff --git a/src/Kconfig b/src/Kconfig
index 2a2a144235..a4c2fa6010 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -234,6 +234,26 @@ config USE_AMD_BLOBS
Note that for some products, omitting PSP, SMU images, or other items
may result in a nonbooting coreboot.rom.
+config USE_QC_BLOBS
+ bool "Allow QC blobs repository (selecting this agrees to the license!)"
+ depends on USE_BLOBS
+ help
+ This draws in the qc_blobs repository, which contains binary files
+ distributed by Qualcomm that are required to build firmware for
+ certain Qualcomm SoCs (including QcLib, QC-SEC, qtiseclib and QUP
+ firmware). If you say Y here you are implicitly agreeing to the
+ Qualcomm license agreement which can be found at:
+ https://review.coreboot.org/cgit/qc_blobs.git/tree/LICENSE
+
+ *****************************************************
+ PLEASE MAKE SURE YOU READ AND AGREE TO ALL TERMS IN
+ ABOVE LICENSE AGREEMENT BEFORE SELECTING THIS OPTION!
+ *****************************************************
+
+ Not selecting this option means certain Qualcomm SoCs and related
+ mainboards cannot be built and will be hidden from the "Mainboards"
+ section.
+
config COVERAGE
bool "Code coverage support"
depends on COMPILER_GCC
@@ -250,20 +270,9 @@ config UBSAN
say N because it adds a small performance penalty and may abort
on code that happens to work in spite of the UB.
-config RELOCATABLE_RAMSTAGE
- bool
- default y if ARCH_X86
- select RELOCATABLE_MODULES
- help
- The reloctable ramstage support allows for the ramstage to be built
- as a relocatable module. The stage loader can identify a place
- out of the OS way so that copying memory is unnecessary during an S3
- wake. When selecting this option the romstage is responsible for
- determing a stack location to use for loading the ramstage.
-
choice
prompt "Stage Cache for ACPI S3 resume"
- default NO_STAGE_CACHE if !HAVE_ACPI_RESUME || !RELOCATABLE_RAMSTAGE
+ default NO_STAGE_CACHE if !HAVE_ACPI_RESUME
default TSEG_STAGE_CACHE if SMM_TSEG
config NO_STAGE_CACHE
@@ -323,6 +332,33 @@ config BOOTSPLASH_FILE
The path and filename of the file to use as graphical bootsplash
screen. The file format has to be jpg.
+config FW_CONFIG
+ bool "Firmware Configuration Probing"
+ default n
+ help
+ Enable support for probing devices with fw_config. This is a simple
+ bitmask broken into fields and options for probing.
+
+config FW_CONFIG_SOURCE_CBFS
+ bool "Obtain Firmware Configuration value from CBFS"
+ depends on FW_CONFIG
+ default n
+ help
+ With this option enabled coreboot will look for the 32bit firmware
+ configuration value in CBFS at the selected prefix with the file name
+ "fw_config". This option will override other sources and allow the
+ local image to preempt the mainboard selected source.
+
+config FW_CONFIG_SOURCE_CHROMEEC_CBI
+ bool "Obtain Firmware Configuration value from Google Chrome EC CBI"
+ depends on FW_CONFIG && EC_GOOGLE_CHROMEEC
+ default n
+ help
+ This option tells coreboot to read the firmware configuration value
+ from the Google Chrome Embedded Controller CBI interface. This source
+ is not tried if FW_CONFIG_SOURCE_CBFS is enabled and the value was
+ found in CBFS.
+
config HAVE_RAMPAYLOAD
bool
@@ -390,7 +426,7 @@ config OVERRIDE_DEVICETREE
config FMDFILE
string "fmap description file in fmd format"
- default "src/mainboard/$(CONFIG_MAINBOARD_DIR)/chromeos.fmd" if CHROMEOS
+ default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/chromeos.fmd" if CHROMEOS
default ""
help
The build system creates a default FMAP from ROM_SIZE and CBFS_SIZE,
@@ -529,7 +565,6 @@ source "src/console/Kconfig"
config HAVE_ACPI_RESUME
bool
default n
- depends on RELOCATABLE_RAMSTAGE
config DISABLE_ACPI_HIBERNATE
bool
@@ -628,10 +663,6 @@ config HAVE_PIRQ_TABLE
Whether or not the PIRQ table is actually generated by coreboot
is configurable by the user via GENERATE_PIRQ_TABLE.
-config COMMON_FADT
- bool
- default n
-
config ACPI_NHLT
bool
default n
@@ -707,19 +738,15 @@ config MAINBOARD_SMBIOS_PRODUCT_NAME
help
Override the default Product name stored in SMBIOS structures.
-config SMBIOS_ENCLOSURE_TYPE
- hex
- depends on GENERATE_SMBIOS_TABLES
- default 0x09 if SYSTEM_TYPE_LAPTOP
- default 0x1e if SYSTEM_TYPE_TABLET
- default 0x1f if SYSTEM_TYPE_CONVERTIBLE
- default 0x20 if SYSTEM_TYPE_DETACHABLE
- default 0x03
+config VPD_SMBIOS_VERSION
+ bool "Populates SMBIOS type 0 version from the VPD_RO variable 'firmware_version'"
+ default n
+ depends on VPD && GENERATE_SMBIOS_TABLES
help
- System Enclosure or Chassis Types as defined in SMBIOS specification.
- The default value is SMBIOS_ENCLOSURE_DESKTOP (0x03) but laptop,
- convertible, or tablet enclosure will be used if the appropriate
- system type is selected.
+ Selecting this option will read firmware_version from
+ VPD_RO and override SMBIOS type 0 version. One special
+ scenario of using this feature is to assign a BIOS version
+ to a coreboot image without the need to rebuild from source.
endmenu
@@ -820,6 +847,10 @@ config DEBUG_SMI
If unsure, say N.
+config DEBUG_PERIODIC_SMI
+ bool "Trigger SMI periodically"
+ depends on DEBUG_SMI
+
# Only visible if debug level is DEBUG (7) or SPEW (8) as it does additional
# printk(BIOS_DEBUG, ...) calls.
config DEBUG_MALLOC
@@ -1173,6 +1204,15 @@ config BOOTBLOCK_CUSTOM
# src/lib/bootblock.c#main() C entry point.
bool
+config MEMLAYOUT_LD_FILE
+ string
+ default "src/mainboard/\$(CONFIG_MAINBOARD_DIR)/memlayout.ld"
+ help
+ This variable allows SoC/mainboard to supply in a custom linker file
+ if required. This determines the linker file used for all the stages
+ (bootblock, romstage, verstage, ramstage, postcar) in
+ src/arch/${ARCH}/Makefile.inc.
+
###############################################################################
# Set default values for symbols created before mainboards. This allows the
# option to be displayed in the general menu, but the default to be loaded in
diff --git a/src/acpi/Kconfig b/src/acpi/Kconfig
index 11ef12a347..07008db7a9 100644
--- a/src/acpi/Kconfig
+++ b/src/acpi/Kconfig
@@ -24,6 +24,9 @@ config ACPI_INTEL_HARDWARE_SLEEP_VALUES
Provide common definitions for Intel hardware PM1_CNT register sleep
values.
+config ACPI_NO_SMI_GNVS
+ bool
+
config ACPI_NO_PCAT_8259
bool
help
diff --git a/src/acpi/Makefile.inc b/src/acpi/Makefile.inc
index ffffb860c6..f70b23ff5b 100644
--- a/src/acpi/Makefile.inc
+++ b/src/acpi/Makefile.inc
@@ -4,10 +4,13 @@ ifeq ($(CONFIG_HAVE_ACPI_TABLES),y)
ramstage-y += acpi.c
ramstage-y += acpigen.c
+ramstage-y += acpigen_dptf.c
ramstage-y += acpigen_dsm.c
ramstage-y += acpigen_ps2_keybd.c
ramstage-y += acpigen_usb.c
ramstage-y += device.c
+ramstage-$(CONFIG_CHROMEOS) += chromeos-gnvs.c
+ramstage-y += gnvs.c
ramstage-y += pld.c
ramstage-y += sata.c
ramstage-y += soundwire.c
@@ -16,8 +19,5 @@ ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/acpi_tables.c),)
ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/acpi_tables.c
endif
$(eval $(call asl_template,dsdt))
-ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/fadt.c),)
-ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/fadt.c
-endif
-endif # CONFIG_GENERATE_ACPI_TABLES
+endif # CONFIG_HAVE_ACPI_TABLES
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index 8bf4b49b66..ccd8d2526d 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -1219,7 +1219,10 @@ void acpi_write_bert(acpi_bert_t *bert, uintptr_t region, size_t length)
header->checksum = acpi_checksum((void *)bert, header->length);
}
-#if CONFIG(COMMON_FADT)
+__weak void arch_fill_fadt(acpi_fadt_t *fadt) { }
+__weak void soc_fill_fadt(acpi_fadt_t *fadt) { }
+__weak void mainboard_fill_fadt(acpi_fadt_t *fadt) { }
+
void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
{
acpi_header_t *header = &(fadt->header);
@@ -1238,13 +1241,16 @@ void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
header->asl_compiler_revision = asl_revision;
fadt->firmware_ctrl = (unsigned long) facs;
- fadt->dsdt = (unsigned long) dsdt;
-
fadt->x_firmware_ctl_l = (unsigned long)facs;
fadt->x_firmware_ctl_h = 0;
+
+ fadt->dsdt = (unsigned long) dsdt;
fadt->x_dsdt_l = (unsigned long)dsdt;
fadt->x_dsdt_h = 0;
+ /* should be 0 ACPI 3.0 */
+ fadt->reserved = 0;
+
if (CONFIG(SYSTEM_TYPE_CONVERTIBLE) ||
CONFIG(SYSTEM_TYPE_LAPTOP))
fadt->preferred_pm_profile = PM_MOBILE;
@@ -1254,12 +1260,16 @@ void acpi_create_fadt(acpi_fadt_t *fadt, acpi_facs_t *facs, void *dsdt)
else
fadt->preferred_pm_profile = PM_DESKTOP;
+ arch_fill_fadt(fadt);
+
acpi_fill_fadt(fadt);
+ soc_fill_fadt(fadt);
+ mainboard_fill_fadt(fadt);
+
header->checksum =
acpi_checksum((void *) fadt, header->length);
}
-#endif
unsigned long __weak fw_cfg_acpi_tables(unsigned long start)
{
diff --git a/src/acpi/acpigen.c b/src/acpi/acpigen.c
index 793841cc5b..a4a74f65d7 100644
--- a/src/acpi/acpigen.c
+++ b/src/acpi/acpigen.c
@@ -339,6 +339,18 @@ void acpigen_write_scope(const char *name)
acpigen_emit_namestring(name);
}
+void acpigen_get_package_op_element(uint8_t package_op, unsigned int element, uint8_t dest_op)
+{
+ /* = DeRefOf ([polarity == ACPI_GPIO_ACTIVE_HIGH)
- return acpigen_soc_set_tx_gpio(gpio->pins[0]);
- else
+ if (gpio->active_low)
return acpigen_soc_clear_tx_gpio(gpio->pins[0]);
+ else
+ return acpigen_soc_set_tx_gpio(gpio->pins[0]);
}
int acpigen_disable_tx_gpio(struct acpi_gpio *gpio)
{
- if (gpio->polarity == ACPI_GPIO_ACTIVE_LOW)
+ if (gpio->active_low)
return acpigen_soc_set_tx_gpio(gpio->pins[0]);
else
return acpigen_soc_clear_tx_gpio(gpio->pins[0]);
@@ -1786,7 +1829,15 @@ void acpigen_get_rx_gpio(struct acpi_gpio *gpio)
{
acpigen_soc_read_rx_gpio(gpio->pins[0]);
- if (gpio->polarity == ACPI_GPIO_ACTIVE_LOW)
+ if (gpio->active_low)
+ acpigen_write_xor(LOCAL0_OP, 1, LOCAL0_OP);
+}
+
+void acpigen_get_tx_gpio(struct acpi_gpio *gpio)
+{
+ acpigen_soc_get_tx_gpio(gpio->pins[0]);
+
+ if (gpio->active_low)
acpigen_write_xor(LOCAL0_OP, 1, LOCAL0_OP);
}
@@ -1913,3 +1964,10 @@ void acpigen_write_ADR_soundwire_device(const struct soundwire_address *address)
(((uint64_t)address->part_id & 0xffff) << 8) |
(((uint64_t)address->class & 0xff)));
}
+
+void acpigen_notify(const char *namestr, int value)
+{
+ acpigen_emit_byte(NOTIFY_OP);
+ acpigen_emit_namestring(namestr);
+ acpigen_write_integer(value);
+}
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c
new file mode 100644
index 0000000000..0c44b8f8ba
--- /dev/null
+++ b/src/acpi/acpigen_dptf.c
@@ -0,0 +1,486 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include
+#include
+
+/* Defaults */
+#define DEFAULT_RAW_UNIT "ma"
+
+/* DPTF-specific UUIDs */
+#define DPTF_PASSIVE_POLICY_1_0_UUID "42A441D6-AE6A-462B-A84B-4A8CE79027D3"
+#define DPTF_CRITICAL_POLICY_UUID "97C68AE7-15FA-499c-B8C9-5DA81D606E0A"
+#define DPTF_ACTIVE_POLICY_UUID "3A95C389-E4B8-4629-A526-C52C88626BAE"
+
+enum {
+ ART_REVISION = 0,
+ DEFAULT_PRIORITY = 100,
+ DEFAULT_TRIP_POINT = 0xFFFFFFFFull,
+ DEFAULT_WEIGHT = 100,
+ DPTF_MAX_ART_THRESHOLDS = 10,
+ PPCC_REVISION = 2,
+ RAPL_PL1_INDEX = 0,
+ RAPL_PL2_INDEX = 1,
+};
+
+/* Convert degrees C to 1/10 degree Kelvin for ACPI */
+static int to_acpi_temp(int deg_c)
+{
+ return deg_c * 10 + 2732;
+}
+
+/* Converts ms to 1/10th second for ACPI */
+static int to_acpi_time(int ms)
+{
+ return ms / 100;
+}
+
+/* Writes out a 0-argument non-Serialized Method that returns an Integer */
+static void write_simple_return_method(const char *name, int value)
+{
+ acpigen_write_method(name, 0);
+ acpigen_write_return_integer(value);
+ acpigen_pop_len(); /* Method */
+}
+
+/* Writes out 'count' ZEROs in a row */
+static void write_zeros(int count)
+{
+ for (; count; --count)
+ acpigen_write_integer(0);
+}
+
+/* Return the assigned namestring of any participant */
+static const char *namestring_of(enum dptf_participant participant)
+{
+ switch (participant) {
+ case DPTF_CPU:
+ return "TCPU";
+ case DPTF_CHARGER:
+ return "TCHG";
+ case DPTF_FAN:
+ return "TFN1";
+ case DPTF_TEMP_SENSOR_0:
+ return "TSR0";
+ case DPTF_TEMP_SENSOR_1:
+ return "TSR1";
+ case DPTF_TEMP_SENSOR_2:
+ return "TSR2";
+ case DPTF_TEMP_SENSOR_3:
+ return "TSR3";
+ default:
+ return "";
+ }
+}
+
+/* Helper to get Scope for participants underneath \_SB.DPTF */
+static const char *scope_of(enum dptf_participant participant)
+{
+ static char scope[16];
+
+ if (participant == DPTF_CPU)
+ snprintf(scope, sizeof(scope), TCPU_SCOPE ".%s", namestring_of(participant));
+ else
+ snprintf(scope, sizeof(scope), DPTF_DEVICE_PATH ".%s",
+ namestring_of(participant));
+
+ return scope;
+}
+
+/*
+ * Most of the DPTF participants are underneath the \_SB.DPTF scope, so we can just get away
+ * with using the simple namestring for references, but the TCPU has a different scope, so
+ * either an absolute or relative path must be used instead.
+ */
+static const char *path_of(enum dptf_participant participant)
+{
+ if (participant == DPTF_CPU)
+ return scope_of(participant);
+ else
+ return namestring_of(participant);
+}
+
+/* Write out scope of a participant */
+void dptf_write_scope(enum dptf_participant participant)
+{
+ acpigen_write_scope(scope_of(participant));
+}
+
+/*
+ * This table describes active cooling relationships between the system's fan and the
+ * temperature sensors that it can have an effect on. As ever-increasing temperature thresholds
+ * are crossed (_AC9.._AC0, low to high), the corresponding fan percentages listed in this table
+ * are used to increase the speed of the fan in order to speed up cooling.
+ */
+static void write_active_relationship_table(const struct dptf_active_policy *policies,
+ int max_count)
+{
+ char *pkg_count;
+ int i, j;
+
+ /* Nothing to do */
+ if (!max_count || policies[0].target == DPTF_NONE)
+ return;
+
+ acpigen_write_scope(DPTF_DEVICE_PATH);
+ acpigen_write_method("_ART", 0);
+
+ /* Return this package */
+ acpigen_emit_byte(RETURN_OP);
+
+ /* Keep track of items added to the package */
+ pkg_count = acpigen_write_package(1); /* The '1' here is for the revision */
+ acpigen_write_integer(ART_REVISION);
+
+ for (i = 0; i < max_count; ++i) {
+ /*
+ * These have to be filled out from AC0 down to AC9, filling in only as many
+ * as are used. As soon as one isn't filled in, we're done.
+ */
+ if (policies[i].target == DPTF_NONE)
+ break;
+
+ (*pkg_count)++;
+
+ /* Source, Target, Percent, Fan % for each of _AC0 ... _AC9 */
+ acpigen_write_package(13);
+ acpigen_emit_namestring(path_of(DPTF_FAN));
+ acpigen_emit_namestring(path_of(policies[i].target));
+ acpigen_write_integer(DEFAULT_IF_0(policies[i].weight, DEFAULT_WEIGHT));
+
+ /* Write out fan %; corresponds with target's _ACx methods */
+ for (j = 0; j < DPTF_MAX_ART_THRESHOLDS; ++j)
+ acpigen_write_integer(policies[i].thresholds[j].fan_pct);
+
+ acpigen_pop_len(); /* inner Package */
+ }
+
+ acpigen_pop_len(); /* outer Package */
+ acpigen_pop_len(); /* Method _ART */
+ acpigen_pop_len(); /* Scope */
+}
+
+/*
+ * _AC9 through _AC0 represent temperature thresholds, in increasing order, defined from _AC0
+ * down, that, when reached, DPTF will activate TFN1 in order to actively cool the temperature
+ * sensor(s). As increasing thresholds are reached, the fan is spun faster.
+ */
+static void write_active_cooling_methods(const struct dptf_active_policy *policies,
+ int max_count)
+{
+ char name[5];
+ int i, j;
+
+ /* Nothing to do */
+ if (!max_count || policies[0].target == DPTF_NONE)
+ return;
+
+ for (i = 0; i < max_count; ++i) {
+ if (policies[i].target == DPTF_NONE)
+ break;
+
+ dptf_write_scope(policies[i].target);
+
+ /* Write out as many of _AC0 through _AC9 that are applicable */
+ for (j = 0; j < DPTF_MAX_ACX; ++j) {
+ if (!policies[i].thresholds[j].temp)
+ break;
+
+ snprintf(name, sizeof(name), "_AC%1X", j);
+ write_simple_return_method(name, to_acpi_temp(
+ policies[i].thresholds[j].temp));
+ }
+
+ acpigen_pop_len(); /* Scope */
+ }
+}
+
+void dptf_write_active_policies(const struct dptf_active_policy *policies, int max_count)
+{
+ write_active_relationship_table(policies, max_count);
+ write_active_cooling_methods(policies, max_count);
+}
+
+/*
+ * This writes out the Thermal Relationship Table, which describes the thermal relationships
+ * between participants in a thermal zone. This information is used to passively cool (i.e.,
+ * throttle) the Source (source of heat), in order to indirectly cool the Target (temperature
+ * sensor).
+ */
+static void write_thermal_relationship_table(const struct dptf_passive_policy *policies,
+ int max_count)
+{
+ char *pkg_count;
+ int i;
+
+ /* Nothing to do */
+ if (!max_count || policies[0].source == DPTF_NONE)
+ return;
+
+ acpigen_write_scope(DPTF_DEVICE_PATH);
+
+ /*
+ * A _TRT Revision (TRTR) of 1 means that the 'Priority' field is an arbitrary priority
+ * value to be used for this specific relationship. The priority value determines the
+ * order in which various sources are used in a passive thermal action for a given
+ * target.
+ */
+ acpigen_write_name_integer("TRTR", 1);
+
+ /* Thermal Relationship Table */
+ acpigen_write_method("_TRT", 0);
+
+ /* Return this package */
+ acpigen_emit_byte(RETURN_OP);
+ pkg_count = acpigen_write_package(0);
+
+ for (i = 0; i < max_count; ++i) {
+ /* Stop writing the table once an entry is empty */
+ if (policies[i].source == DPTF_NONE)
+ break;
+
+ /* Keep track of outer package item count */
+ (*pkg_count)++;
+
+ acpigen_write_package(8);
+
+ /* Source, Target, Priority, Sampling Period */
+ acpigen_emit_namestring(path_of(policies[i].source));
+ acpigen_emit_namestring(path_of(policies[i].target));
+ acpigen_write_integer(DEFAULT_IF_0(policies[i].priority, DEFAULT_PRIORITY));
+ acpigen_write_integer(to_acpi_time(policies[i].period));
+
+ /* Reserved */
+ write_zeros(4);
+
+ acpigen_pop_len(); /* Package */
+ }
+
+ acpigen_pop_len(); /* Package */
+ acpigen_pop_len(); /* Method */
+ acpigen_pop_len(); /* Scope */
+}
+
+/*
+ * When a temperature sensor measures above its the temperature returned in its _PSV Method,
+ * DPTF will begin throttling Sources in order to indirectly cool the sensor.
+ */
+static void write_all_PSV(const struct dptf_passive_policy *policies, int max_count)
+{
+ int i;
+
+ for (i = 0; i < max_count; ++i) {
+ if (policies[i].source == DPTF_NONE)
+ break;
+
+ dptf_write_scope(policies[i].target);
+ write_simple_return_method("_PSV", to_acpi_temp(policies[i].temp));
+ acpigen_pop_len(); /* Scope */
+ }
+}
+
+void dptf_write_passive_policies(const struct dptf_passive_policy *policies, int max_count)
+{
+ write_thermal_relationship_table(policies, max_count);
+ write_all_PSV(policies, max_count);
+}
+
+void dptf_write_critical_policies(const struct dptf_critical_policy *policies, int max_count)
+{
+ int i;
+
+ for (i = 0; i < max_count; ++i) {
+ if (policies[i].source == DPTF_NONE)
+ break;
+
+ dptf_write_scope(policies[i].source);
+
+ /* Choose _CRT or _HOT */
+ write_simple_return_method(policies[i].type == DPTF_CRITICAL_SHUTDOWN ?
+ "_CRT" : "_HOT", to_acpi_temp(policies[i].temp));
+
+ acpigen_pop_len(); /* Scope */
+ }
+}
+
+void dptf_write_charger_perf(const struct dptf_charger_perf *states, int max_count)
+{
+ char *pkg_count;
+ int i;
+
+ if (!max_count || !states[0].control)
+ return;
+
+ dptf_write_scope(DPTF_CHARGER);
+
+ /* PPSS - Participant Performance Supported States */
+ acpigen_write_method("PPSS", 0);
+ acpigen_emit_byte(RETURN_OP);
+
+ pkg_count = acpigen_write_package(0);
+ for (i = 0; i < max_count; ++i) {
+ if (!states[i].control)
+ break;
+
+ (*pkg_count)++;
+
+ /*
+ * 0, 0, 0, 0, # Reserved
+ * Control, Raw Performance, Raw Unit, 0 # Reserved
+ */
+ acpigen_write_package(8);
+ write_zeros(4);
+ acpigen_write_integer(states[i].control);
+ acpigen_write_integer(states[i].raw_perf);
+ acpigen_write_string(DEFAULT_RAW_UNIT);
+ acpigen_write_integer(0);
+ acpigen_pop_len(); /* inner Package */
+ }
+
+ acpigen_pop_len(); /* outer Package */
+ acpigen_pop_len(); /* Method PPSS */
+ acpigen_pop_len(); /* Scope */
+}
+
+void dptf_write_fan_perf(const struct dptf_fan_perf *states, int max_count)
+{
+ char *pkg_count;
+ int i;
+
+ if (!max_count || !states[0].percent)
+ return;
+
+ dptf_write_scope(DPTF_FAN);
+
+ /* _FPS - Fan Performance States */
+ acpigen_write_name("_FPS");
+ pkg_count = acpigen_write_package(0);
+
+ for (i = 0; i < max_count; ++i) {
+ /*
+ * Some _FPS tables do include a last entry where Percent is 0, but Power is
+ * called out, so this table is finished when both are zero.
+ */
+ if (!states[i].percent && !states[i].power)
+ break;
+
+ (*pkg_count)++;
+ acpigen_write_package(5);
+ acpigen_write_integer(states[i].percent);
+ acpigen_write_integer(DEFAULT_TRIP_POINT);
+ acpigen_write_integer(states[i].speed);
+ acpigen_write_integer(states[i].noise_level);
+ acpigen_write_integer(states[i].power);
+ acpigen_pop_len(); /* inner Package */
+ }
+
+ acpigen_pop_len(); /* Package */
+ acpigen_pop_len(); /* Scope */
+}
+
+void dptf_write_power_limits(const struct dptf_power_limits *limits)
+{
+ char *pkg_count;
+
+ /* Nothing to do */
+ if (!limits->pl1.min_power && !limits->pl2.min_power)
+ return;
+
+ dptf_write_scope(DPTF_CPU);
+ acpigen_write_method("PPCC", 0);
+
+ pkg_count = acpigen_write_package(1); /* 1 for the Revision */
+ acpigen_write_integer(PPCC_REVISION); /* revision */
+
+ if (limits->pl1.min_power) {
+ (*pkg_count)++;
+ acpigen_write_package(6);
+ acpigen_write_integer(RAPL_PL1_INDEX);
+ acpigen_write_integer(limits->pl1.min_power);
+ acpigen_write_integer(limits->pl1.max_power);
+ acpigen_write_integer(limits->pl1.time_window_min);
+ acpigen_write_integer(limits->pl1.time_window_max);
+ acpigen_write_integer(limits->pl1.granularity);
+ acpigen_pop_len(); /* inner Package */
+ }
+
+ if (limits->pl2.min_power) {
+ (*pkg_count)++;
+ acpigen_write_package(6);
+ acpigen_write_integer(RAPL_PL2_INDEX);
+ acpigen_write_integer(limits->pl2.min_power);
+ acpigen_write_integer(limits->pl2.max_power);
+ acpigen_write_integer(limits->pl2.time_window_min);
+ acpigen_write_integer(limits->pl2.time_window_max);
+ acpigen_write_integer(limits->pl2.granularity);
+ acpigen_pop_len(); /* inner Package */
+ }
+
+ acpigen_pop_len(); /* outer Package */
+ acpigen_pop_len(); /* Method */
+ acpigen_pop_len(); /* Scope */
+}
+
+void dptf_write_STR(const char *str)
+{
+ if (!str)
+ return;
+
+ acpigen_write_name_string("_STR", str);
+}
+
+void dptf_write_fan_options(bool fine_grained, int step_size, bool low_speed_notify)
+{
+ acpigen_write_name("_FIF");
+ acpigen_write_package(4);
+
+ acpigen_write_integer(0); /* Revision */
+ acpigen_write_integer(fine_grained);
+ acpigen_write_integer(step_size);
+ acpigen_write_integer(low_speed_notify);
+ acpigen_pop_len(); /* Package */
+}
+
+void dptf_write_tsr_hysteresis(uint8_t hysteresis)
+{
+ if (!hysteresis)
+ return;
+
+ acpigen_write_name_integer("GTSH", hysteresis);
+}
+
+void dptf_write_enabled_policies(const struct dptf_active_policy *active_policies,
+ int active_count,
+ const struct dptf_passive_policy *passive_policies,
+ int passive_count,
+ const struct dptf_critical_policy *critical_policies,
+ int critical_count)
+{
+ bool is_active_used;
+ bool is_passive_used;
+ bool is_critical_used;
+ int pkg_count;
+
+ is_active_used = (active_count && active_policies[0].target != DPTF_NONE);
+ is_passive_used = (passive_count && passive_policies[0].target != DPTF_NONE);
+ is_critical_used = (critical_count && critical_policies[0].source != DPTF_NONE);
+ pkg_count = is_active_used + is_passive_used + is_critical_used;
+
+ if (!pkg_count)
+ return;
+
+ acpigen_write_scope(DPTF_DEVICE_PATH);
+ acpigen_write_name("IDSP");
+ acpigen_write_package(pkg_count);
+
+ if (is_active_used)
+ acpigen_write_uuid(DPTF_ACTIVE_POLICY_UUID);
+
+ if (is_passive_used)
+ acpigen_write_uuid(DPTF_PASSIVE_POLICY_1_0_UUID);
+
+ if (is_critical_used)
+ acpigen_write_uuid(DPTF_CRITICAL_POLICY_UUID);
+
+ acpigen_pop_len(); /* Package */
+ acpigen_pop_len(); /* Scope */
+}
diff --git a/src/acpi/chromeos-gnvs.c b/src/acpi/chromeos-gnvs.c
new file mode 100644
index 0000000000..4bcf892745
--- /dev/null
+++ b/src/acpi/chromeos-gnvs.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include
+#include
+#include
+
+void gnvs_assign_chromeos(void)
+{
+ chromeos_acpi_t *gnvs_chromeos = gnvs_chromeos_ptr();
+ chromeos_init_chromeos_acpi(gnvs_chromeos);
+
+ /* EC can override to ECFW_RW. */
+ gnvs_chromeos->vbt2 = ACTIVE_ECFW_RO;
+
+ if (CONFIG(EC_GOOGLE_CHROMEEC) && !google_ec_running_ro())
+ gnvs_chromeos->vbt2 = ACTIVE_ECFW_RW;
+}
diff --git a/src/acpi/device.c b/src/acpi/device.c
index 8b03bfd6af..b119abd61f 100644
--- a/src/acpi/device.c
+++ b/src/acpi/device.c
@@ -53,7 +53,7 @@ const char *acpi_device_name(const struct device *dev)
return NULL;
/* Check for device specific handler */
- if (dev->ops->acpi_name)
+ if (dev->ops && dev->ops->acpi_name)
return dev->ops->acpi_name(dev);
/* Walk up the tree to find if any parent can identify this device */
@@ -523,6 +523,80 @@ void acpi_device_write_spi(const struct acpi_spi *spi)
acpi_device_fill_len(desc_length);
}
+/* UART Serial Bus - UARTSerialBusV2() */
+void acpi_device_write_uart(const struct acpi_uart *uart)
+{
+ void *desc_length, *type_length;
+ uint16_t flags;
+
+ /* Byte 0: Descriptor Type */
+ acpigen_emit_byte(ACPI_DESCRIPTOR_SERIAL_BUS);
+
+ /* Byte 1+2: Length (filled in later) */
+ desc_length = acpi_device_write_zero_len();
+
+ /* Byte 3: Revision ID */
+ acpigen_emit_byte(ACPI_UART_SERIAL_BUS_REVISION_ID);
+
+ /* Byte 4: Resource Source Index is Reserved */
+ acpigen_emit_byte(0);
+
+ /* Byte 5: Serial Bus Type is UART */
+ acpigen_emit_byte(ACPI_SERIAL_BUS_TYPE_UART);
+
+ /*
+ * Byte 6: Flags
+ * [7:2]: 0 => Reserved
+ * [1]: 1 => ResourceConsumer
+ * [0]: 0 => ControllerInitiated
+ */
+ acpigen_emit_byte(BIT(1));
+
+ /*
+ * Byte 7-8: Type Specific Flags
+ * [15:8]: 0 => Reserved
+ * [7]: 0 => Little Endian, 1 => Big Endian
+ * [6:4]: Data bits
+ * [3:2]: Stop bits
+ * [1:0]: Flow control
+ */
+ flags = uart->flow_control & 3;
+ flags |= (uart->stop_bits & 3) << 2;
+ flags |= (uart->data_bits & 7) << 4;
+ flags |= (uart->endian & 1) << 7;
+ acpigen_emit_word(flags);
+
+ /* Byte 9: Type Specific Revision ID */
+ acpigen_emit_byte(ACPI_UART_TYPE_SPECIFIC_REVISION_ID);
+
+ /* Byte 10-11: Type Data Length */
+ type_length = acpi_device_write_zero_len();
+
+ /* Byte 12-15: Initial Baud Rate */
+ acpigen_emit_dword(uart->initial_baud_rate);
+
+ /* Byte 16-17: RX FIFO size */
+ acpigen_emit_word(uart->rx_fifo_bytes);
+
+ /* Byte 18-19: TX FIFO size */
+ acpigen_emit_word(uart->tx_fifo_bytes);
+
+ /* Byte 20: Parity */
+ acpigen_emit_byte(uart->parity);
+
+ /* Byte 21: Lines Enabled */
+ acpigen_emit_byte(uart->lines_in_use);
+
+ /* Fill in Type Data Length */
+ acpi_device_fill_len(type_length);
+
+ /* Byte 22+: ResourceSource */
+ acpigen_emit_string(uart->resource);
+
+ /* Fill in Descriptor Length */
+ acpi_device_fill_len(desc_length);
+}
+
/* PowerResource() with Enable and/or Reset control */
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
{
@@ -658,10 +732,48 @@ static void acpi_dp_free(struct acpi_dp *dp)
}
}
-void acpi_dp_write(struct acpi_dp *table)
+static bool acpi_dp_write_properties(struct acpi_dp *prop, const char *uuid)
+{
+ struct acpi_dp *dp;
+ char *prop_count = NULL;
+
+ /* Print base properties */
+ for (dp = prop; dp; dp = dp->next) {
+ if (dp->type == ACPI_DP_TYPE_TABLE ||
+ dp->type == ACPI_DP_TYPE_CHILD ||
+ dp->type == ACPI_DP_TYPE_PACKAGE)
+ continue;
+
+ /*
+ * The UUID and package is only added when
+ * we come across the first property. This
+ * is to avoid creating a zero-length package
+ * in situations where there are only children.
+ */
+ if (!prop_count) {
+ /* ToUUID (dp->uuid) */
+ acpigen_write_uuid(uuid);
+ /*
+ * Package (PROP), element count determined as
+ * it is populated
+ */
+ prop_count = acpigen_write_package(0);
+ }
+ (*prop_count)++;
+ acpi_dp_write_property(dp);
+ }
+ if (prop_count) {
+ /* Package (PROP) length, if a package was written */
+ acpigen_pop_len();
+ return true;
+ }
+ return false;
+}
+
+static void acpi_dp_write_(struct acpi_dp *table)
{
struct acpi_dp *dp, *prop;
- char *dp_count, *prop_count = NULL;
+ char *dp_count;
int child_count = 0;
if (!table || table->type != ACPI_DP_TYPE_TABLE || !table->next)
@@ -677,37 +789,17 @@ void acpi_dp_write(struct acpi_dp *table)
dp_count = acpigen_write_package(0);
/* Print base properties */
- for (dp = prop; dp; dp = dp->next) {
- if (dp->type == ACPI_DP_TYPE_CHILD) {
- child_count++;
- } else {
- /*
- * The UUID and package is only added when
- * we come across the first property. This
- * is to avoid creating a zero-length package
- * in situations where there are only children.
- */
- if (!prop_count) {
- *dp_count += 2;
- /* ToUUID (ACPI_DP_UUID) */
- acpigen_write_uuid(ACPI_DP_UUID);
- /*
- * Package (PROP), element count determined as
- * it is populated
- */
- prop_count = acpigen_write_package(0);
- }
- (*prop_count)++;
- acpi_dp_write_property(dp);
- }
- }
- if (prop_count) {
- /* Package (PROP) length, if a package was written */
- acpigen_pop_len();
- }
+ if (acpi_dp_write_properties(prop, table->uuid))
+ *dp_count += 2;
+ /* Count child properties */
+ for (dp = prop; dp; dp = dp->next)
+ if (dp->type == ACPI_DP_TYPE_CHILD)
+ child_count++;
+
+ /* Add child properties to the base table */
if (child_count) {
- /* Update DP package count to 2 or 4 */
+ /* Update DP package count */
*dp_count += 2;
/* ToUUID (ACPI_DP_CHILD_UUID) */
acpigen_write_uuid(ACPI_DP_CHILD_UUID);
@@ -722,13 +814,24 @@ void acpi_dp_write(struct acpi_dp *table)
acpigen_pop_len();
}
+ /* Write packages of properties with unique UUID */
+ for (dp = prop; dp; dp = dp->next)
+ if (dp->type == ACPI_DP_TYPE_PACKAGE)
+ if (acpi_dp_write_properties(dp->child, dp->uuid))
+ *dp_count += 2;
+
/* Package (DP) length */
acpigen_pop_len();
/* Recursively parse children into separate tables */
for (dp = prop; dp; dp = dp->next)
if (dp->type == ACPI_DP_TYPE_CHILD)
- acpi_dp_write(dp->child);
+ acpi_dp_write_(dp->child);
+}
+
+void acpi_dp_write(struct acpi_dp *table)
+{
+ acpi_dp_write_(table);
/* Clean up */
acpi_dp_free(table);
@@ -746,6 +849,7 @@ static struct acpi_dp *acpi_dp_new(struct acpi_dp *dp, enum acpi_dp_type type,
memset(new, 0, sizeof(*new));
new->type = type;
new->name = name;
+ new->uuid = ACPI_DP_UUID;
if (dp) {
/* Add to end of property list */
@@ -863,6 +967,22 @@ struct acpi_dp *acpi_dp_add_child(struct acpi_dp *dp, const char *name,
return new;
}
+struct acpi_dp *acpi_dp_add_package(struct acpi_dp *dp, struct acpi_dp *package)
+{
+ struct acpi_dp *new;
+
+ if (!dp || !package || package->type != ACPI_DP_TYPE_TABLE)
+ return NULL;
+
+ new = acpi_dp_new(dp, ACPI_DP_TYPE_PACKAGE, NULL);
+ if (new) {
+ new->uuid = package->name;
+ new->child = package;
+ }
+
+ return new;
+}
+
struct acpi_dp *acpi_dp_add_array(struct acpi_dp *dp, struct acpi_dp *array)
{
struct acpi_dp *new;
diff --git a/src/acpi/gnvs.c b/src/acpi/gnvs.c
new file mode 100644
index 0000000000..fbc84b36fd
--- /dev/null
+++ b/src/acpi/gnvs.c
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+static void *gnvs;
+
+void *acpi_get_gnvs(void)
+{
+ if (gnvs)
+ return gnvs;
+
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (gnvs)
+ return gnvs;
+
+ printk(BIOS_ERR, "Unable to locate Global NVS\n");
+ return NULL;
+}
+
+static void gnvs_assign_cbmc(void)
+{
+ uint32_t *gnvs_cbmc = gnvs_cbmc_ptr();
+ if (gnvs_cbmc)
+ *gnvs_cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);
+}
+
+void *gnvs_get_or_create(void)
+{
+ size_t gnvs_size;
+
+ if (gnvs)
+ return gnvs;
+
+ gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
+ if (gnvs)
+ return gnvs;
+
+ gnvs_size = gnvs_size_of_array();
+
+ gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, gnvs_size);
+ if (!gnvs)
+ return gnvs;
+
+ memset(gnvs, 0, gnvs_size);
+
+ if (CONFIG(CONSOLE_CBMEM))
+ gnvs_assign_cbmc();
+
+ if (CONFIG(CHROMEOS))
+ gnvs_assign_chromeos();
+
+ return gnvs;
+}
+
+void acpi_inject_nvsa(void)
+{
+ uintptr_t gnvs_address = (uintptr_t)acpi_get_gnvs();
+ if (!gnvs_address)
+ return;
+
+ acpigen_write_scope("\\");
+ acpigen_write_name_dword("NVSA", gnvs_address);
+ acpigen_pop_len();
+}
diff --git a/src/acpi/soundwire.c b/src/acpi/soundwire.c
index 1151a181c1..c27c6f2dd3 100644
--- a/src/acpi/soundwire.c
+++ b/src/acpi/soundwire.c
@@ -6,8 +6,7 @@
#include
#include
#include
-#include
-#include
+#include
/* Specification-defined prefix for SoundWire properties. */
#define SDW_PFX "mipi-sdw-"
diff --git a/src/arch/arm/Makefile.inc b/src/arch/arm/Makefile.inc
index 66bf9c4f31..eef2650685 100644
--- a/src/arch/arm/Makefile.inc
+++ b/src/arch/arm/Makefile.inc
@@ -50,11 +50,11 @@ bootblock-y += stages.c
$(objcbfs)/bootblock.debug: $$(bootblock-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) -T $(call src-to-obj,bootblock,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) --end-group
+ $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) -T $(call src-to-obj,bootblock,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) --end-group
$(objcbfs)/decompressor.debug: $$(decompressor-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) -T $(call src-to-obj,decompressor,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(decompressor-objs)) --end-group
+ $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) -T $(call src-to-obj,decompressor,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(decompressor-objs)) --end-group
endif # CONFIG_ARCH_BOOTBLOCK_ARM
@@ -66,7 +66,7 @@ ifeq ($(CONFIG_ARCH_VERSTAGE_ARM),y)
$(objcbfs)/verstage.debug: $$(verstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_verstage) $(LDFLAGS_verstage) -o $@ -L$(obj) -T $(call src-to-obj,verstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(verstage-objs)) --end-group
+ $(LD_verstage) $(LDFLAGS_verstage) -o $@ -L$(obj) -T $(call src-to-obj,verstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(verstage-objs)) --end-group
verstage-y += boot.c
verstage-y += div0.c
@@ -99,7 +99,7 @@ rmodules_arm-y += eabi_compat.c
$(objcbfs)/romstage.debug: $$(romstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group
+ $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group
endif # CONFIG_ARCH_ROMSTAGE_ARM
@@ -128,6 +128,6 @@ ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
$(objcbfs)/ramstage.debug: $$(ramstage-objs)
@printf " CC $(subst $(obj)/,,$(@))\n"
- $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group
+ $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group
endif # CONFIG_ARCH_RAMSTAGE_ARM
diff --git a/src/arch/arm/armv7/exception.c b/src/arch/arm/armv7/exception.c
index 39ef16da22..799ae027c9 100644
--- a/src/arch/arm/armv7/exception.c
+++ b/src/arch/arm/armv7/exception.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause */
-#include
#include
#include
#include
diff --git a/src/arch/arm/armv7/mmu.c b/src/arch/arm/armv7/mmu.c
index d823c61f35..51b4860768 100644
--- a/src/arch/arm/armv7/mmu.c
+++ b/src/arch/arm/armv7/mmu.c
@@ -118,7 +118,7 @@ static void mmu_fill_table(pte_t *table, u32 start_idx, u32 end_idx,
/* Invalidate the TLB entries. */
for (i = start_idx; i < end_idx; i++)
- tlbimvaa(offset + (i << shift));
+ tlbimva(offset + (i << shift));
dsb();
isb();
}
@@ -152,7 +152,7 @@ static pte_t *mmu_create_subtable(pte_t *pgd_entry)
*pgd_entry = (pte_t)(uintptr_t)table | ATTR_NEXTLEVEL;
dccmvac((uintptr_t)pgd_entry);
dsb();
- tlbimvaa(start_addr);
+ tlbimva(start_addr);
dsb();
isb();
diff --git a/src/arch/arm/include/armv4/arch/cache.h b/src/arch/arm/include/armv4/arch/cache.h
index 8807bebe0b..8aa619dcc5 100644
--- a/src/arch/arm/include/armv4/arch/cache.h
+++ b/src/arch/arm/include/armv4/arch/cache.h
@@ -7,7 +7,6 @@
#define ARM_CACHE_H
#include
-#include
/*
* Cache maintenance API
diff --git a/src/arch/arm/include/armv7.h b/src/arch/arm/include/armv7.h
index 1223d9b1a2..0d7a8cfe7f 100644
--- a/src/arch/arm/include/armv7.h
+++ b/src/arch/arm/include/armv7.h
@@ -2,7 +2,6 @@
#ifndef ARMV7_H
#define ARMV7_H
-#include
/* Cortex-A9 revisions */
#define MIDR_CORTEX_A9_R0P1 0x410FC091
diff --git a/src/arch/arm/include/armv7/arch/cache.h b/src/arch/arm/include/armv7/arch/cache.h
index 600ec46f91..e332c31663 100644
--- a/src/arch/arm/include/armv7/arch/cache.h
+++ b/src/arch/arm/include/armv7/arch/cache.h
@@ -73,10 +73,10 @@ static inline void tlbiall(void)
asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0) : "memory");
}
-/* invalidate unified TLB by MVA, all ASID */
-static inline void tlbimvaa(unsigned long mva)
+/* invalidate unified TLB by MVA and ASID */
+static inline void tlbimva(unsigned long mva)
{
- asm volatile ("mcr p15, 0, %0, c8, c7, 3" : : "r" (mva) : "memory");
+ asm volatile ("mcr p15, 0, %0, c8, c7, 1" : : "r" (mva) : "memory");
}
/* write data access control register (DACR) */
diff --git a/src/arch/arm/include/smp/spinlock.h b/src/arch/arm/include/smp/spinlock.h
deleted file mode 100644
index e7aa3679ce..0000000000
--- a/src/arch/arm/include/smp/spinlock.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef ARCH_SMP_SPINLOCK_H
-#define ARCH_SMP_SPINLOCK_H
-
-/* FIXME: implement this for ARM */
-#error "implement this for ARM"
-#if 0
-/*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
- volatile unsigned int lock;
-} spinlock_t;
-
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
-#define DECLARE_SPIN_LOCK(x) static spinlock_t x = SPIN_LOCK_UNLOCKED;
-
-#define barrier() (__asm__ __volatile__("" : : : "memory"))
-#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) != 0)
-#define spin_unlock_wait(x) do { barrier(); } while (spin_is_locked(x))
-
-static __always_inline void spin_lock(spinlock_t *lock)
-{
- unsigned long tmp;
- __asm__ __volatile__ (
- "1: ldrex %0, [%1]\n"
- " teq %0, #0\n"
- " strexeq %0, %2, [%1]\n"
- " teqeq %0, #0\n"
- " bne 1b\n"
- : "=&r" (tmp)
- : "r" (&lock->lock), "r" (1)
- : "cc"
- );
- barrier();
-}
-
-static __always_inline void spin_unlock(spinlock_t *lock)
-{
- __asm__ __volatile__(
- " str %1, [%0]\n"
- :
- : "r" (&lock->lock), "r" (0)
- : "cc"
- );
-}
-
-#define cpu_relax() barrier()
-
-#endif
-#endif /* ARCH_SMP_SPINLOCK_H */
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index 5fd316aa7b..920ff5db51 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -45,11 +45,11 @@ bootblock-y += memmove.S
$(objcbfs)/bootblock.debug: $$(bootblock-objs) $(obj)/config.h
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) --end-group -T $(call src-to-obj,bootblock,src/mainboard/$(MAINBOARDDIR)/memlayout.ld)
+ $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) --end-group -T $(call src-to-obj,bootblock,$(CONFIG_MEMLAYOUT_LD_FILE))
$(objcbfs)/decompressor.debug: $$(decompressor-objs) $(obj)/config.h
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(decompressor-objs)) --end-group -T $(call src-to-obj,decompressor,src/mainboard/$(MAINBOARDDIR)/memlayout.ld)
+ $(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(decompressor-objs)) --end-group -T $(call src-to-obj,decompressor,$(CONFIG_MEMLAYOUT_LD_FILE))
endif # CONFIG_ARCH_BOOTBLOCK_ARM64
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_ARCH_VERSTAGE_ARM64),y)
$(objcbfs)/verstage.debug: $$(verstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_verstage) $(LDFLAGS_verstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(verstage-objs)) --end-group -T $(call src-to-obj,verstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld)
+ $(LD_verstage) $(LDFLAGS_verstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(verstage-objs)) --end-group -T $(call src-to-obj,verstage,$(CONFIG_MEMLAYOUT_LD_FILE))
verstage-y += boot.c
verstage-y += div0.c
@@ -99,7 +99,7 @@ rmodules_arm64-y += eabi_compat.c
$(objcbfs)/romstage.debug: $$(romstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group -T $(call src-to-obj,romstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld)
+ $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group -T $(call src-to-obj,romstage,$(CONFIG_MEMLAYOUT_LD_FILE))
endif # CONFIG_ARCH_ROMSTAGE_ARM64
@@ -134,7 +134,7 @@ ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
$(objcbfs)/ramstage.debug: $$(ramstage-objs)
@printf " CC $(subst $(obj)/,,$(@))\n"
- $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group -T $(call src-to-obj,ramstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld)
+ $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE))
# Build ARM Trusted Firmware (BL31)
diff --git a/src/arch/arm64/armv8/exception.c b/src/arch/arm64/armv8/exception.c
index db399fe699..88e68e759e 100644
--- a/src/arch/arm64/armv8/exception.c
+++ b/src/arch/arm64/armv8/exception.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause */
-#include
#include
#include
#include
diff --git a/src/arch/arm64/include/armv8/arch/cache.h b/src/arch/arm64/include/armv8/arch/cache.h
index a78d03c610..bb9d6febec 100644
--- a/src/arch/arm64/include/armv8/arch/cache.h
+++ b/src/arch/arm64/include/armv8/arch/cache.h
@@ -11,7 +11,6 @@
#ifndef __ASSEMBLER__
#include
-#include
#include
/* dcache clean by virtual address to PoC */
diff --git a/src/arch/ppc64/Makefile.inc b/src/arch/ppc64/Makefile.inc
index f1a2487a57..d1774a1d15 100644
--- a/src/arch/ppc64/Makefile.inc
+++ b/src/arch/ppc64/Makefile.inc
@@ -24,7 +24,7 @@ bootblock-generic-ccopts += $(ppc64_flags)
$(objcbfs)/bootblock.debug: $$(bootblock-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
$(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) \
- -T $(call src-to-obj,bootblock,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) \
+ -T $(call src-to-obj,bootblock,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) \
$(LIBGCC_FILE_NAME_bootblock) --end-group $(COMPILER_RT_bootblock)
endif
@@ -50,7 +50,7 @@ romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
$(objcbfs)/romstage.debug: $$(romstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group $(COMPILER_RT_romstage)
+ $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group $(COMPILER_RT_romstage)
romstage-c-ccopts += $(ppc64_flags)
romstage-S-ccopts += $(ppc64_asm_flags)
@@ -83,7 +83,7 @@ ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/mainboard.c
$(objcbfs)/ramstage.debug: $$(ramstage-objs)
@printf " CC $(subst $(obj)/,,$(@))\n"
- $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group $(COMPILER_RT_ramstage)
+ $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group $(COMPILER_RT_ramstage)
ramstage-c-ccopts += $(ppc64_flags)
ramstage-S-ccopts += $(ppc64_asm_flags)
diff --git a/src/arch/riscv/Makefile.inc b/src/arch/riscv/Makefile.inc
index 632e220410..cd94692c02 100644
--- a/src/arch/riscv/Makefile.inc
+++ b/src/arch/riscv/Makefile.inc
@@ -64,7 +64,7 @@ bootblock-$(CONFIG_RISCV_USE_ARCH_TIMER) += arch_timer.c
$(objcbfs)/bootblock.debug: $$(bootblock-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
$(LD_bootblock) $(LDFLAGS_bootblock) -o $@ -L$(obj) \
- -T $(call src-to-obj,bootblock,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) \
+ -T $(call src-to-obj,bootblock,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(bootblock-objs)) \
$(LIBGCC_FILE_NAME_bootblock) --end-group $(COMPILER_RT_bootblock)
bootblock-c-ccopts += $(riscv_flags)
@@ -99,7 +99,7 @@ romstage-$(CONFIG_RISCV_USE_ARCH_TIMER) += arch_timer.c
$(objcbfs)/romstage.debug: $$(romstage-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group $(COMPILER_RT_romstage)
+ $(LD_romstage) $(LDFLAGS_romstage) -o $@ -L$(obj) -T $(call src-to-obj,romstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(romstage-objs)) --end-group $(COMPILER_RT_romstage)
romstage-c-ccopts += $(riscv_flags)
romstage-S-ccopts += $(riscv_asm_flags)
@@ -148,7 +148,7 @@ ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/mainboard.c
$(objcbfs)/ramstage.debug: $$(ramstage-objs)
@printf " CC $(subst $(obj)/,,$(@))\n"
- $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,src/mainboard/$(MAINBOARDDIR)/memlayout.ld) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group $(COMPILER_RT_ramstage)
+ $(LD_ramstage) $(LDFLAGS_ramstage) -o $@ -L$(obj) -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) --end-group $(COMPILER_RT_ramstage)
ramstage-c-ccopts += $(riscv_flags)
ramstage-S-ccopts += $(riscv_asm_flags)
diff --git a/src/arch/riscv/fit_payload.c b/src/arch/riscv/fit_payload.c
index 2e676c799d..abce57ee08 100644
--- a/src/arch/riscv/fit_payload.c
+++ b/src/arch/riscv/fit_payload.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-#include
#include
#include
#include
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 0a207e19b0..660ff2d4d2 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -133,12 +133,6 @@ config NUM_IPI_STARTS
int
default 2
-config CBMEM_TOP_BACKUP
- def_bool n
- help
- Platform implements non-volatile storage to cache cbmem_top()
- over stage transitions and optionally also over S3 suspend.
-
config PRERAM_CBMEM_CONSOLE_SIZE
hex
default 0xc00
@@ -162,7 +156,7 @@ config HAVE_CMOS_DEFAULT
config CMOS_DEFAULT_FILE
string
- default "src/mainboard/$(MAINBOARDDIR)/cmos.default"
+ default "src/mainboard/\$(MAINBOARDDIR)/cmos.default"
depends on HAVE_CMOS_DEFAULT
config IOAPIC_INTERRUPTS_ON_FSB
@@ -316,4 +310,8 @@ config MAX_ACPI_TABLE_SIZE_KB
help
Set the maximum size of all ACPI tables in KiB.
+config MEMLAYOUT_LD_FILE
+ string
+ default "src/arch/x86/memlayout.ld"
+
endif
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index 0dd8d2b71e..00690ba02e 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -50,7 +50,7 @@ pci$(stripped_vgabios_dgpu_id).rom-type := optionrom
# into a single generated file.
crt0s = $(cpu_incs-y)
-$(objgenerated)/assembly.inc: $$(crt0s)
+$(objgenerated)/assembly.inc: build-dirs $$(crt0s)
@printf " GEN $(subst $(obj)/,,$(@))\n"
printf '$(foreach crt0,$(crt0s),#include "$(crt0)"\n)' > $@
@@ -67,14 +67,13 @@ endef
define early_x86_stage
# $1 stage name
# $2 oformat
-$(1)-y += memlayout.ld
# The '.' include path is needed for the generated assembly.inc file.
$(1)-S-ccopts += -I.
$$(objcbfs)/$(1).debug: $$$$($(1)-libs) $$$$($(1)-objs)
@printf " LINK $$(subst $$(obj)/,,$$(@))\n"
- $$(LD_$(1)) $$(LDFLAGS_$(1)) -o $$@ -L$$(obj) $$(COMPILER_RT_FLAGS_$(1)) --whole-archive --start-group $$(filter-out %.ld,$$($(1)-objs)) $$($(1)-libs) --no-whole-archive $$(COMPILER_RT_$(1)) --end-group -T $(call src-to-obj,$(1),$(dir)/memlayout.ld) --oformat $(2)
+ $$(LD_$(1)) $$(LDFLAGS_$(1)) -o $$@ -L$$(obj) $$(COMPILER_RT_FLAGS_$(1)) --whole-archive --start-group $$(filter-out %.ld,$$($(1)-objs)) $$($(1)-libs) --no-whole-archive $$(COMPILER_RT_$(1)) --end-group -T $(call src-to-obj,$(1),$(CONFIG_MEMLAYOUT_LD_FILE)) --oformat $(2)
-LANG=C LC_ALL= $$(OBJCOPY_$(1)) --only-section .illegal_globals $$(@) $$(objcbfs)/$(1)_null.offenders >/dev/null 2>&1
if [ -z "$$$$($$(NM_$(1)) $$(objcbfs)/$(1)_null.offenders 2>&1 | grep 'no symbols')" ];then \
echo "Forbidden global variables in $(1):"; \
@@ -82,33 +81,26 @@ $$(objcbfs)/$(1).debug: $$$$($(1)-libs) $$$$($(1)-objs)
fi
endef
-###############################################################################
-# all (bootblock,verstage,romstage,postcar,ramstage)
-###############################################################################
-
-ifeq ($(CONFIG_ARCH_X86),y)
-
-all-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
-all-y += boot.c
-all-y += memcpy.c
-all-y += memset.c
-all-y += cpu_common.c
-all-y += post.c
-
-endif
-
###############################################################################
# bootblock
###############################################################################
ifeq ($(CONFIG_ARCH_BOOTBLOCK_X86_32)$(CONFIG_ARCH_BOOTBLOCK_X86_64),y)
+bootblock-y += boot.c
+bootblock-y += post.c
+bootblock-y += cpu_common.c
bootblock-$(CONFIG_IDT_IN_EVERY_STAGE) += exception.c
bootblock-$(CONFIG_IDT_IN_EVERY_STAGE) += idt.S
+bootblock-y += memcpy.c
+bootblock-y += memset.c
+bootblock-y += memmove.c
bootblock-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
bootblock-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
bootblock-$(CONFIG_BOOTBLOCK_NORMAL) += bootblock_normal.c
bootblock-y += id.S
+bootblock-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
+
$(call src-to-obj,bootblock,$(dir)/id.S): $(obj)/build.h
bootblock-y += bootblock_crt0.S
@@ -129,10 +121,16 @@ endif # CONFIG_ARCH_BOOTBLOCK_X86_32 / CONFIG_ARCH_BOOTBLOCK_X86_64
ifeq ($(CONFIG_ARCH_VERSTAGE_X86_32)$(CONFIG_ARCH_VERSTAGE_X86_64),y)
+verstage-y += boot.c
+verstage-y += post.c
verstage-$(CONFIG_VBOOT_SEPARATE_VERSTAGE) += gdt_init.S
verstage-$(CONFIG_IDT_IN_EVERY_STAGE) += exception.c
verstage-$(CONFIG_IDT_IN_EVERY_STAGE) += idt.S
+verstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
+verstage-y += cpu_common.c
+verstage-y += memset.c
+verstage-y += memcpy.c
verstage-y += memmove.c
verstage-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
# If verstage is a separate stage it means there's no need
@@ -161,16 +159,21 @@ endif # CONFIG_ARCH_VERSTAGE_X86_32 / CONFIG_ARCH_VERSTAGE_X86_64
ifeq ($(CONFIG_ARCH_ROMSTAGE_X86_32)$(CONFIG_ARCH_ROMSTAGE_X86_64),y)
romstage-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c
+romstage-y += boot.c
+romstage-y += post.c
# gdt_init.S is included by entry32.inc when romstage is the first C
# environment.
romstage-y += gdt_init.S
-romstage-y += cbmem.c
+romstage-y += cpu_common.c
romstage-$(CONFIG_IDT_IN_EVERY_STAGE) += exception.c
romstage-$(CONFIG_IDT_IN_EVERY_STAGE) += idt.S
+romstage-y += memcpy.c
romstage-y += memmove.c
+romstage-y += memset.c
romstage-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
romstage-y += postcar_loader.c
romstage-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
+romstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
romstage-srcs += $(wildcard $(src)/mainboard/$(MAINBOARDDIR)/romstage.c)
romstage-libs ?=
@@ -196,21 +199,26 @@ $(eval $(call create_class_compiler,postcar,x86_32))
postcar-generic-ccopts += -D__POSTCAR__
postcar-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c
+postcar-y += boot.c
+postcar-y += post.c
postcar-y += gdt_init.S
+postcar-y += cpu_common.c
postcar-$(CONFIG_IDT_IN_EVERY_STAGE) += exception.c
postcar-$(CONFIG_IDT_IN_EVERY_STAGE) += idt.S
postcar-y += exit_car.S
+postcar-y += memcpy.c
postcar-y += memmove.c
-postcar-y += memlayout.ld
+postcar-y += memset.c
postcar-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
postcar-y += postcar.c
postcar-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
+postcar-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
LDFLAGS_postcar += -Map $(objcbfs)/postcar.map
$(objcbfs)/postcar.debug: $$(postcar-objs)
@printf " LINK $(subst $(obj)/,,$(@))\n"
- $(LD_postcar) $(LDFLAGS_postcar) -o $@ -L$(obj) $(COMPILER_RT_FLAGS_postcar) --whole-archive --start-group $(filter-out %.ld,$^) --no-whole-archive $(COMPILER_RT_postcar) --end-group -T $(call src-to-obj,postcar,src/arch/x86/memlayout.ld)
+ $(LD_postcar) $(LDFLAGS_postcar) -o $@ -L$(obj) $(COMPILER_RT_FLAGS_postcar) --whole-archive --start-group $(filter-out %.ld,$^) --no-whole-archive $(COMPILER_RT_postcar) --end-group -T $(call src-to-obj,postcar,$(CONFIG_MEMLAYOUT_LD_FILE))
$(objcbfs)/postcar.elf: $(objcbfs)/postcar.debug.rmod
cp $< $@
@@ -227,17 +235,21 @@ $(CONFIG_CBFS_PREFIX)/postcar-compression := none
ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32)$(CONFIG_ARCH_RAMSTAGE_X86_64),y)
+ramstage-y += acpi.c
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c
ramstage-$(CONFIG_ACPI_BERT) += acpi_bert_storage.c
+ramstage-y += boot.c
+ramstage-y += post.c
ramstage-y += c_start.S
ramstage-y += cpu.c
+ramstage-y += cpu_common.c
ramstage-y += ebda.c
ramstage-y += exception.c
ramstage-y += idt.S
-ramstage-y += gdt.c
ramstage-$(CONFIG_IOAPIC) += ioapic.c
-ramstage-y += memlayout.ld
+ramstage-y += memcpy.c
ramstage-y += memmove.c
+ramstage-y += memset.c
ramstage-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
ramstage-$(CONFIG_GENERATE_MP_TABLE) += mpspec.c
ramstage-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.c
@@ -248,22 +260,23 @@ ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
ramstage-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.S
+ramstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
-ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
rmodules_x86_32-y += memcpy.c
rmodules_x86_32-y += memmove.c
rmodules_x86_32-y += memset.c
-else
+
rmodules_x86_64-y += memcpy.c
rmodules_x86_64-y += memmove.c
rmodules_x86_64-y += memset.c
-endif
ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
target-objcopy=-O elf32-i386 -B i386
+LD_MACHINE =-m elf_i386
endif
ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_64),y)
target-objcopy=-O elf64-x86-64 -B i386:x86-64
+LD_MACHINE =-m elf_x86_64
endif
ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
@@ -275,31 +288,20 @@ endif
ifeq ($(CONFIG_GENERATE_PIRQ_TABLE),y)
ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/irq_tables.c
endif
-ifneq ($(wildcard src/mainboard/$(MAINBOARDDIR)/reset.c),)
-ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/reset.c
-endif
ramstage-libs ?=
-ifeq ($(CONFIG_RELOCATABLE_RAMSTAGE),y)
-
# The rmodule_link definition creates an elf file with .rmod extension.
$(objcbfs)/ramstage.elf: $(objcbfs)/ramstage.debug.rmod
cp $< $@
-endif
-
-$(objcbfs)/ramstage.debug: $(objgenerated)/ramstage.o $(call src-to-obj,ramstage,src/arch/x86/memlayout.ld)
+$(objcbfs)/ramstage.debug: $(objgenerated)/ramstage.o $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE))
@printf " CC $(subst $(obj)/,,$(@))\n"
- $(LD_ramstage) $(CPPFLAGS) $(LDFLAGS_ramstage) -o $@ -L$(obj) $< -T $(call src-to-obj,ramstage,src/arch/x86/memlayout.ld)
+ $(LD_ramstage) $(CPPFLAGS) $(LDFLAGS_ramstage) -o $@ -L$(obj) $< -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE))
$(objgenerated)/ramstage.o: $$(ramstage-objs) $(COMPILER_RT_ramstage) $$(ramstage-libs)
@printf " CC $(subst $(obj)/,,$(@))\n"
-ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
- $(LD_ramstage) -m elf_i386 -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group
-else
- $(LD_ramstage) -m elf_x86_64 -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group
-endif
+ $(LD_ramstage) $(LD_MACHINE) -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group
endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c
new file mode 100644
index 0000000000..0ff0ded9bf
--- /dev/null
+++ b/src/arch/x86/acpi.c
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include
+#include
+
+void arch_fill_fadt(acpi_fadt_t *fadt)
+{
+ if (CONFIG(HAVE_CF9_RESET)) {
+ fadt->reset_reg.space_id = ACPI_ADDRESS_SPACE_IO;
+ fadt->reset_reg.bit_width = 8;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
+ fadt->reset_reg.addrl = RST_CNT;
+ fadt->reset_reg.addrh = 0;
+
+ fadt->reset_value = RST_CPU | SYS_RST;
+
+ fadt->flags |= ACPI_FADT_RESET_REGISTER;
+ }
+}
diff --git a/src/arch/x86/acpi/debug.asl b/src/arch/x86/acpi/debug.asl
index 11651e4f00..fd071f8fdb 100644
--- a/src/arch/x86/acpi/debug.asl
+++ b/src/arch/x86/acpi/debug.asl
@@ -1,20 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- #include
- DefinitionBlock (
- "DSDT.AML",
- "DSDT",
- 0x01,
- OEM_ID,
- ACPI_TABLE_CREATOR,
- 0x00010001
- )
- {
- #include "debug.asl"
- }
-*/
-
/*
* 0x80: POST_BASE
* 0x3F8: DEBCOM_BASE
diff --git a/src/arch/x86/acpi_bert_storage.c b/src/arch/x86/acpi_bert_storage.c
index cde95f12e0..de56291ac4 100644
--- a/src/arch/x86/acpi_bert_storage.c
+++ b/src/arch/x86/acpi_bert_storage.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-#include
#include
#include
#include
diff --git a/src/arch/x86/acpi_s3.c b/src/arch/x86/acpi_s3.c
index 5ef0f7a6c8..4872c07228 100644
--- a/src/arch/x86/acpi_s3.c
+++ b/src/arch/x86/acpi_s3.c
@@ -4,14 +4,11 @@
#include
#include
#include
-#include
#include
+#include
#include
#include
-#include
#include
-#include
-#include
#if ENV_RAMSTAGE || ENV_POSTCAR
@@ -81,16 +78,8 @@ void __weak mainboard_suspend_resume(void)
void acpi_resume(void *wake_vec)
{
- if (CONFIG(HAVE_SMI_HANDLER)) {
- void *gnvs_address = cbmem_find(CBMEM_ID_ACPI_GNVS);
-
- /* Restore GNVS pointer in SMM if found */
- if (gnvs_address) {
- printk(BIOS_DEBUG, "Restore GNVS pointer to %p\n",
- gnvs_address);
- smm_setup_structures(gnvs_address, NULL, NULL);
- }
- }
+ /* Restore GNVS pointer in SMM if found. */
+ apm_control(APM_CNT_GNVS_UPDATE);
/* Call mainboard resume handler first, if defined. */
mainboard_suspend_resume();
diff --git a/src/arch/x86/car.ld b/src/arch/x86/car.ld
index ddd4e7a2bf..17b774845b 100644
--- a/src/arch/x86/car.ld
+++ b/src/arch/x86/car.ld
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+/* CACHE_ROM_SIZE defined here. */
+#include
+
/* This file is included inside a SECTIONS block */
. = CONFIG_DCACHE_RAM_BASE;
.car.data . (NOLOAD) : {
@@ -73,6 +76,27 @@
_car_region_end = . + CONFIG_DCACHE_RAM_SIZE - (. - _car_region_start);
}
+. = _car_region_end;
+.car.mrc_var . (NOLOAD) : {
+ . += CONFIG_DCACHE_RAM_MRC_VAR_SIZE;
+}
+
+#if ENV_BOOTBLOCK
+_car_mtrr_end = .;
+_car_mtrr_start = _car_region_start;
+
+_car_mtrr_size = _car_mtrr_end - _car_mtrr_start;
+_car_mtrr_sz_log2 = 1 << LOG2CEIL(_car_mtrr_size);
+_car_mtrr_mask = ~(MAX(4096, _car_mtrr_sz_log2) - 1);
+
+#if !CONFIG(NO_XIP_EARLY_STAGES)
+_xip_program_sz_log2 = 1 << LOG2CEIL(_ebootblock - _bootblock);
+_xip_mtrr_mask = ~(MAX(4096, _xip_program_sz_log2) - 1);
+#endif
+
+_rom_mtrr_mask = ~(CACHE_ROM_SIZE - 1);
+_rom_mtrr_base = _rom_mtrr_mask;
+#endif
/* Global variables are not allowed in romstage
* This section is checked during stage creation to ensure
diff --git a/src/arch/x86/cbmem.c b/src/arch/x86/cbmem.c
deleted file mode 100644
index 353368a1ec..0000000000
--- a/src/arch/x86/cbmem.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#include
-
-#if CONFIG(CBMEM_TOP_BACKUP)
-
-void *cbmem_top_chipset(void)
-{
- /* Top of CBMEM is at highest usable DRAM address below 4GiB. */
- return (void *)restore_top_of_low_cacheable();
-}
-
-#endif /* CBMEM_TOP_BACKUP */
diff --git a/src/arch/x86/early_ram.ld b/src/arch/x86/early_ram.ld
deleted file mode 100644
index 82bd775e9c..0000000000
--- a/src/arch/x86/early_ram.ld
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-/* This file is included inside a SECTIONS block */
-
-_STACK_SIZE = CONFIG_EARLYRAM_BSP_STACK_SIZE;
-_ = ASSERT(_STACK_SIZE > 0x0, "EARLYRAM_BSP_STACK_SIZE is not configured");
-
-_CONSOLE_SIZE = CONFIG_PRERAM_CBMEM_CONSOLE_SIZE;
-_ = ASSERT(_CONSOLE_SIZE > 0x0, "PRERAM_CBMEM_CONSOLE_SIZE is not configured");
-
-_TIMESTAMPS_SIZE = 0x200;
-#if !CONFIG(NO_FMAP_CACHE)
-_FMAP_SIZE = FMAP_SIZE;
-#else
-_FMAP_SIZE = 0;
-#endif
-
-/*
- * The PRERAM_CBMEM_CONSOLE, TIMESTAMP, and FMAP_CACHE regions are shared
- * between the pre-ram stages (bootblock, romstage, etc). We need to assign a
- * fixed size and consistent link address so they can be shared between stages.
- *
- * The stack area is not shared between stages, but is defined here for
- * convenience.
- */
-. = CONFIG_X86_RESET_VECTOR - ARCH_STACK_ALIGN_SIZE - _STACK_SIZE - _CONSOLE_SIZE - _TIMESTAMPS_SIZE - _FMAP_SIZE - VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE;
-
-_ = ASSERT(. > _eprogram, "Not enough room for .earlyram.data. Try increasing C_ENV_BOOTBLOCK_SIZE, or decreasing either EARLYRAM_BSP_STACK_SIZE or PRERAM_CBMEM_CONSOLE_SIZE.");
-
-.stack ALIGN(ARCH_STACK_ALIGN_SIZE) (NOLOAD) : {
- EARLYRAM_STACK(., _STACK_SIZE)
-}
-
-.persistent ALIGN(ARCH_POINTER_ALIGN_SIZE) (NOLOAD) : {
- PRERAM_CBMEM_CONSOLE(., _CONSOLE_SIZE)
- TIMESTAMP(., _TIMESTAMPS_SIZE)
- #if !CONFIG(NO_FMAP_CACHE)
- FMAP_CACHE(., FMAP_SIZE)
- #endif
-
- #if CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)
- ALIGN_COUNTER(16);
- VBOOT2_WORK(., VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE)
- #endif
-}
-
-_ = ASSERT(. <= CONFIG_X86_RESET_VECTOR, "Earlyram data regions don't fit below the reset vector!");
diff --git a/src/arch/x86/exception.c b/src/arch/x86/exception.c
index 46ba370cdf..958ebfc41c 100644
--- a/src/arch/x86/exception.c
+++ b/src/arch/x86/exception.c
@@ -489,12 +489,38 @@ void x86_exception(struct eregs *info)
put_packet(out_buffer);
}
#else /* !CONFIG_GDB_STUB */
-#define MDUMP_SIZE 0x80
+
int logical_processor = 0;
#if ENV_RAMSTAGE
logical_processor = cpu_index();
#endif
+ u8 *code;
+#ifdef __x86_64__
+#define MDUMP_SIZE 0x100
+ printk(BIOS_EMERG,
+ "CPU Index %d - APIC %d Unexpected Exception:\n"
+ "%lld @ %02llx:%016llx - Halting\n"
+ "Code: %lld rflags: %016llx cr2: %016llx\n"
+ "rax: %016llx rbx: %016llx\n"
+ "rcx: %016llx rdx: %016llx\n"
+ "rdi: %016llx rsi: %016llx\n"
+ "rbp: %016llx rsp: %016llx\n"
+ "r08: %016llx r09: %016llx\n"
+ "r10: %016llx r11: %016llx\n"
+ "r12: %016llx r13: %016llx\n"
+ "r14: %016llx r15: %016llx\n",
+ logical_processor, (unsigned int)lapicid(),
+ info->vector, info->cs, info->rip,
+ info->error_code, info->rflags, read_cr2(),
+ info->rax, info->rbx, info->rcx, info->rdx,
+ info->rdi, info->rsi, info->rbp, info->rsp,
+ info->r8, info->r9, info->r10, info->r11,
+ info->r12, info->r13, info->r14, info->r15);
+ code = (u8 *)((uintptr_t)info->rip - (MDUMP_SIZE >> 2));
+#else
+#define MDUMP_SIZE 0x80
+
printk(BIOS_EMERG,
"CPU Index %d - APIC %d Unexpected Exception:"
"%d @ %02x:%08x - Halting\n"
@@ -506,7 +532,8 @@ void x86_exception(struct eregs *info)
info->error_code, info->eflags, read_cr2(),
info->eax, info->ebx, info->ecx, info->edx,
info->edi, info->esi, info->ebp, info->esp);
- u8 *code = (u8 *)((uintptr_t)info->eip - (MDUMP_SIZE >> 1));
+ code = (u8 *)((uintptr_t)info->eip - (MDUMP_SIZE >> 1));
+#endif
/* Align to 8-byte boundary please, and print eight bytes per row.
* This is done to make DRAM burst timing/reordering errors more
* evident from the looking at the dump */
@@ -517,7 +544,18 @@ void x86_exception(struct eregs *info)
printk(BIOS_EMERG, "\n%p:\t", code + i);
printk(BIOS_EMERG, "%.2x ", code[i]);
}
- die("");
+
+ /* Align to 4-byte boundary and up the stack. */
+ u32 *ptr = (u32 *)(ALIGN_DOWN((uintptr_t)info->esp, sizeof(u32)) + MDUMP_SIZE - 4);
+ for (i = 0; i < MDUMP_SIZE / sizeof(u32); ++i, --ptr) {
+ printk(BIOS_EMERG, "\n%p:\t0x%08x", ptr, *ptr);
+ if ((uintptr_t)ptr == info->ebp)
+ printk(BIOS_EMERG, " <-ebp");
+ else if ((uintptr_t)ptr == info->esp)
+ printk(BIOS_EMERG, " <-esp");
+ }
+
+ die("\n");
#endif
}
diff --git a/src/arch/x86/gdt.c b/src/arch/x86/gdt.c
deleted file mode 100644
index 9c855664cf..0000000000
--- a/src/arch/x86/gdt.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* i386 lgdt argument */
-struct gdtarg {
- u16 limit;
-#ifdef __x86_64__
- u64 base;
-#else
- u32 base;
-#endif
-} __packed;
-
-/*
- * Copy GDT to new location and reload it.
- * FIXME: We only do this for BSP CPU.
- */
-static void move_gdt(int is_recovery)
-{
- void *newgdt;
- u16 num_gdt_bytes;
- struct gdtarg gdtarg;
-
- /* ramstage is already in high memory. No need to use a new gdt. */
- if (CONFIG(RELOCATABLE_RAMSTAGE))
- return;
-
- newgdt = cbmem_find(CBMEM_ID_GDT);
- num_gdt_bytes = (uintptr_t)&gdt_end - (uintptr_t)&gdt;
- if (!newgdt) {
- newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN_UP(num_gdt_bytes, 512));
- if (!newgdt) {
- printk(BIOS_ERR, "Error: Could not relocate GDT.\n");
- return;
- }
- memcpy((void *)newgdt, &gdt, num_gdt_bytes);
- }
- printk(BIOS_DEBUG, "Moving GDT to %p...", newgdt);
-
- gdtarg.base = (uintptr_t)newgdt;
- gdtarg.limit = num_gdt_bytes - 1;
-
- __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
- printk(BIOS_DEBUG, "ok\n");
-}
-RAMSTAGE_CBMEM_INIT_HOOK(move_gdt)
diff --git a/src/arch/x86/idt.S b/src/arch/x86/idt.S
index a15ccbb132..6807056fe3 100644
--- a/src/arch/x86/idt.S
+++ b/src/arch/x86/idt.S
@@ -109,6 +109,68 @@ vec19:
.global int_hand
int_hand:
+#ifdef __x86_64__
+ /* At this point, on x86-64, on the stack there is:
+ * 0(%rsp) vector
+ * 8(%rsp) error code
+ * 16(%rsp) rip
+ * 24(%rsp) cs
+ * 32(%rsp) rflags
+ * 40(%rsp) rsp
+ * 48(%rsp) ss
+ */
+ push %r15
+ push %r14
+ push %r13
+ push %r12
+ push %r11
+ push %r10
+ push %r9
+ push %r8
+
+ push %rdi
+ push %rsi
+ push %rbp
+
+ push %rbx
+ push %rdx
+ push %rcx
+ push %rax
+
+ /* Pass pointer to struct as first argument */
+ mov %rsp, %rdi
+
+ /* Back up stack pointer */
+ mov %rsp, %rbp
+
+ /* Align stack to 16 bytes. */
+ and $(~0xf), %rsp
+
+ call x86_exception
+
+ /* Restore stack pointer from backup */
+ mov %rbp, %rsp
+
+ pop %rax
+ pop %rcx
+ pop %rdx
+ pop %rbx
+
+ pop %rbp
+ pop %rsi
+ pop %rdi
+
+ pop %r8
+ pop %r9
+ pop %r10
+ pop %r11
+ pop %r12
+ pop %r13
+ pop %r14
+ pop %r15
+
+ add $16, %rsp /* pop of the vector and error code */
+#else
/* At this point, on x86-32, on the stack there is:
* 0(%esp) vector
* 4(%esp) error code
@@ -116,33 +178,6 @@ int_hand:
* 12(%esp) cs
* 16(%esp) eflags
*/
-#ifdef __x86_64__
- push %rdi
- push %rsi
- push %rbp
- /* Original stack pointer */
- lea 32(%rsp), %rbp
- push %rbp
- push %rbx
- push %rdx
- push %rcx
- push %rax
-
- push %rsp /* Pointer to structure on the stack */
- call x86_exception
- pop %rax /* Drop the pointer */
-
- pop %rax
- pop %rcx
- pop %rdx
- pop %rbx
- pop %rbp /* Ignore saved %rsp value */
- pop %rbp
- pop %rsi
- pop %rdi
-
- add $8, %rsp /* pop of the vector and error code */
-#else
pushl %edi
pushl %esi
pushl %ebp
diff --git a/src/arch/x86/include/arch/ebda.h b/src/arch/x86/include/arch/ebda.h
index 71426b13ef..e625d4a305 100644
--- a/src/arch/x86/include/arch/ebda.h
+++ b/src/arch/x86/include/arch/ebda.h
@@ -3,7 +3,6 @@
#ifndef __ARCH_EBDA_H
#define __ARCH_EBDA_H
-#include
#include
#define X86_BDA_SIZE 0x200
diff --git a/src/arch/x86/include/arch/registers.h b/src/arch/x86/include/arch/registers.h
index 256053c9b0..5f8f9becd3 100644
--- a/src/arch/x86/include/arch/registers.h
+++ b/src/arch/x86/include/arch/registers.h
@@ -6,7 +6,7 @@
#if !defined(__ASSEMBLER__)
#include
-#define DOWNTO8(A) \
+#define LONG_DOWNTO8(A) \
union { \
struct { \
union { \
@@ -21,7 +21,7 @@
uint32_t e##A##x; \
} __packed;
-#define DOWNTO16(A) \
+#define LONG_DOWNTO16(A) \
union { \
struct { \
uint16_t A; \
@@ -30,21 +30,60 @@
uint32_t e##A; \
} __packed;
+#define QUAD_DOWNTO8(A) \
+ union { \
+ LONG_DOWNTO8(A) \
+ uint64_t r##A##x; \
+ } __packed
+
+#define QUAD_DOWNTO16(A) \
+ union {\
+ LONG_DOWNTO16(A) \
+ uint64_t r##A; \
+ } __packed
+
+#ifdef __ARCH_x86_64__
struct eregs {
- DOWNTO8(a);
- DOWNTO8(c);
- DOWNTO8(d);
- DOWNTO8(b);
- DOWNTO16(sp);
- DOWNTO16(bp);
- DOWNTO16(si);
- DOWNTO16(di);
+ QUAD_DOWNTO8(a);
+ QUAD_DOWNTO8(c);
+ QUAD_DOWNTO8(d);
+ QUAD_DOWNTO8(b);
+ QUAD_DOWNTO16(bp);
+ QUAD_DOWNTO16(si);
+ QUAD_DOWNTO16(di);
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t vector;
+ uint64_t error_code;
+ uint64_t rip;
+ uint64_t cs;
+ uint64_t rflags;
+ QUAD_DOWNTO16(sp);
+ uint64_t ss;
+};
+#else
+struct eregs {
+ LONG_DOWNTO8(a);
+ LONG_DOWNTO8(c);
+ LONG_DOWNTO8(d);
+ LONG_DOWNTO8(b);
+ LONG_DOWNTO16(sp);
+ LONG_DOWNTO16(bp);
+ LONG_DOWNTO16(si);
+ LONG_DOWNTO16(di);
uint32_t vector;
uint32_t error_code;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
};
+#endif
#endif // !ASSEMBLER
#if CONFIG(COMPILER_LLVM_CLANG)
diff --git a/src/arch/x86/include/arch/romstage.h b/src/arch/x86/include/arch/romstage.h
index 8418366d6c..28d29bfdd8 100644
--- a/src/arch/x86/include/arch/romstage.h
+++ b/src/arch/x86/include/arch/romstage.h
@@ -5,6 +5,7 @@
#include
#include
+#include
void mainboard_romstage_entry(void);
@@ -16,10 +17,8 @@ void mainboard_romstage_entry(void);
struct postcar_frame {
uintptr_t stack;
- uint32_t upper_mask;
- int max_var_mtrrs;
- int num_var_mtrrs;
int skip_common_mtrr;
+ struct var_mtrr_context ctx;
};
/*
diff --git a/src/arch/x86/memlayout.ld b/src/arch/x86/memlayout.ld
index 7209034169..3659cc9f96 100644
--- a/src/arch/x86/memlayout.ld
+++ b/src/arch/x86/memlayout.ld
@@ -3,15 +3,6 @@
#include
#include
-/* Pull in the either CAR or early DRAM rules. */
-#if ENV_ROMSTAGE_OR_BEFORE
-#if ENV_CACHE_AS_RAM
-#define EARLY_MEMLAYOUT "car.ld"
-#else
-#define EARLY_MEMLAYOUT "early_ram.ld"
-#endif
-#endif
-
SECTIONS
{
/*
@@ -22,26 +13,25 @@ SECTIONS
* conditionalize with macros.
*/
#if ENV_RAMSTAGE
- RAMSTAGE(CONFIG_RAMBASE, (CONFIG(RELOCATABLE_RAMSTAGE) ? 8M :
- CONFIG_RAMTOP - CONFIG_RAMBASE))
+ RAMSTAGE(CONFIG_RAMBASE, 8M)
#elif ENV_ROMSTAGE
/* The 1M size is not allocated. It's just for basic size checking.
* Link at 32MiB address and rely on cbfstool to relocate to XIP. */
ROMSTAGE(CONFIG_ROMSTAGE_ADDR, 1M)
- #include EARLY_MEMLAYOUT
+ #include "car.ld"
#elif ENV_SEPARATE_VERSTAGE
/* The 1M size is not allocated. It's just for basic size checking.
* Link at 32MiB address and rely on cbfstool to relocate to XIP. */
VERSTAGE(CONFIG_VERSTAGE_ADDR, 1M)
- #include EARLY_MEMLAYOUT
+ #include "car.ld"
#elif ENV_BOOTBLOCK
BOOTBLOCK(CONFIG_X86_RESET_VECTOR - CONFIG_C_ENV_BOOTBLOCK_SIZE + 0x10,
CONFIG_C_ENV_BOOTBLOCK_SIZE)
- #include EARLY_MEMLAYOUT
+ #include "car.ld"
#elif ENV_POSTCAR
POSTCAR(32M, 1M)
@@ -52,9 +42,7 @@ SECTIONS
/* Bootblock specific scripts which provide more SECTION directives. */
#include
#include
-#if !CONFIG(RESET_VECTOR_IN_RAM)
#include
-#endif
#if CONFIG(CPU_INTEL_FIRMWARE_INTERFACE_TABLE)
#include
#endif
diff --git a/src/arch/x86/mpspec.c b/src/arch/x86/mpspec.c
index 31e1127772..15c3c0e1ea 100644
--- a/src/arch/x86/mpspec.c
+++ b/src/arch/x86/mpspec.c
@@ -240,12 +240,6 @@ void smp_write_intsrc(struct mp_config_table *mc,
mpc->mpc_dstapic = dstapic;
mpc->mpc_dstirq = dstirq;
smp_add_mpc_entry(mc, sizeof(*mpc));
-#ifdef DEBUG_MPTABLE
- printk(BIOS_DEBUG,
- "add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
- srcbus, srcbusirq, dstapic, dstirq);
- hexdump(__func__, mpc, sizeof(*mpc));
-#endif
}
/*
diff --git a/src/arch/x86/postcar_loader.c b/src/arch/x86/postcar_loader.c
index 58c6db92e7..241ba8c21f 100644
--- a/src/arch/x86/postcar_loader.c
+++ b/src/arch/x86/postcar_loader.c
@@ -3,7 +3,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -26,12 +25,7 @@ static inline void stack_push(struct postcar_frame *pcf, uint32_t val)
static void postcar_frame_prepare(struct postcar_frame *pcf)
{
- msr_t msr;
- msr = rdmsr(MTRR_CAP_MSR);
-
- pcf->upper_mask = (1 << (cpu_phys_address_size() - 32)) - 1;
- pcf->max_var_mtrrs = msr.lo & MTRR_CAP_VCNT;
- pcf->num_var_mtrrs = 0;
+ var_mtrr_context_init(&pcf->ctx, pcf);
}
int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
@@ -60,47 +54,25 @@ int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
return 0;
}
+static void postcar_var_mtrr_set(const struct var_mtrr_context *ctx,
+ uintptr_t addr, size_t size,
+ msr_t base, msr_t mask)
+{
+ struct postcar_frame *pcf = ctx->arg;
+
+ printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %zx)\n",
+ addr, addr + size, size);
+
+ stack_push(pcf, mask.hi);
+ stack_push(pcf, mask.lo);
+ stack_push(pcf, base.hi);
+ stack_push(pcf, base.lo);
+}
+
void postcar_frame_add_mtrr(struct postcar_frame *pcf,
uintptr_t addr, size_t size, int type)
{
- /*
- * Utilize additional MTRRs if the specified size is greater than the
- * base address alignment.
- */
- while (size != 0) {
- uint32_t addr_lsb;
- uint32_t size_msb;
- uint32_t mtrr_size;
-
- if (pcf->num_var_mtrrs >= pcf->max_var_mtrrs) {
- printk(BIOS_ERR, "No more variable MTRRs: %d\n",
- pcf->max_var_mtrrs);
- return;
- }
-
- addr_lsb = fls(addr);
- size_msb = fms(size);
-
- /* All MTRR entries need to have their base aligned to the mask
- * size. The maximum size is calculated by a function of the
- * min base bit set and maximum size bit set. */
- if (addr_lsb > size_msb)
- mtrr_size = 1 << size_msb;
- else
- mtrr_size = 1 << addr_lsb;
-
- printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %x)\n",
- addr, addr + mtrr_size, mtrr_size);
-
- stack_push(pcf, pcf->upper_mask);
- stack_push(pcf, ~(mtrr_size - 1) | MTRR_PHYS_MASK_VALID);
- stack_push(pcf, 0);
- stack_push(pcf, addr | type);
- pcf->num_var_mtrrs++;
-
- size -= mtrr_size;
- addr += mtrr_size;
- }
+ var_mtrr_set_with_cb(&pcf->ctx, addr, size, type, postcar_var_mtrr_set);
}
void postcar_frame_add_romcache(struct postcar_frame *pcf, int type)
@@ -140,8 +112,8 @@ static void postcar_commit_mtrrs(struct postcar_frame *pcf)
* Place the number of used variable MTRRs on stack then max number
* of variable MTRRs supported in the system.
*/
- stack_push(pcf, pcf->num_var_mtrrs);
- stack_push(pcf, pcf->max_var_mtrrs);
+ stack_push(pcf, pcf->ctx.used_var_mtrrs);
+ stack_push(pcf, pcf->ctx.max_var_mtrrs);
}
static void finalize_load(uintptr_t *stack_top_ptr, uintptr_t stack_top)
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
index 29d5d54181..3c5799bca8 100644
--- a/src/arch/x86/smbios.c
+++ b/src/arch/x86/smbios.c
@@ -19,6 +19,8 @@
#if CONFIG(CHROMEOS)
#include
#endif
+#include