77 changes: 77 additions & 0 deletions Documentation/mainboard/system76/bonw14.md
@@ -0,0 +1,77 @@
# System76 Bonobo Workstation 14 (bonw14)

## Specs

- CPU
- Intel Core i5-10600K
- Intel Core i7-10700K
- Intel Core i9-10900K
- Chipset
- Intel Z490
- EC
- ITE IT5570E running [System76 EC](https://github.com/system76/ec)
- Grahpics
- dGPU options
- NVIDIA GeForce RTX 2080 Super
- NVIDIA GeForce RTX 2070 Super
- NVIDIA GeForce RTX 2060
- eDP options
- 17.3" 1920x1080x144Hz LCD (LG LP173WFG-SPB1)
- 17.3" 3840x2160@60Hz LCD (AUO B173ZAN03.0)
- 1x HDMI
- 2x Mini DisplayPort 1.4
- 2x DisplayPort 1.4 over USB-C
- Memory
- Up to 128GB (4x32GB) quad-channel DDR4 SO-DIMMs @ 3200 MHz
- Networking
- Gigabit Ethernet
- M.2 PCIe/CNVi WiFi/Bluetooth
- Intel Wi-Fi 6 AX200/AX201
- Power
- 2x 280W (20V 14A) AC barrel adapter
- Chicony A18-280P1A, using a C13 power cord
- 97Wh 8-cell Lithium-Ion battery
- Sound
- Realtek ALC1220 codec
- 2x TI TAS5825MRHBR smart AMPs
- Internal speakers (stereo + subwoofer) and microphone
- Combined 3.5mm headphone/microphone jack
- Combined 3.5mm microphone and S/PDIF jack
- HDMI, Mini DisplayPort, USB-C DisplayPort audio
- Storage
- 2x M.2 PCIe NVMe or SATA SSD
- 1x M.2 PCIe NVMe-only SSD
- 1x M.2 SATA-only SSD
- SD card reader (RTS5260)
- USB
- 1x USB Type-C with Thunderbolt 3
- 1x USB 3.2 Gen 2 Type-C with DisplayPort 1.4
- 1x USB 3.2 Gen 2x2 Type-C
- 3x USB 3.2 Gen 2 Type-A
- Dimensions
- 4.343cm x 39.903cm x 31.902cm, 3.80kg

## Flashing coreboot

```eval_rst
+---------------------+---------------------+
| Type | Value |
+=====================+=====================+
| Socketed flash | no |
+---------------------+---------------------+
| Vendor | GigaDevice |
+---------------------+---------------------+
| Model | GD25B127D |
+---------------------+---------------------+
| Size | 16 MiB |
+---------------------+---------------------+
| Package | SOIC-8 |
+---------------------+---------------------+
| Internal flashing | yes |
+---------------------+---------------------+
| External flashing | yes |
+---------------------+---------------------+
```

External flashing via ISP requires removing the board from the chassis.
The flash chip (U16) is next to the PCH.
87 changes: 87 additions & 0 deletions Documentation/mainboard/system76/gaze16.md
@@ -0,0 +1,87 @@
# System76 Gazelle 16 (gaze16)

## Specs

- CPU
- Intel Core i7-11800H
- Chipset
- Intel HM570
- EC
- ITE IT5570E running [System76 EC](https://github.com/system76/ec)
- Graphics
- dGPU options
- NVIDIA GeForce RTX 3050
- NVIDIA GeForce RTX 3050 Ti
- NVIDIA GeForce RTX 3060
- eDP displays
- 15.6" 1920x1080@144Hz LCD (AUO B156HAN08.4)
- 17.3" 1920x1080@144Hz LCD (LG LP173WFG-SPB3)
- External outputs
- RTX 3050/3050 Ti
- 1x HDMI
- 1x Mini DisplayPort 1.4
- RTX 3060
- 1x HDMI
- 1x Mini DisplayPort 1.2
- 1x DisplayPort 1.4 over USB-C
- Memory
- Up to 64GB (2x32GB) dual-channel DDR4 SO-DIMMs @ 3200 MHz
- Networking
- Gigabit Ethernet
- Either onboard Intel I219-V or Realtek RTL8111H controller
- M.2 PCIe/CNVi WiFi/Bluetooth
- Intel Wi-Fi 6 AX200/AX201
- Power
- RTX 3050/3050 Ti
- 150W AC barrel adapter
- Included: Chicony A17-150P2A, using a C5 power cord
- RTX 3060
- 180W AC barrel adapter
- Included: Chicony A17-180P4A, using a C5 power cord
- 48.96Wh 4-cell battery
- Sound
- Realtek ALC256 codec
- Internal speakers and microphone
- Combined 3.5mm headphone/microphone jack
- Dedicated 3.5mm microphone jack
- HDMI, mDP, USB-C DP audio
- Storage
- 1x M.2 PCIe NVMe Gen 4 SSD
- 1x M.2 PCIe NVMe Gen 3 or SATA 3 SSD
- SD card reader
- Realtek RTS5227S on RTX 3050/3050 Ti models
- Realtek OZ711LV2 on RTX 3060 models
- USB
- 1x USB 3.2 Gen 2 Type-C
- Supports DisplayPort over USB-C on RTX 3060 models only
- Does not support USB-C charging (USB-PD) or Thunderbolt
- 1x USB 3.2 Gen 2 Type-A
- 1x USB 3.2 Gen 1 Type-A
- 1x USB 2.0 Type-A
- Dimensions
- 15": 35.75cm x 23.8cm x 1.98cm, 1.99kg
- 17": 39.59cm x 26.495cm x 1.99cm, 2.3kg

## Flashing coreboot

```eval_rst
+---------------------+---------------------+
| Type | Value |
+=====================+=====================+
| Socketed flash | no |
+---------------------+---------------------+
| Vendor | GigaDevice |
+---------------------+---------------------+
| Model | GD25B127D |
+---------------------+---------------------+
| Size | 16 MiB |
+---------------------+---------------------+
| Package | SOIC-8 |
+---------------------+---------------------+
| Internal flashing | yes |
+---------------------+---------------------+
| External flashing | yes |
+---------------------+---------------------+
```

The flash chip (U51 on 3050 variant, U52 on 3060 variant) is left of the top DIMM slot.
71 changes: 71 additions & 0 deletions Documentation/mainboard/system76/oryp7.md
@@ -0,0 +1,71 @@
# System76 Oryx Pro 7 (oryp7)

## Specs

- CPU
- Intel Core i7-10870H
- Chipset
- Intel HM470
- EC
- ITE IT5570E running [System76 EC](https://github.com/system76/ec)
- Graphics
- dGPU options
- NVIDIA GeForce RTX 3060
- NVIDIA GeForce RTX 3070 (Max-Q)
- NVIDIA GeForce RTX 3080 (Max-Q)
- eDP display options
- 15.6" 1920x1080@144Hz LCD (LG LP156WFG-SPB3)
- 15.6" 1920x1080@60Hz OLED (Samsung ATNA56WR06)
- 17.3" 1920x1080@144Hz LCD (LG LP173WFG-SPB1)
- 1x HDMI 2.1
- 1x Mini DisplayPort 1.4
- 1x DisplayPort 1.4 over USB-C
- Memory
- Up to 64GB (2x32GB) dual-channel DDR4 SO-DIMMs @ 2933 MHz
- Networking
- Gigabit Ethernet
- M.2 PCIe/CNVi WiFi/Bluetooth
- Intel WiFi 6 AX200/AX201
- Power
- 180W (19.5V, 9.23A) AC barrel adapter
- Chicony A17-180P4A, using a C5 power cord
- 73Wh 3-cell battery
- Sound
- Internal speakers and microphone
- Combined 3.5mm headphone and microphone jack
- Combined 3.5mm microphone and S/PDIF jack
- HDMI, Mini DisplayPort, USB-C DisplayPort audio
- Storage
- 1x M.2 PCIe NVMe or SATA SSD
- 1x M.2 PCIe NVME SSD
- MicroSD card reader
- USB
- 1x USB Type-C with Thunderbolt 3
- 3x USB 3.2 Gen 1 Type-A
- Dimensions
- 15": 35.75cm x 23.8cm x 1.98cm, 1.99kg
- 17": 39.59cm x 26.495cm x 1.99cm, 2.3kg

## Flashing coreboot

```eval_rst
+---------------------+-----------------+
| Type | Value |
+=====================+=================+
| Socketed flash | no |
+---------------------+-----------------+
| Vendor | Macronix |
+---------------------+-----------------+
| Model | MX25L12873F |
+---------------------+-----------------+
| Size | 16 MiB |
+---------------------+-----------------+
| Package | SOIC-8 |
+---------------------+-----------------+
| Internal flashing | yes |
+---------------------+-----------------+
| External flashing | yes |
+---------------------+-----------------+
```

The flash chip (U66) is above the M.2 SSD connectors.
70 changes: 70 additions & 0 deletions Documentation/mainboard/system76/oryp8.md
@@ -0,0 +1,70 @@
# System76 Oryx Pro 8 (oryp8)

## Specs

- CPU
- Intel Core i7-11800H
- Chipset
- Intel HM570
- EC
- ITE IT570E running [System76 EC](https://github.com/system76/ec)
- Graphics
- dGPU options
- NVIDIA GeForce RTX 3070 (Max-Q)
- NVIDIA GeForce RTX 3080 (Max-Q)
- eDP options
- 15.6" 1920x1080@144Hz LCD (LG LP156WFG-SPB3)
- 17.3" 1920x1080@144Hz LCD (LG LP173WFG-SPB3)
- 1x HDMI 2.1
- 1x Mini DisplayPort 1.4
- 1x DisplayPort 1.4 over USB-C
- Memory
- Up to 64GB (2x32GB) dual-channel DDR4 SO-DIMMs @ 3200 MHz
- Networking
- Gigabit Ethernet
- M.2 PCIe/CNVi WiFi/Bluetooth
- Intel Wi-Fi 6 AX200/AX201
- Power
- 180W (19.5V, 9.23A) AC barrel adapter
- Lite-On PA-1181-16, using a C5 power cord
- 73Wh 3-cell battery
- Sound
- Realtek ALC1220 codec
- TI TAS5825M smart amp
- Internal speakers and microphone
- Combined 3.5mm headphone & microphone jack
- Combined 3.5mm microphone & S/PDIF jack
- HDMI, mDP, USB-C DP audio
- Storage
- 1x M.2 PCIe NVMe Gen 4 SSD
- 1x M.2 PCIe NVMe Gen 3 or SATA SSD
- USB
- 1x USB Type-C with Thunderbolt 4
- 3x USB 3.0 Type-A
- Dimensions
- 15": 35.75cm x 23.8cm x 1.98cm, 1.99kg
- 17": 39.59cm x 26.495cm x 1.99cm, 2.3kg

## Flashing coreboot

```eval_rst
+---------------------+-----------------+
| Type | Value |
+=====================+=================+
| Socketed flash | no |
+---------------------+-----------------+
| Vendor | GigaDevice |
+---------------------+-----------------+
| Model | GD25B127D |
+---------------------+-----------------+
| Size | 16 MiB |
+---------------------+-----------------+
| Package | SOIC-8 |
+---------------------+-----------------+
| Internal flashing | yes |
+---------------------+-----------------+
| External flashing | yes |
+---------------------+-----------------+
```

The flash chip (U74) is right of the bottom DIMM slot.
6 changes: 3 additions & 3 deletions Documentation/mainboard/up/squared/index.md
Expand Up @@ -48,7 +48,7 @@
+---------------------+------------+
| Internal flashing | No |
+---------------------+------------+
| In curcuit flashing | Yes |
| In circuit flashing | Yes |
+---------------------+------------+
```

Expand All @@ -67,8 +67,8 @@ The GPIO header is located on the **bottom** side (see [here][overview_bottom_li
The SPI header is located on the **bottom** side (see [here][overview_bottom_link]).
![][header_cn22]

### Preperations
In order to build coreboot, it's neccessary to extract some files from the vendor firmware. Make sure that you have a fully working dump.
### Preparations
In order to build coreboot, it's necessary to extract some files from the vendor firmware. Make sure that you have a fully working dump.
```bash
[upsquared]$ ls
firmware_vendor.rom
Expand Down
37 changes: 0 additions & 37 deletions Documentation/mainboard_io_trap_handler_sample.c

This file was deleted.

4 changes: 2 additions & 2 deletions Documentation/northbridge/intel/sandybridge/nri.md
Expand Up @@ -40,7 +40,7 @@ The memory initialization code has to take care of lots of duties:
+---------+-------------------------------------------------------------------+------------+--------------+
```

## (Unoffical) register documentation
## (Unofficial) register documentation
- [Sandy Bridge - Register documentation](nri_registers.md)

## Frequency selection
Expand Down Expand Up @@ -101,7 +101,7 @@ is stored to MRC cache.
As of writing the only supported error handling is to disable the failing
channel and restart the memory training sequence. It's very likely to succeed,
as memory channels operate independent of each other.
In case no DIMM could be initilized coreboot will halt. The screen will stay
In case no DIMM could be initialized coreboot will halt. The screen will stay
black until you power of your device. On some platforms there's additional
feedback to indicate such an event.

Expand Down
2 changes: 1 addition & 1 deletion Documentation/northbridge/intel/sandybridge/nri_freq.md
Expand Up @@ -42,7 +42,7 @@ Only **XMP profile 1** is being used in case it advertises:
* 1.5V operating voltage
* The channel's installed DIMM count doesn't exceed the XMP coded limit

In case the XMP profile doesn't fullfill those limits, the regular SPD will be
In case the XMP profile doesn't fulfill those limits, the regular SPD will be
used.
> **Note:** XMP Profiles are supported since coreboot 4.4.

Expand Down
Expand Up @@ -1947,7 +1947,7 @@ Please handle with care!
+-----------+------------------------------------------------------------------+
| Bit | Description |
+===========+==================================================================+
| 0:7| OREF_RI, Rank idle period that defines an oppertunity for |
| 0:7| OREF_RI, Rank idle period that defines an opportunity for |
| | refresh |
+-----------+------------------------------------------------------------------+
| 8:11| Refresh_HP_WM, tREFI count level that turns the refresh |
Expand Down
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.11-relnotes.md
Expand Up @@ -136,7 +136,7 @@ removed soon after release.

### `TSEG` and `cbmem_top()` mapping

Significant refactoring has bee done to achieve some consistency across platforms
Significant refactoring has been done to achieve some consistency across platforms
and to reduce code duplication.

### Build system amenities ###
Expand Down
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.13-relnotes.md
Expand Up @@ -200,7 +200,7 @@ a bug in the more involved code to query options.
### Resource allocator v4

A new revision of resource allocator v4 is now added to coreboot that supports
mutiple ranges for allocating resources. Unlike the previous allocator (v3), it does
multiple ranges for allocating resources. Unlike the previous allocator (v3), it does
not use the topmost available window for allocation. Instead, it uses the first
window within the address space that is available and satisfies the resource request.
This allows utilization of the entire available address space and also allows
Expand Down
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.14-relnotes.md
Expand Up @@ -142,7 +142,7 @@ primarily to serve the needs of the server market.
coreboot support for Xeon-SP is in src/soc/intel/xeon_sp directory.
This release has support for SkyLake-SP (SKX-SP) which is the 2nd
generation, and for CooperLake-SP (CPX-SP) which is the 3rd generation
generation, and for Cooper Lake-SP (CPX-SP) which is the 3rd generation
or the latest generation [2] on market.
With this release, the codebase for multiple generations of Xeon-SP
Expand Down
113 changes: 105 additions & 8 deletions Documentation/releases/coreboot-4.15-relnotes.md
@@ -1,14 +1,69 @@
Upcoming release - coreboot 4.15
coreboot 4.15
================================

The 4.15 release is planned for October 2021.
coreboot 4.15 was released on November 5th, 2021.

Update this document with changes that should be in the release notes.
Since 4.14 there have been more than 2597 new commits by more than 219 developers.
Of these, over 73 contributed to coreboot for the first time.

* Please use Markdown.
* See the past few release notes for the general format.
* The chip and board additions and removals will be updated right
before the release, so those do not need to be added.
Welcome to the project!

Thank you to all the developers who continue to make coreboot the
great open source firmware project that it is.

Important Announcement
----------------------
We are going to be changing the cadence from every 6 months, to every 3 months.
That means the 4.16 release will be coming in February, 2022.


New mainboards
--------------
* Asus p8h61-m_pro_cm6630
* Asus p8h77-v
* Asus p8z77-v
* Google nipperkin
* Lenovo w541
* Siemens mc_ehl
* SuperMicro x9sae
* System76 addw1
* System76 addw2
* System76 bonw14
* System76 darp6
* System76 darp7
* System76 galp2
* System76 galp3
* System76 galp3-b
* System76 galp4
* System76 galp5
* System76 gaze14
* System76 lemp10
* System76 oryp7
* System76 oryp8

Removed mainboards
------------------
* Google Mancomb

Deprecations and incompatible changes
-------------------------------------

### COREBOOTPAYLOAD option

Drop the deprecated COREBOOTPAYLOAD option, and replace it with MrChromebox's
updated UefiPayloadPkg option. Simplify the Kconfig options to make it easier
to build from upstream edk2 master. Drop the TIANOCORE_USE_8254_TIMER Kconfig
option since it applies only to CorebootPayloadPkg. Clean up the Makefile now
that we're only building from a single Tianocore package/target.

### Remove old lp4x and ddr4 versions of spd_tools

The migration to the new unified version of spd_tools is complete, so
the old lp4x and ddr4 versions can be removed.

### Remove AMD PI 00630F01

No board currently uses AMD PI 00630F01 so remove it.

Significant changes
-------------------
Expand All @@ -25,5 +80,47 @@ Previously, the default behaviour for Intel chipset lockdown was to let the FSP
do it. Since all related mainboards used the coreboot mechanisms for chipset
lockdown, the default behaviour was changed to that.

### Payloads unit testing

Libpayload now supports the mock architecture, which can be used for unit testing
payloads. (For examples see
[depthcharge](https://chromium.googlesource.com/chromiumos/platform/depthcharge/)
payload)

### Unit testing infrastructure

Unit testing of libpayload is now possible in the same fashion as in the main
coreboot tree.

### Introduce new method for accessing cpu_info

There is currently a fundamental flaw in the current cpu_info()
implementation. It assumes that current stack is CONFIG_STACK_SIZE
aligned. This assumption breaks down when performing SMM relocation.

The first step in performing SMM relocation is changing the SMBASE. This
is accomplished by installing the smmstub at 0x00038000, which is the
default SMM entry point. The stub is configured to set up a new stack
with the size of 1 KiB (CONFIG_SMM_STUB_STACK_SIZE), and an entry point
of smm_do_relocation located in RAMSTAGE RAM.

This means that when smm_do_relocation is executed, it is running in SMM
with a different sized stack. When cpu_info() gets called it will be
using CONFIG_STACK_SIZE to calculate the location of the cpu_info
struct. This results in reading random memory. Since cpu_info() has to
run in multiple environments, we can't use a compile time constant to
locate the cpu_info struct.

### Add significant changes here
This CL introduces a new way of locating cpu_info. It uses a per-cpu
segment descriptor that points to a per-cpu segment that is allocated on
the stack. By using a segment descriptor to point to the per-cpu data,
we no longer need to calculate the location of the cpu_info struct. This
has the following advantages:
* Stacks no longer need to be CONFIG_STACK_SIZE aligned.
* Accessing an unconfigured segment will result in an exception. This
ensures no one can call cpu_info() from an unsupported environment.
* Segment selectors are cleared when entering SMM and restored when
leaving SMM.
* There is a 1:1 mapping between cpu and cpu_info. When using
COOP_MULTITASKING, a new cpu_info is currently allocated at the top of
each thread's stack. This no longer needs to happen.
19 changes: 19 additions & 0 deletions Documentation/releases/coreboot-4.16-relnotes.md
@@ -0,0 +1,19 @@
Upcoming release - coreboot 4.16
================================

The 4.16 release is planned for February, 2022.

We are increasing the frequency of releases in order to enable others to release quarterly on
a fresher version of coreboot.

Update this document with changes that should be in the release notes.

* Please use Markdown.
* See the past few release notes for the general format.
* The chip and board additions and removals will be updated right
before the release, so those do not need to be added.

Significant changes
-------------------

### Add significant changes here
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.3-relnotes.md
Expand Up @@ -124,7 +124,7 @@ X86
Areas with significant work on updates and fixes
------------------------------------------------
* cpu/amd/model_fxx
* intel/fsp1_x: Fix timestanps & postcodes, add native CAR & microcode
* intel/fsp1_x: Fix timestamps & postcodes, add native CAR & microcode
* nb/amd/amdfam10: Add S3, voltage & ACPI, speed fixes & MANY other
changes
* nb/amd/amdmct: Add S3, mem voltage, Fix performance & MANY other
Expand Down
3 changes: 2 additions & 1 deletion Documentation/releases/index.md
Expand Up @@ -15,6 +15,7 @@ Release notes for previous releases
* [4.12 - May 2020](coreboot-4.12-relnotes.md)
* [4.13 - November 2020](coreboot-4.13-relnotes.md)
* [4.14 - May 2021](coreboot-4.14-relnotes.md)
* [4.15 - November 2021](coreboot-4.15-relnotes.md)

The checklist contains instructions to ensure that a release covers all
important things and provides a reliable format for tarballs, branch
Expand All @@ -26,4 +27,4 @@ Upcoming release
----------------

Please add to the release notes as changes are added:
* [4.15 - October 2021](coreboot-4.15-relnotes.md)
* [4.16 - Feb 2022](coreboot-4.16-relnotes.md)
2 changes: 1 addition & 1 deletion Documentation/security/intel/txt.md
Expand Up @@ -37,7 +37,7 @@ More details can be found in the [Intel TXT IBB] chapter.

### Measurements
The IBBs (Initial Boot Blocks) are measured into TPM's PCR0 by the BIOS [ACM]
before the CPU reset vector is executed. To indentify the regions that need
before the CPU reset vector is executed. To identify the regions that need
to be measured, the [FIT] contains one ore multiple *Type 7* entries, that
point to the IBBs.

Expand Down
4 changes: 2 additions & 2 deletions Documentation/security/smm.md
@@ -1,12 +1,12 @@
# x86 System Managment Mode
# x86 System Management 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).
SMM can be entered by issuing System Management Interrupts (SMIs).

## Secure data exchange

Expand Down
78 changes: 44 additions & 34 deletions Documentation/security/vboot/list_vboot.md
Expand Up @@ -31,6 +31,7 @@
- Zako (HP Chromebox G1)
- Butterfly (HP Pavilion Chromebook 14)
- Cherry
- Tomato
- Banon (Acer Chromebook 15 (CB3-532))
- Celes (Samsung Chromebook 3)
- Cyan (Acer Chromebook R11 (C738T))
Expand Down Expand Up @@ -66,60 +67,68 @@
- Nefario
- Rainier
- Guybrush
- Akemi
- Dratini
- Nipperkin
- Dewatt
- Akemi (IdeaPad Flex 5/5i Chromebook)
- Dratini (HP Pro c640 Chromebook)
- Duffy Legacy (32MB)
- Duffy
- Faffy
- Duffy (ASUS Chromebox 4)
- Faffy (ASUS Fanless Chromebox)
- Hatch
- Jinlon
- Jinlon (HP Elite c1030 Chromebook)
- Kaisa Legacy (32MB)
- Kaisa
- Kohaku
- Kindred
- Helios
- Kaisa (Acer Chromebox CXI4)
- Kohaku (Samsung Galaxy Chromebook)
- Kindred (Acer Chromebook 712)
- Helios (ASUS Chromebook Flip C436FA)
- Mushu
- Palkia
- Nightfury
- Noibat
- Nightfury (Samsung Galaxy Chromebook 2)
- Noibat (HP Chromebox G3)
- Puff
- Helios_Diskswap
- Stryke
- Wyvern
- Wyvern (CTL Chromebox CBx2)
- Dooly
- Ambassador
- Genesis
- Scout
- Moonbuggy
- Herobrine
- Senor
- Piglin
- Hoglin
- Guado (ASUS Chromebox CN62)
- Jecht
- Rikku (Acer Chromebox CXI2)
- Tidus (Lenovo ThinkCentre Chromebox)
- Aleena
- Careena
- Aleena/Kasumi (Acer Chromebook 315 (CB315-2H), 311 (C721) / Spin 311 (R721T))
- Barla/Careena (HP Chromebook 11A G6/G8 EE, 14A G5/G6)
- Grunt
- Liara
- Liara (Lenovo 14e Chromebook, Chromebook S345-14)
- Nuwani
- Treeya
- Treeya (Lenovo 100e/300e Gen2 AMD)
- Kukui
- Krane
- Kodama
- Krane (Lenovo Chromebook Duet/Lenovo IdeaPad Duet Chromebook)
- Kodama (Lenovo 10e Chromebook Tablet)
- Kakadu
- Flapjack
- Katsu
- Jacuzzi
- Juniper
- Juniper (Acer Chromebook Spin 311 (CP311-3H))
- Kappa
- Damu
- Damu (ASUS Chromebook Flip CM3 (CM3200))
- Cerise
- Stern
- Willow
- Esche
- Burnet
- Esche (HP Chromebook 11MK G9 EE)
- Burnet (HP Chromebook x360 11MK G3 EE)
- Fennel
- Cozmo
- Makomo
- Munna
- Pico
- Link (Google Chromebook Pixel (2013))
- Mancomb
- Mistral
- Nyan
- Nyan Big (Acer Chromebook 13 (CB5-311))
Expand All @@ -132,7 +141,7 @@
- Atlas (Google Pixelbook Go)
- Poppy
- Nami
- Nautilus (Samsung Chromebook Plus (V2 / LTE))
- Nautilus (Samsung Chromebook Plus V2, V2 LTE)
- Nocturne (Google Pixel Slate)
- Rammus (Asus Chromebook C425, Flip C433, Flip C434)
- Soraka (HP Chromebook x2)
Expand All @@ -158,8 +167,8 @@
- Snappy (HP Chromebook x360 11 G1 EE)
- Nasher
- Coral
- Arcada
- Sarien
- Arcada (Latitude 5300 2-in-1 Chromebook Enterprise)
- Sarien (Dell Latitude 5400 Chromebook Enterprise)
- Falco (HP Chromebook 14)
- Leon (Toshiba Chromebook)
- Peppy (Acer C720/C720P Chromebook)
Expand All @@ -177,8 +186,8 @@
- Pazquel
- Pompom
- Quackingstick
- Trogdor
- Wormdingler
- Trogdor
- Veyron_Jaq (Haier Chromebook 11)
- Veyron_Jerry (Hisense Chromebook 11)
- Veyron_Mighty (Haier Chromebook 11(edu))
Expand All @@ -187,22 +196,23 @@
- Veyron_Mickey (Asus Chromebit CS10)
- Veyron_Rialto
- Dalboz
- Vilboz
- Ezkinil
- Morphius
- Vilboz (Lenovo 100e/300e Gen3 AMD)
- Ezkinil (Acer Chromebook Spin 514)
- Morphius (Lenovo ThinkPad C13 Yoga Chromebook)
- Trembyle
- Berknip
- Woomax
- Dirinboz
- Berknip (HP Pro c645 Chromebook Enterprise)
- Woomax (ASUS Chromebook Flip CM5)
- Dirinboz (HP Chromebook 14a-nd0097nr)
- Shuboz
- Gumboz
- Gumboz (HP Chromebook x360 14a)

## HP
- Z220 SFF Workstation

## Intel
- Alderlake-P RVP
- Alderlake-P RVP with Chrome EC
- Alderlake-P RVP with Microchip EC
- Alderlake-M RVP
- Alderlake-M RVP with Chrome EC
- Basking Ridge CRB
Expand Down
2 changes: 1 addition & 1 deletion Documentation/security/vboot/measured_boot.md
Expand Up @@ -9,7 +9,7 @@ The "Initial Boot Block" or "Core Root of Trust for Measurement" is the first
code block loaded at reset vector and measured by a DRTM solution.
In case SRTM mode is active, the IBB measures itself before measuring the next
code block. In coreboot, cbfs files which are part of the IBB are identified
by a metatdata tag. This makes it possible to have platform specific IBB
by a metadata tag. This makes it possible to have platform specific IBB
measurements without hardcoding them.

## Known Limitations
Expand Down
2 changes: 1 addition & 1 deletion Documentation/soc/cavium/cn81xx/index.md
Expand Up @@ -21,7 +21,7 @@ The SOC folder contains functions for:
* Secondary CPUs
* PCI

All other hardware is initilized by the BDK code, which is invoked from
All other hardware is initialized by the BDK code, which is invoked from
ramstage.

## Notes about the hardware
Expand Down
12 changes: 12 additions & 0 deletions Documentation/soc/intel/fsp/index.md
Expand Up @@ -2,6 +2,18 @@

This section contains documentation about Intel-FSP in public domain.

## Integration Guidelines

Some guiding principles when working on the glue to integrate FSP into
coreboot, e.g. on how to configure a board in devicetree when that affects
the way FSP works:

* It should be possible to replace FSP based boot with a native coreboot
implementation for a given chipset without touching the mainboard code.
* The devicetree configures coreboot and part of what coreboot does with the
information is setting some FSP UPDs. The devicetree isn't supposed to
directly configure FSP.

## Bugs
As Intel doesn't even list known bugs, they are collected here until
those are fixed. If possible a workaround is described here as well.
Expand Down
4 changes: 2 additions & 2 deletions Documentation/superio/common/ssdt.md
Expand Up @@ -50,7 +50,7 @@ end
The following methods are generated for each SuperIO:
## AMTX()
Acquire the global mutex and enter config mode.
It's called this at the begining of an atomic operation to make sure
It's called this at the beginning of an atomic operation to make sure
no other ACPI code messes with the config space while working on it.

## RMTX()
Expand All @@ -63,7 +63,7 @@ This method isn't guarded with the global mutex.

## DLDN(Arg0)
Disables the (virtual) LDN given as Arg0.
This method aquires the global mutex.
This method acquires the global mutex.

## QLDN(Arg0)
Queries the state of the (virtual) LDN given as Arg0.
Expand Down
6 changes: 3 additions & 3 deletions Documentation/superio/nuvoton/nct5539d.md
@@ -1,9 +1,9 @@
# NCT5539D SuperIO
# NCT5539D Super I/O

The SuperIO has the ID `0xd121` and the source can be found in
The Super I/O has the ID `0xd121` and the source can be found in
`src/superio/nuvoton/nct5539d/`.

## For developers

The SuperIO generates ACPI using the
The Super I/O generates ACPI using the
[SSDT generator for generic SuperIOs](../common/ssdt.md).
2 changes: 1 addition & 1 deletion Documentation/superio/nuvoton/npcd378.md
Expand Up @@ -4,7 +4,7 @@ This page describes the [Nuvoton] SuperIO chip that can be found on various [HP]
mainboards.

As no datasheet is available most of the functions have been reverse engineered and
might be inacurate or wrong.
might be inaccurate or wrong.

## LDNs

Expand Down
2 changes: 1 addition & 1 deletion Documentation/technotes/2020-03-unit-testing-coreboot.md
Expand Up @@ -83,7 +83,7 @@ Requirements for unit testing frameworks:

Compiler for the host _must_ support the same language standards as the target
compiler. Ideally the same toolchain should be used for building firmware
executables and test binaries, however the host complier will be used to build
executables and test binaries, however the host compiler will be used to build
unit tests, whereas the coreboot toolchain will be used for building the
firmware executables. For some targets, the host compiler and the target
compiler could be the same, but this is not a requirement.
Expand Down
3 changes: 3 additions & 0 deletions Documentation/technotes/2021-05-code-coverage.md
Expand Up @@ -4,6 +4,9 @@ Code coverage for the coreboot unit tests allows us to see what lines of
code in the coreboot library are covered by unit tests, and allows a test
author to see where they need to add test cases for additional coverage.

Code coverage requires `lcov`; install the tool if necessary by
`sudo apt install lcov` or the equivalent for your system.

Enable code coverage in your unit test build by setting the environment
variable `COV` to 1; either `export COV=1` in your shell, or add it to your
`make` command, e.g. `COV=1 make unit-tests`.
Expand Down
2 changes: 1 addition & 1 deletion Documentation/tutorial/part1.md
Expand Up @@ -123,7 +123,7 @@ are needed to build the coreboot toolchain. `gcc` and `gnat` have to be
of the same version.

If you started with a different distribution or package management system you
might need to install other packages. Most likely they are named sightly
might need to install other packages. Most likely they are named slightly
different. If that is the case for you, we'd like to encourage you to contribute
to the project and submit a pull request with an update for this documentation
for your system.
Expand Down
2 changes: 1 addition & 1 deletion Documentation/util.md
Expand Up @@ -57,7 +57,7 @@ even if hidden `C`
hardware configuration (register contents, MSRs, etc). `C`
* __intelvbttool__ - Parse VBT from VGA BIOS `C`
* __ipqheader__
* _createxbl.py_ - Concatentates XBL segments into one ELF
* _createxbl.py_ - Concatenates XBL segments into one ELF
image `Python`
* _ipqheader.py_ - Returns a packed MBN header image with the
specified base and size `Python`
Expand Down
11 changes: 11 additions & 0 deletions MAINTAINERS
Expand Up @@ -169,6 +169,11 @@ F: src/mainboard/asrock/h81m-hds/



ASUS A88XM-E MAINBOARD
M: Mike Banon <mikebdp2@gmail.com>
S: Maintained
F: src/mainboard/asus/a88xm-e/

ASUS AM1I-A MAINBOARD
M: Mike Banon <mikebdp2@gmail.com>
S: Maintained
Expand Down Expand Up @@ -857,6 +862,12 @@ S: Maintained
F: src/superio/
F: util/superiotool/

SPD UTILITIES
M: Reka Norman <rekanorman@chromium.org>
S: Maintained
F: util/spd_tools/
F: util/spdtool/

MEMLAYOUT
M: Julius Werner <jwerner@chromium.org>
S: Supported
Expand Down
18 changes: 15 additions & 3 deletions Makefile.inc
Expand Up @@ -60,7 +60,7 @@ COREBOOT_EXPORTS += CCACHE_EXTRAFILES
#######################################################################
# root rule to resolve if in build mode (ie. configuration exists)
real-target: $(obj)/config.h coreboot files_added
coreboot: $(obj)/coreboot.rom $(obj)/cbfstool $(obj)/rmodtool $(obj)/ifwitool
coreboot: $(obj)/coreboot.rom $(obj)/cbfstool $(obj)/rmodtool $(obj)/ifwitool $(obj)/cse_fpt $(obj)/cse_serger

# This target can be used in site local to run scripts or additional
# targets after the build completes by creating a Makefile.inc in the
Expand All @@ -81,7 +81,7 @@ PHONY+= clean-abuild coreboot check-style build_complete
# root source directories of coreboot
subdirs-y := src/lib src/commonlib/ src/console src/device src/acpi src/superio/common
subdirs-y += src/ec/acpi $(wildcard src/ec/*/*) $(wildcard src/southbridge/*/*)
subdirs-y += $(wildcard src/soc/*/*) $(wildcard src/northbridge/*/*)
subdirs-y += $(wildcard src/soc/*) $(wildcard src/soc/*/*) $(wildcard src/northbridge/*/*)
subdirs-y += $(wildcard src/superio/*) $(wildcard src/superio/*/*)
subdirs-y += $(wildcard src/drivers/*) $(wildcard src/drivers/*/*) $(wildcard src/drivers/*/*/*)
subdirs-y += src/cpu src/vendorcode
Expand Down Expand Up @@ -544,6 +544,8 @@ RMODTOOL:=$(objutil)/cbfstool/rmodtool
IFWITOOL:=$(objutil)/cbfstool/ifwitool
IFITTOOL:=$(objutil)/cbfstool/ifittool
AMDCOMPRESS:=$(objutil)/cbfstool/amdcompress
CSE_FPT:=$(objutil)/cbfstool/cse_fpt
CSE_SERGER:=$(objutil)/cbfstool/cse_serger

$(obj)/cbfstool: $(CBFSTOOL)
cp $< $@
Expand All @@ -563,6 +565,12 @@ $(obj)/ifittool: $(IFITTOOL)
$(obj)/amdcompress: $(AMDCOMPRESS)
cp $< $@

$(obj)/cse_fpt: $(CSE_FPT)
cp $< $@

$(obj)/cse_serger: $(CSE_SERGER)
cp $< $@

_WINCHECK=$(shell uname -o 2> /dev/null)
STACK=
ifeq ($(_WINCHECK),Msys)
Expand Down Expand Up @@ -689,7 +697,7 @@ install-git-commit-clangfmt:
include util/crossgcc/Makefile.inc

.PHONY: tools
tools: $(objutil)/kconfig/conf $(objutil)/kconfig/toada $(CBFSTOOL) $(objutil)/cbfstool/cbfs-compression-tool $(FMAPTOOL) $(RMODTOOL) $(IFWITOOL) $(objutil)/nvramtool/nvramtool $(objutil)/sconfig/sconfig $(IFDTOOL) $(CBOOTIMAGE) $(AMDFWTOOL) $(AMDCOMPRESS) $(FUTILITY) $(BINCFG) $(IFITTOOL) $(objutil)/supermicro/smcbiosinfo
tools: $(objutil)/kconfig/conf $(objutil)/kconfig/toada $(CBFSTOOL) $(objutil)/cbfstool/cbfs-compression-tool $(FMAPTOOL) $(RMODTOOL) $(IFWITOOL) $(objutil)/nvramtool/nvramtool $(objutil)/sconfig/sconfig $(IFDTOOL) $(CBOOTIMAGE) $(AMDFWTOOL) $(AMDCOMPRESS) $(FUTILITY) $(BINCFG) $(IFITTOOL) $(objutil)/supermicro/smcbiosinfo $(CSE_FPT) $(CSE_SERGER)

###########################################################################
# Common recipes for all stages
Expand Down Expand Up @@ -1209,6 +1217,10 @@ cbfs-files-$(CONFIG_HAVE_RAMSTAGE) += $(CONFIG_CBFS_PREFIX)/ramstage
$(CONFIG_CBFS_PREFIX)/ramstage-file := $(RAMSTAGE)
$(CONFIG_CBFS_PREFIX)/ramstage-type := stage
$(CONFIG_CBFS_PREFIX)/ramstage-compression := $(CBFS_COMPRESS_FLAG)
# The AMD LPC SPI DMA controller requires source files to be 64 byte aligned.
ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA),y)
$(CONFIG_CBFS_PREFIX)/ramstage-align := 64
endif

cbfs-files-$(CONFIG_HAVE_REFCODE_BLOB) += $(CONFIG_CBFS_PREFIX)/refcode
$(CONFIG_CBFS_PREFIX)/refcode-file := $(REFCODE_BLOB)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -102,3 +102,12 @@ were derived from other projects, other (GPL-compatible) licenses may apply.
Please check the individual source files for details.

This makes the resulting coreboot images licensed under the GPL, version 2.


Issues
-----------

If you have any trouble or find any bug, please report an issue in
[this location](https://github.com/pcengines/apu2-documentation/issues). To
create the issue, from the list of available templates select the one, that fits
best the nature of the issue (bug, feature, question or task) and fill it.
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_CBFS_SIZE=0x00200000
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,157b"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu4
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu6
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.15.0.1"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
4 changes: 3 additions & 1 deletion payloads/external/Makefile.inc
Expand Up @@ -201,10 +201,12 @@ payloads/external/tianocore/tianocore/Build/UEFIPAYLOAD.fd tianocore: $(DOTCONFI
CONFIG_TIANOCORE_BOOTSPLASH_FILE=$(CONFIG_TIANOCORE_BOOTSPLASH_FILE) \
CONFIG_TIANOCORE_UEFIPAYLOAD=$(CONFIG_TIANOCORE_UEFIPAYLOAD) \
CONFIG_TIANOCORE_UPSTREAM=$(CONFIG_TIANOCORE_UPSTREAM) \
CONFIG_MMCONF_BASE_ADDRESS=$(CONFIG_MMCONF_BASE_ADDRESS) \
CONFIG_ECAM_MMCONF_BASE_ADDRESS=$(CONFIG_ECAM_MMCONF_BASE_ADDRESS) \
CONFIG_TIANOCORE_ABOVE_4G_MEMORY=$(CONFIG_TIANOCORE_ABOVE_4G_MEMORY) \
CONFIG_TIANOCORE_BOOT_TIMEOUT=$(CONFIG_TIANOCORE_BOOT_TIMEOUT) \
CONFIG_TIANOCORE_CBMEM_LOGGING=$(CONFIG_TIANOCORE_CBMEM_LOGGING) \
CONFIG_TIANOCORE_COREBOOTPAYLOAD=$(CONFIG_TIANOCORE_COREBOOTPAYLOAD) \
CONFIG_TIANOCORE_USE_8254_TIMER=$(CONFIG_TIANOCORE_USE_8254_TIMER) \
GCC_CC_x86_32=$(GCC_CC_x86_32) \
GCC_CC_x86_64=$(GCC_CC_x86_64) \
GCC_CC_arm=$(GCC_CC_arm) \
Expand Down
32 changes: 30 additions & 2 deletions payloads/external/tianocore/Kconfig
Expand Up @@ -14,6 +14,9 @@ choice
UefiPayload: MrChromebox's customized fork of Tianocore which works on most
x86_64 devices
Upstream: Use upstream Tianocore payload from https://github.com/tianocore/edk2
CorebootPayload: MrChromebox's customized fork of the deprecated CorebootPayloadPkg
Tianocore build target. It may work better on some older hardware (eg, x230)
which does not work properly with the UefiPayloadPkg options.

config TIANOCORE_UEFIPAYLOAD
bool "UEFIPayload"
Expand All @@ -26,6 +29,12 @@ config TIANOCORE_UPSTREAM
help
Select this option if you want to use upstream EDK2 to build Tianocore.

config TIANOCORE_COREBOOTPAYLOAD
bool "CorebootPayload"
help
Select this option to build using MrChromebox's older (now deprecated)
CorebootPayloadPkg-based Tianocore branch

endchoice

config TIANOCORE_REVISION_ID
Expand Down Expand Up @@ -76,8 +85,18 @@ config TIANOCORE_BOOTSPLASH_FILE
default "bootsplash.bmp"
help
The path and filename of the file to use as graphical bootsplash
screen. The file format must be uncompressed BMP, and the file's
resolution must be less than the native resolution of the display.
image. The file must be an uncompressed BMP.

This image will also be used as the BGRT boot image, which may
persist through your OS boot process, and will be displayed
vertically centered 38.2% from the top of the display.

See ACPI spec 6.3, 5.2.22 Boot Graphics Resource Table (BGRT), and
Microsoft's documentation on BGRT positioning:
Docs/Windows/Windows Drivers/Bring up guide/Boot screen components

Accordingly, the image used should be no taller/wider than 40% of
the display panel's native pixel height/width (or resolution set).

If an absolute path is not given, the path will assumed to be
relative to the coreboot root directory.
Expand All @@ -95,6 +114,15 @@ config TIANOCORE_ABOVE_4G_MEMORY

endif

if TIANOCORE_COREBOOTPAYLOAD

config TIANOCORE_USE_8254_TIMER
bool "TianoCore 8254 Timer"
help
Use 8254 Timer for legacy support.

endif

config TIANOCORE_BOOT_TIMEOUT
int
default 2
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/tianocore/Kconfig.name
@@ -1,6 +1,6 @@
config PAYLOAD_TIANOCORE
bool "Tianocore payload"
depends on ARCH_X86
depends on ARCH_X86 || ARCH_ARM64
help
Select this option if you want to build a coreboot image
with a Tianocore payload. If you don't know what this is
Expand Down
19 changes: 17 additions & 2 deletions payloads/external/tianocore/Makefile
Expand Up @@ -9,7 +9,14 @@ project_git_repo=https://github.com/3mdeb/edk2
project_git_branch=coreboot-4.7.x-uefi
upstream_git_repo=https://github.com/tianocore/edk2

build_flavor=-D BOOTLOADER=COREBOOT -D PCIE_BASE=$(CONFIG_MMCONF_BASE_ADDRESS) -DPS2_KEYBOARD_ENABLE
build_flavor=-D BOOTLOADER=COREBOOT -D PCIE_BASE=$(CONFIG_ECAM_MMCONF_BASE_ADDRESS) -DPS2_KEYBOARD_ENABLE

ifeq ($(CONFIG_TIANOCORE_COREBOOTPAYLOAD),y)
project_git_branch=coreboot_fb
bootloader=CorebootPayloadPkg
else
bootloader=UefiPayloadPkg
endif

ifeq ($(CONFIG_TIANOCORE_UPSTREAM),y)
TAG=upstream/master
Expand Down Expand Up @@ -41,7 +48,15 @@ endif

TIMEOUT=-D PLATFORM_BOOT_TIMEOUT=$(CONFIG_TIANOCORE_BOOT_TIMEOUT)

ifneq ($(CONFIG_TIANOCORE_USE_8254_TIMER), y)
TIMER=-DUSE_HPET_TIMER
endif

ifeq ($(CONFIG_TIANOCORE_COREBOOTPAYLOAD),y)
BUILD_STR=-q -a IA32 -a X64 -p CorebootPayloadPkg/CorebootPayloadPkgIa32X64.dsc -t COREBOOT -b $(BUILD_TYPE) $(TIMER) -DPS2_KEYBOARD_ENABLE
else
BUILD_STR=-q -a IA32 -a X64 -p UefiPayloadPkg/UefiPayloadPkg.dsc -t COREBOOT -b $(BUILD_TYPE) $(TIMEOUT) $(build_flavor) $(CBMEM) $(4G)
endif

all: clean build

Expand Down Expand Up @@ -99,7 +114,7 @@ build: update checktools
cat ../tools_def.txt >> $(project_dir)/Conf/tools_def.txt; \
fi; \
build $(BUILD_STR); \
mv $(project_dir)/Build/UefiPayloadPkg*/*/FV/UEFIPAYLOAD.fd $(project_dir)/Build/UEFIPAYLOAD.fd; \
mv $(project_dir)/Build/$(bootloader)*/*/FV/UEFIPAYLOAD.fd $(project_dir)/Build/UEFIPAYLOAD.fd; \
git checkout MdeModulePkg/Logo/Logo.bmp > /dev/null 2>&1 || true

clean:
Expand Down
10 changes: 10 additions & 0 deletions payloads/libpayload/Kconfig
Expand Up @@ -121,6 +121,14 @@ config ARCH_ARM64
help
Support the ARM64 architecture

config ARCH_MOCK
bool "Mock architecture (for unit tests)"
help
This enables the mock architecture (for unit tests) that is intended
to be used for testing purposes, to either test payloads or libpayload itself.
It provides necessary headers, but requires mocking (providing implementation
for) arch-specific functions.

endchoice

config MULTIBOOT
Expand Down Expand Up @@ -150,6 +158,7 @@ config BASE_ADDRESS
default 0x04000000 if ARCH_ARM
default 0x80100000 if ARCH_ARM64
default 0x00100000 if ARCH_X86
default 0x00000000 if ARCH_MOCK
help
This is the base address for the payload.

Expand Down Expand Up @@ -480,3 +489,4 @@ config IO_ADDRESS_SPACE
source "arch/arm/Kconfig"
source "arch/arm64/Kconfig"
source "arch/x86/Kconfig"
source "arch/mock/Kconfig"
74 changes: 68 additions & 6 deletions payloads/libpayload/Makefile
Expand Up @@ -74,6 +74,14 @@ HOSTCC = gcc
HOSTCXX = g++
HOSTCFLAGS := -I$(srck) -I$(objk) -g
HOSTCXXFLAGS := -I$(srck) -I$(objk)
HOSTAS ?= as
HOSTLD ?= ld
HOSTNM ?= nm
HOSTOBJCOPY ?= objcopy
HOSTOBJDUMP ?= objdump
HOSTREADELF ?= readelf
HOSTSTRIP ?= strip
HOSTAR ?= ar

DOXYGEN := doxygen
DOXYGEN_OUTPUT_DIR := doxygen
Expand All @@ -95,6 +103,7 @@ include $(HAVE_DOTCONFIG)
ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm
ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86
ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock

ARCH-y := $(ARCHDIR-y)

Expand All @@ -103,18 +112,37 @@ ARCH-y := $(ARCHDIR-y)
ARCH-$(CONFIG_LP_ARCH_ARM) := arm
ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCH-$(CONFIG_LP_ARCH_X86) := x86_32
ARCH-$(CONFIG_LP_ARCH_MOCK) := mock

# Three cases where we don't need fully populated $(obj) lists:
# Five cases where we don't need fully populated $(obj) lists:
# 1. when no .config exists
# 2. when make config (in any flavour) is run
# 3. when make distclean is run
# 4. when make help% or make clean% is run
# 5. when make %-test or make %-tests or make %coverage-report is run
# Don't waste time on reading all Makefile.incs in these cases
ifeq ($(strip $(HAVE_DOTCONFIG)),)
NOCOMPILE:=1
NOCOMPILE := 1
endif
ifneq ($(MAKECMDGOALS),)
ifneq ($(filter %config %clean,$(MAKECMDGOALS)),)
NOCOMPILE:=1
ifneq ($(filter %config %clean clean-% help%,$(MAKECMDGOALS)),)
NOCOMPILE := 1
endif
ifneq ($(filter %clean help% clean%, $(MAKECMDGOALS)),)
UNIT_TEST := 1
endif
endif

ifneq ($(filter help%, $(MAKECMDGOALS)),)
NOCOMPILE := 1
UNIT_TEST := 1
else
ifneq ($(filter %-test %-tests %coverage-report, $(MAKECMDGOALS)),)
ifneq ($(filter-out %-test %-tests %coverage-report, $(MAKECMDGOALS)),)
$(error Cannot mix unit-tests targets with other targets)
endif
NOCOMPILE :=
UNIT_TEST := 1
endif
endif

Expand All @@ -125,10 +153,36 @@ $(xcompile): $(top)/../../util/xcompile/xcompile

ifeq ($(NOCOMPILE),1)
include $(TOPLEVEL)/Makefile.inc
include $(TOPLEVEL)/tests/Makefile.inc
real-all: config

else

ifeq ($(CONFIG_LP_ARCH_MOCK),y)

# Create empty xcompile to satisfy install script
$(shell echo '' > $(xcompile))

CC := $(HOSTCC)
CC-mock := $(HOSTCC)
AS := $(HOSTAS)
AS-mock := $(HOSTAS)
LD := $(HOSTLD)
LD-mock := $(HOSTLD)
NM := $(HOSTNM)
NM-mock := $(HOSTNM)
OBJCOPY := $(HOSTOBJCOPY)
OBJCOPY-mock := $(HOSTOBJCOPY)
OBJDUMP := $(HOSTOBJDUMP)
OBJDUMP-mock := $(HOSTOBJDUMP)
READELF := $(HOSTREADELF)
READELF-mock := $(HOSTEADELF)
STRIP := $(HOSTSTRIP)
STRIP-mock := $(HOSTSTRIP)
AR := $(HOSTAR)
AR-mock := $(HOSTAR)
else

# in addition to the dependency below, create the file if it doesn't exist
# to silence stupid warnings about a file that would be generated anyway.
$(if $(wildcard $(xcompile)),,$(shell \
Expand All @@ -152,12 +206,16 @@ OBJDUMP := $(OBJDUMP_$(ARCH-y))
READELF := $(READELF_$(ARCH-y))
STRIP := $(STRIP_$(ARCH-y))
AR := $(AR_$(ARCH-y))
endif

CFLAGS += -std=gnu11 $(CFLAGS_$(ARCH-y))

ifneq ($(INNER_SCANBUILD),y)
ifeq ($(CONFIG_LP_COMPILER_LLVM_CLANG),y)
CC:=clang -m32
CC:=clang
ifneq ($(CONFIG_LP_ARCH_MOCK),y)
CC += -m32
endif
HOSTCC:=clang
endif
endif
Expand Down Expand Up @@ -244,9 +302,13 @@ evaluate_subdirs= \
$(eval $(call includemakefiles,$(dir)/Makefile.inc))) \
$(if $(subdirs),$(eval $(call evaluate_subdirs)))

# collect all object files eligible for building
# collect all object files eligible for building or run unit-tests
ifneq ($(UNIT_TEST),1)
subdirs:=$(TOPLEVEL)
$(eval $(call evaluate_subdirs))
else
include $(TOPLEVEL)/tests/Makefile.inc
endif

src-to-obj=$(addsuffix .$(1).o, $(basename $(addprefix $(obj)/, $($(1)-srcs))))
$(foreach class,$(classes),$(eval $(class)-objs:=$(call src-to-obj,$(class))))
Expand Down
5 changes: 3 additions & 2 deletions payloads/libpayload/Makefile.inc
Expand Up @@ -33,6 +33,7 @@ export KERNELVERSION := 0.2.0
ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm
ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64
ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86
ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock
DESTDIR ?= install

real-target: lib
Expand Down Expand Up @@ -134,7 +135,7 @@ prepare:

junit.xml:
echo '<?xml version="1.0" encoding="utf-8"?><testsuite>' > $@.tmp
for i in $(filter-out %.old,$(wildcard configs/*)); do \
for i in $(filter-out %.old %.unit-tests,$(wildcard configs/*)); do \
$(MAKE) clean; \
echo "Building libpayload for $$i"; \
cp "$$i" junit_config; \
Expand All @@ -157,7 +158,7 @@ junit.xml:
mv $@.tmp $@

test-configs:
for config in $(filter-out %.old,$(wildcard configs/*)); do \
for config in $(filter-out %.old %.unit-tests,$(wildcard configs/*)); do \
$(MAKE) clean; \
cp "$$config" test_config; \
echo "*** Making libpayload config $$config ***"; \
Expand Down
16 changes: 16 additions & 0 deletions payloads/libpayload/arch/mock/Kconfig
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-only

if ARCH_MOCK

config ARCH_MOCK_BIG_ENDIAN
bool "Use big-endian for mock architecture"
default n
help
This option enables big-endinan support in the code.

config ARCH_SPECIFIC_OPTIONS
def_bool y
select LITTLE_ENDIAN if !ARCH_MOCK_BIG_ENDIAN
select BIG_ENDIAN if ARCH_MOCK_BIG_ENDIAN

endif
7 changes: 7 additions & 0 deletions payloads/libpayload/arch/mock/Makefile.inc
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only

head.o-y += head.c

libc-y += virtual.c

libcbfs-$(CONFIG_LP_CBFS) += mock_media.c
3 changes: 3 additions & 0 deletions payloads/libpayload/arch/mock/head.c
@@ -0,0 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/* This file is empty on purpose. It should not be used. */
3 changes: 3 additions & 0 deletions payloads/libpayload/arch/mock/libpayload.ldscript
@@ -0,0 +1,3 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/* This file is empty on purpose. It is present only to satisfy install script */
10 changes: 10 additions & 0 deletions payloads/libpayload/arch/mock/mock_media.c
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cbfs.h>

int libpayload_init_default_cbfs_media(struct cbfs_media *media);

__attribute__((weak)) int libpayload_init_default_cbfs_media(struct cbfs_media *media)
{
return -1;
}
10 changes: 10 additions & 0 deletions payloads/libpayload/arch/mock/virtual.c
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <unistd.h>

unsigned long virtual_offset = 0;

int getpagesize(void)
{
return 4096;
}
13 changes: 12 additions & 1 deletion payloads/libpayload/bin/lpgcc
Expand Up @@ -91,13 +91,24 @@ if [ "$CONFIG_LP_ARCH_X86" = "y" ]; then
_ARCHEXTRA="-m32 "
_ARCH=x86
fi
if [ "$CONFIG_LP_ARCH_MOCK" = "y" ]; then
_ARCHINCDIR=$_INCDIR/mock
_ARCHLIBDIR=$_LIBDIR/mock
_ARCHEXTRA=""
_ARCH=mock
fi

if [ -f $_LIBDIR/libpayload.ldscript ]; then
_LDDIR=$_LIBDIR
elif [ -f $BASE/../arch/$_ARCH/libpayload.ldscript ]; then
_LDDIR=$BASE/../arch/$_ARCH
fi
_LDSCRIPT="-Wl,-T,$_LDDIR/libpayload.ldscript"
# Host arch should youse default linker script
if [ "$CONFIG_LP_ARCH_MOCK" = "y" ]; then
_LDSCRIPT=""
else
_LDSCRIPT="-Wl,-T,$_LDDIR/libpayload.ldscript"
fi

trygccoption() {
$DEFAULT_CC $1 -S -xc /dev/null -o /dev/null &> /dev/null
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/configs/config.herobrine
Expand Up @@ -2,3 +2,4 @@ CONFIG_LP_CHROMEOS=y
CONFIG_LP_ARCH_ARM64=y
CONFIG_LP_TIMER_ARM64_ARCH=y
CONFIG_LP_SERIAL_CONSOLE=y
CONFIG_LP_QUALCOMM_QUPV3_SERIAL_CONSOLE=y
2 changes: 2 additions & 0 deletions payloads/libpayload/configs/config.unit-tests
@@ -0,0 +1,2 @@
CONFIG_LP_ARCH_MOCK=y
CONFIG_LP_ARCH_BIG_ENDIAN=n
38 changes: 18 additions & 20 deletions payloads/libpayload/drivers/video/graphics.c
Expand Up @@ -274,19 +274,12 @@ static inline uint32_t calculate_color(const struct rgb_color *rgb,
* Plot a pixel in a framebuffer. This is called from tight loops. Keep it slim
* and do the validation at callers' site.
*/
static inline void set_pixel_raw(struct vector *rcoord, uint32_t color)
static inline void set_pixel(struct vector *coord, uint32_t color)
{
const int bpp = fbinfo->bits_per_pixel;
const int bpl = fbinfo->bytes_per_line;
int i;
uint8_t * const pixel = FB + rcoord->y * bpl + rcoord->x * bpp / 8;
for (i = 0; i < bpp / 8; i++)
pixel[i] = (color >> (i * 8));
}

static inline void set_pixel(struct vector *coord, uint32_t color)
{
struct vector rcoord;
int i;

switch (fbinfo->orientation) {
case CB_FB_ORIENTATION_NORMAL:
Expand All @@ -308,7 +301,9 @@ static inline void set_pixel(struct vector *coord, uint32_t color)
break;
}

set_pixel_raw(&rcoord, color);
uint8_t * const pixel = FB + rcoord.y * bpl + rcoord.x * bpp / 8;
for (i = 0; i < bpp / 8; i++)
pixel[i] = (color >> (i * 8));
}

/*
Expand Down Expand Up @@ -625,22 +620,25 @@ int clear_screen(const struct rgb_color *rgb)
if (cbgfx_init())
return CBGFX_ERROR_INIT;

struct vector p;
int x, y, i;
uint32_t color = calculate_color(rgb, 0);
const int bpp = fbinfo->bits_per_pixel;
const int bpl = fbinfo->bytes_per_line;
uint8_t *line = malloc(bpl);

/* If all significant bytes in color are equal, fastpath through memset.
* We assume that for 32bpp the high byte gets ignored anyway. */
if ((((color >> 8) & 0xff) == (color & 0xff)) && (bpp == 16 ||
(((color >> 16) & 0xff) == (color & 0xff)))) {
memset(FB, color & 0xff, fbinfo->y_resolution * bpl);
} else {
for (p.y = 0; p.y < fbinfo->y_resolution; p.y++)
for (p.x = 0; p.x < fbinfo->x_resolution; p.x++)
set_pixel_raw(&p, color);
if (!line) {
LOG("Failed to allocate line buffer (%u bytes)\n", bpl);
return CBGFX_ERROR_UNKNOWN;
}

/* Set line buffer pixels, then memcpy to framebuffer */
for (x = 0; x < fbinfo->x_resolution; x++)
for (i = 0; i < bpp / 8; i++)
line[x * bpp / 8 + i] = (color >> (i * 8));
for (y = 0; y < fbinfo->y_resolution; y++)
memcpy(FB + y * bpl, line, bpl);

free(line);
return CBGFX_SUCCESS;
}

Expand Down
13 changes: 13 additions & 0 deletions payloads/libpayload/include/mock/arch/barrier.h
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ARCH_BARRIER_H__
#define __ARCH_BARRIER_H__

/* No memory barrier on mock build */
#define mb()
/* No read memory barrier on mock build */
#define rmb()
/* No write memory barrier on mock build */
#define wmb()

#endif /* __ARCH_BARRIER_H__ */
18 changes: 18 additions & 0 deletions payloads/libpayload/include/mock/arch/cache.h
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ARCH_CACHE_H__
#define __ARCH_CACHE_H__

/* No support for cache in the mock architecture */

#define dmb()
#define dsb()
#define dcache_clean_all()
#define dcache_clean_by_mva(addr, len)
#define dcache_invalidate_all()
#define dcache_invalidate_by_mva(addr, len)
#define dcache_clean_invalidate_all()
#define dcache_clean_invalidate_by_mva(addr, len)
#define cache_sync_instructions()

#endif /* __ARCH_CACHE_H__ */
46 changes: 46 additions & 0 deletions payloads/libpayload/include/mock/arch/io.h
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _ARCH_IO_H
#define _ARCH_IO_H

#include <inttypes.h>

/* Functions in this file are unimplemented by default. Tests are expected to implement
mocks for these functions, if tests will call functions using functions listed below. */

uint8_t readb(volatile const void *_a);
uint16_t readw(volatile const void *_a);
uint32_t readl(volatile const void *_a);

void writeb(uint8_t _v, volatile void *_a);
void writew(uint16_t _v, volatile void *_a);
void writel(uint32_t _v, volatile void *_a);

uint8_t read8(volatile const void *addr);
uint16_t read16(volatile const void *addr);
uint32_t read32(volatile const void *addr);
uint64_t read64(volatile const void *addr);

void write8(volatile void *addr, uint8_t val);
void write16(volatile void *addr, uint16_t val);
void write32(volatile void *addr, uint32_t val);
void write64(volatile void *addr, uint64_t val);

/* x86 I/O functions */
unsigned int inl(int port);
unsigned short inw(int port);
unsigned char inb(int port);

void outl(unsigned int val, int port);
void outw(unsigned short val, int port);
void outb(unsigned char val, int port);

void outsl(int port, const void *addr, unsigned long count);
void outsw(int port, const void *addr, unsigned long count);
void outsb(int port, const void *addr, unsigned long count);

void insl(int port, void *addr, unsigned long count);
void insw(int port, void *addr, unsigned long count);
void insb(int port, void *addr, unsigned long count);

#endif /* _ARCH_IO_H */
33 changes: 33 additions & 0 deletions payloads/libpayload/include/mock/arch/types.h
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _ARCH_TYPES_H
#define _ARCH_TYPES_H

typedef unsigned char uint8_t;
typedef unsigned char u8;
typedef signed char int8_t;
typedef signed char s8;

typedef unsigned short uint16_t;
typedef unsigned short u16;
typedef signed short int16_t;
typedef signed short s16;

typedef unsigned int uint32_t;
typedef unsigned int u32;
typedef signed int int32_t;
typedef signed int s32;

typedef unsigned long long uint64_t;
typedef unsigned long long u64;
typedef signed long long int64_t;
typedef signed long long s64;

typedef long time_t;
typedef long suseconds_t;

#ifndef NULL
#define NULL ((void *)0)
#endif

#endif /* _ARCH_TYPES_H */
15 changes: 15 additions & 0 deletions payloads/libpayload/include/mock/arch/virtual.h
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _ARCH_VIRTUAL_H
#define _ARCH_VIRTUAL_H

/* virtual_offset has to be declared if used */
extern unsigned long virtual_offset;

#define virt_to_phys(virt) ((unsigned long)(virt) + virtual_offset)
#define phys_to_virt(phys) ((void *)((unsigned long)(phys) - virtual_offset))

#define virt_to_bus(addr) virt_to_phys(addr)
#define bus_to_virt(addr) phys_to_virt(addr)

#endif
5 changes: 5 additions & 0 deletions payloads/libpayload/sample/Makefile
Expand Up @@ -26,8 +26,13 @@
## SUCH DAMAGE.
##


# Sample libpayload Makefile.
include ../.config
ifeq ($(CONFIG_LP_ARCH_MOCK),y)
$(error This sample program does not support ARCH_MOCK. Use sample/arch_mock instead)
endif

include ../build/xcompile

ARCH-$(CONFIG_LP_ARCH_ARM) := arm
Expand Down
48 changes: 48 additions & 0 deletions payloads/libpayload/sample/arch_mock/Makefile
@@ -0,0 +1,48 @@
# SPDX-License-Identifier: GPL-2.0-only

# Sample libpayload Makefile for ARCH_MOCK
# ARCH_MOCK is not intended to be used with xcompile
include ../../.config

ifneq ($(CONFIG_LP_ARCH_MOCK),y)
$(error This example supports ARCH_MOCK only.)
endif

CC := gcc
AS := as
OBJCOPY := objcopy
LIBPAYLOAD_DIR := ../../install/libpayload
CFLAGS := -fno-builtin -Wall -Werror -Os \
-include $(LIBPAYLOAD_DIR)/include/kconfig.h \
-include $(LIBPAYLOAD_DIR)/include/compiler.h \
-I $(LIBPAYLOAD_DIR)/include \
-I $(LIBPAYLOAD_DIR)/include/mock \
-ffunction-sections \
-fdata-sections -g3
LDFLAGS := -Wl,--gc-sections
TARGET := hello
OBJS := $(TARGET).o
OBJS-mock := $(TARGET)_mocks.o
LIBPAYLOAD-local := libpayload.a
mocks := console_write

all: $(TARGET).elf

$(TARGET).elf: $(OBJS) $(OBJS-mock) $(LIBPAYLOAD-local)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBPAYLOAD-local) \
-Wl,--exclude-libs,ALL -lc $(OBJS-mock)

%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<

%.S.o: %.S
$(AS) --32 -o $@ $<

# Copy libpayload and weaken all mocked symbols
$(LIBPAYLOAD-local): $(LIBPAYLOAD_DIR)/lib/libpayload.a
$(OBJCOPY) $(foreach mock,$(mocks),--weaken-symbol=$(mock)) $< $@

clean:
rm -f $(TARGET).elf *.o $(LIBPAYLOAD-local)

distclean: clean
13 changes: 13 additions & 0 deletions payloads/libpayload/sample/arch_mock/hello.c
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/* Example file for libpayload. */

#include <libpayload-config.h>
#include <libpayload.h>

int main(void)
{
printf("Hello world!\n");
halt();
return 0;
}
43 changes: 43 additions & 0 deletions payloads/libpayload/sample/arch_mock/hello_mocks.c
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <libpayload-config.h>
#include <arch/types.h>
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>

/* Use libc version. calling exit() or abort() would cause infinite recursion */
__attribute__((noreturn))
void _exit(int);

__attribute__((noreturn))
void halt(void)
{
_exit(0);
}

#define TEST_SYMBOL(symbol, value) asm(".set " #symbol ", " #value "\n\t.globl " #symbol)

#define TEST_REGION(region, size) uint8_t _##region[size]; \
TEST_SYMBOL(_e##region, _##region + size); \
TEST_SYMBOL(_##region##_size, size)

TEST_REGION(heap, CONFIG_LP_HEAP_SIZE);

uint64_t timer_raw_value(void)
{
return 0;
}

uint64_t timer_hz(void)
{
return 0;
}

/* Not present in libpayload. Can be used to write to real stdout. */
ssize_t write(int fildes, const void *buf, size_t nbyte);

void console_write(const void *buffer, size_t count)
{
write(1, buffer, count);
}
277 changes: 277 additions & 0 deletions payloads/libpayload/tests/Makefile.inc
@@ -0,0 +1,277 @@
# SPDX-License-Identifier: GPL-2.0-only

testsrc := $(top)/tests

# Place the build output in one of two places depending on COV, so that code
# built with code coverage never mixes with code built without code coverage.
ifeq ($(COV),1)
testobj := $(obj)/coverage
else
testobj := $(obj)/tests
endif
coverage-dir := $(testobj)/coverage_reports

coreboottop := ../../

cmockasrc := $(coreboottop)/3rdparty/cmocka
cmockaobj := $(objutil)/cmocka
CMOCKA_LIB := $(cmockaobj)/src/libcmocka.so

CMAKE := cmake

TEST_DEFAULT_CONFIG := $(top)/configs/config.unit-tests
TEST_DOTCONFIG := $(testobj)/.config
TEST_KCONFIG_AUTOHEADER := $(testobj)/libpayload-config.src.h
TEST_KCONFIG_AUTOCONFIG := $(testobj)/auto.conf
TEST_KCONFIG_DEPENDENCIES := $(testobj)/auto.conf.cmd
TEST_KCONFIG_SPLITCONFIG := $(testobj)/config/
TEST_KCONFIG_TRISTATE := $(testobj)/tristate.conf
TEST_KCONFIG_NEGATIVES := 1
TEST_KBUILD_KCONFIG := $(top)/Kconfig
TEST_CONFIG_ := CONFIG_LP_


# Default includes
TEST_CFLAGS := -include include/kconfig.h -include include/compiler.h
TEST_CFLAGS += -Iinclude -Iinclude/mock
TEST_CFLAGS += -I$(dir $(TEST_KCONFIG_AUTOHEADER))

# Test specific includes
TEST_CFLAGS += -I$(testsrc)/include -I$(testsrc)/include/mocks
TEST_CFLAGS += -I$(cmockasrc)/include

# Minimal subset of warnings and errors. Tests can be less strict than actual build.
TEST_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wvla
TEST_CFLAGS += -Wwrite-strings -Wno-trigraphs -Wimplicit-fallthrough
TEST_CFLAGS += -Wstrict-aliasing -Wshadow -Werror

TEST_CFLAGS += -std=gnu11 -Os -ffunction-sections -fdata-sections -fno-builtin

# Make unit-tests detectable by the code
TEST_CFLAGS += -D__TEST__

# Link against CMocka
TEST_LDFLAGS := -L$(dir $(CMOCKA_LIB)) -lcmocka -Wl,-rpath=$(dir $(CMOCKA_LIB))

TEST_LDFLAGS += -Wl,--gc-sections

# Disable userspace relocations
TEST_CFLAGS += -fno-pie -fno-pic
TEST_LDFLAGS += -no-pie

ifeq ($(COV),1)
TEST_CFLAGS += --coverage
TEST_LDFLAGS += --coverage
endif


# Extra attributes for unit tests. Declated per each test. Only `srcs` is required.
attributes := cflags config mocks srcs

alltests :=
subdirs := tests/crypto tests/curses tests/drivers tests/gdb tests/libc tests/libcbfs
subdirs += tests/liblz4 tests/liblzma tests/libpci

define tests-handler
alltests += $(1)$(2)
$(foreach attribute,$(attributes), \
$(eval $(1)$(2)-$(attribute) += $($(2)-$(attribute))))
$(foreach attribute,$(attributes), \
$(eval $(2)-$(attribute) := ))
endef

# Copy attributes of one test to another
# $1 - input test name
# $2 - output test name
copy-test = $(foreach attribute,$(attributes), \
$(eval $(strip $(2))-$(attribute) := $($(strip $(1))-$(attribute))))

$(call add-special-class,tests)
$(call evaluate_subdirs)

# Create actual targets for unit test binaries
# $1 - test name
define TEST_CC_template

# Generate custom config.h redefining given config symbols, and declaring mocked
# functions weak. It is important that the compiler already sees that they are
# weak (and they aren't just turned weak at a later stage) to prevent certain
# optimizations that would break if the function gets replaced. (For clang this
# file needs to be marked `system_header` to prevent it from warning about
# `#pragma weak` entries without a matching function declaration, since there is
# no -Wno-xxx commandline for that.)
$(1)-config-file := $(testobj)/$(1)/libpayload-config.h
$$($(1)-config-file): $(TEST_KCONFIG_AUTOHEADER)
mkdir -p $$(dir $$@);
printf '// File generated by tests/Makefile.inc\n// Do not change\n' > $$@;
printf '#ifndef TEST_LIBPAYLOAD_CONFIG_H_\n' >> $$@;
printf '#define TEST_LIBPAYLOAD_CONFIG_H_\n' >> $$@;
printf '#include <%s>\n\n' "$(notdir $(TEST_KCONFIG_AUTOHEADER))" >> $$@;
for kv in $$($(1)-config); do \
key="`echo $$$$kv | cut -d '=' -f -1`"; \
value="`echo $$$$kv | cut -d '=' -f 2-`"; \
printf '#undef %s\n' "$$$$key" >> $$@; \
printf '#define %s %s\n\n' "$$$$key" "$$$$value" >> $$@; \
done
printf '#ifdef __clang__\n' >> $$@;
printf '#pragma clang system_header\n' >> $$@;
printf '#endif\n\n' >> $$@;
printf '#ifdef __TEST_SRCOBJ__\n' >> $$@;
for m in $$($(1)-mocks); do \
printf '#pragma weak %s\n' "$$$$m" >> $$@; \
done
printf '#endif\n\n' >> $$@;
printf '#endif\n' >> $$@;

$($(1)-objs): TEST_CFLAGS += -I$$(dir $$($(1)-config-file)) \
-D__TEST_NAME__=\"$(subst /,_,$(1))\"

# Give us a way to distinguish between libpayload source files and test files in the code.
$($(1)-srcobjs): TEST_CFLAGS += -D__TEST_SRCOBJ__

# Compile sources and apply mocking/wrapping for selected symbols.
# For each listed mock add new symbol with prefix `__real_`,
# pointing to the same section:address. This will keep original
# function accessible if required.
$($(1)-objs): $(testobj)/$(1)/%.o: $$$$*.c $$($(1)-config-file)
mkdir -p $$(dir $$@)
$(HOSTCC) $$(TEST_CFLAGS) $($(1)-cflags) -MMD \
-MF $$(basename $$@).d -MT $$@ -c $$< -o $$@.orig
objcopy_wrap_flags=''; \
for sym in $$($(1)-mocks); do \
sym_line="$$$$($(HOSTOBJDUMP) -t $$@.orig \
| grep -E \"[0-9a-fA-F]+\\s+w\\s+F\\s+.*\\s$$$$sym$$$$\")"; \
if [ ! -z "$$$$sym_line" ] ; then \
addr="$$$$(echo \"$$$$sym_line\" | awk '{ print $$$$1 }')"; \
section="$$$$(echo \"$$$$sym_line\" | awk '{ print $$$$(NF - 2) }')"; \
objcopy_wrap_flags="$$$$objcopy_wrap_flags --add-symbol __real_$$$${sym}=$$$${section}:0x$$$${addr},function,global"; \
fi \
done ; \
$(HOSTOBJCOPY) $$@.orig $$$$objcopy_wrap_flags $$@

$($(1)-bin): $($(1)-objs) $(CMOCKA_LIB)
$(HOSTCC) $$^ $($(1)-cflags) $$(TEST_LDFLAGS) -o $$@

endef

$(foreach test,$(alltests), \
$(eval $(test)-srcobjs := $(addprefix $(testobj)/$(test)/, \
$(patsubst %.c,%.o,$(filter-out tests/%,$($(test)-srcs))))) \
$(eval $(test)-objs := $(addprefix $(testobj)/$(test)/, \
$(patsubst %.c,%.o,$($(test)-srcs)))) \
$(eval $(test)-bin := $(testobj)/$(test)/run))
$(foreach test,$(alltests), \
$(eval $(call TEST_CC_template,$(test))))
$(foreach test,$(alltests), \
$(eval all-test-objs += $($(test)-objs)) \
$(eval test-bins += $($(test)-bin)))

DEPENDENCIES += $(addsuffix .d,$(basename $(all-test-objs)))
-include $(DEPENDENCIES)

# Build CMocka
$(CMOCKA_LIB):
echo "*** Building CMOCKA ***"
mkdir -p $(cmockaobj)
cd $(cmockaobj) && $(CMAKE) $(abspath $(cmockasrc))
$(MAKE) -C $(cmockaobj)

# Kconfig targets
$(TEST_DOTCONFIG):
mkdir -p $(dir $@)
cp $(TEST_DEFAULT_CONFIG) $(TEST_DOTCONFIG)

$(TEST_KCONFIG_AUTOHEADER): TEST_KCONFIG_FLAGS := DOTCONFIG=$(TEST_DOTCONFIG) \
KCONFIG_AUTOHEADER=$(TEST_KCONFIG_AUTOHEADER) \
KCONFIG_AUTOCONFIG=$(TEST_KCONFIG_AUTOCONFIG) \
KCONFIG_DEPENDENCIES=$(TEST_KCONFIG_DEPENDENCIES) \
KCONFIG_SPLITCONFIG=$(TEST_KCONFIG_SPLITCONFIG) \
KCONFIG_TRISTATE=$(TEST_KCONFIG_TRISTATE) \
KCONFIG_NEGATIVES=$(TEST_KCONFIG_NEGATIVES) \
KBUILD_KCONFIG=$(TEST_KBUILD_KCONFIG) \
KBUILD_DEFCONFIG=$(TEST_DEFAULT_CONFIG) \
CONFIG_=$(TEST_CONFIG_)

$(TEST_KCONFIG_AUTOHEADER): $(TEST_DOTCONFIG) $(objk)/conf
mkdir -p $(dir $@)
$(MAKE) $(TEST_KCONFIG_FLAGS) olddefconfig V=$(V)
$(MAKE) $(TEST_KCONFIG_FLAGS) syncconfig V=$(V)

$(TEST_KCONFIG_AUTOCONFIG): $(TEST_KCONFIG_AUTOHEADER)
true

.PHONY: $(alltests) $(addprefix clean-,$(alltests))
.PHONY: unit-tests build-unit-tests run-unit-tests clean-unit-tests

ifeq ($(JUNIT_OUTPUT),y)
$(alltests): export CMOCKA_MESSAGE_OUTPUT=xml
$(alltests): export CMOCKA_XML_FILE=$(testobj)/junit-%g.xml
endif

$(alltests): $$($$(@)-bin)
rm -f $(testobj)/junit-libpayload-$(subst /,_,$(patsubst $(testobj)/%/,%,$(dir $^)))\(*\).xml
rm -f $(testobj)/$(subst /,_,$^).failed
-$^ || echo failed > $(testobj)/$(subst /,_,$^).failed

# Build a code coverage report by collecting all the gcov files into a single
# report. If COV is not set, this might be a user error, and they're trying
# to generate a coverage report without first having built and run the code
# with code coverage. absence of COV=1 will be corrected.

.PHONY: coverage-report clean-coverage-report

ifeq ($(COV),1)
coverage-report:
lcov -o $(testobj)/tests.info -c -d $(testobj) --exclude '$(testsrc)/*'
genhtml -q -o $(coverage-dir) -t "coreboot unit tests" -s $(testobj)/tests.info

clean-coverage-report:
rm -Rf $(coverage-dir)
else
coverage-report:
COV=1 V=$(V) $(MAKE) coverage-report

clean-coverage-report:
COV=1 V=$(V) $(MAKE) clean-coverage-report
endif

unit-tests: build-unit-tests run-unit-tests

build-unit-tests: $(test-bins)

run-unit-tests: $(alltests)
if [ `find $(testobj) -name '*.failed' | wc -l` -gt 0 ]; then \
echo "**********************"; \
echo " TESTS FAILED"; \
echo "**********************"; \
exit 1; \
else \
echo "**********************"; \
echo " ALL TESTS PASSED"; \
echo "**********************"; \
exit 0; \
fi

$(addprefix clean-,$(alltests)): clean-%
rm -rf $(testobj)/$*

clean-unit-tests:
rm -rf $(testobj)

list-unit-tests:
@echo "unit-tests:"
for t in $(sort $(alltests)); do \
echo " $$t"; \
done

help-unit-tests help::
@echo '*** libpayload unit-tests targets ***'
@echo ' Use "COV=1 make [target]" to enable code coverage for unit tests'
@echo ' unit-tests - Run all unit-tests from tests/'
@echo ' clean-unit-tests - Remove unit-tests build artifacts'
@echo ' list-unit-tests - List all unit-tests'
@echo ' <unit-test> - Build and run single unit-test'
@echo ' clean-<unit-test> - Remove single unit-test build artifacts'
@echo ' coverage-report - Generate a code coverage report'
@echo ' clean-coverage-report - Remove the code coverage report'
@echo
8 changes: 8 additions & 0 deletions payloads/libpayload/tests/drivers/Makefile.inc
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only

tests-y += speaker-test

speaker-test-srcs += tests/drivers/speaker-test.c
speaker-test-mocks += inb
speaker-test-mocks += outb
speaker-test-mocks += arch_ndelay
147 changes: 147 additions & 0 deletions payloads/libpayload/tests/drivers/speaker-test.c
@@ -0,0 +1,147 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <libpayload.h>

/* Include source to gain access to private defines */
#include "../drivers/speaker.c"

#include <tests/test.h>

void outb(unsigned char val, int port)
{
check_expected(val);
check_expected(port);
}

unsigned char inb(int port)
{
check_expected(port);
return mock_type(unsigned char);
}

static void setup_speaker_enable_calls(u16 freq, u8 port_val)
{
/* Minimal correct value should be at leaset 256. For values lowe than that,
counter will have an incorrect value. Regardless, there is */
u16 reg16 = 1193180 / freq;

/* Select counter 2 */
expect_value(outb, val, 0xb6);
expect_value(outb, port, I82C54_CONTROL_WORD_REGISTER);

/* Write freq. [LSB, MSB] */
expect_value(outb, val, (u8)(reg16 & 0xff));
expect_value(outb, port, I82C54_COUNTER2);
expect_value(outb, val, (u8)(reg16 >> 8));
expect_value(outb, port, I82C54_COUNTER2);

/* Enable PC speaker */
expect_value(inb, port, PC_SPEAKER_PORT);
will_return(inb, port_val);
expect_value(outb, val, port_val | 0x3);
expect_value(outb, port, PC_SPEAKER_PORT);
}

static void test_speaker_enable(void **state)
{
setup_speaker_enable_calls(1, 0);
speaker_enable(1);

setup_speaker_enable_calls(1, 0xff);
speaker_enable(1);

setup_speaker_enable_calls(1, 123);
speaker_enable(1);

setup_speaker_enable_calls(1, -1);
speaker_enable(1);

setup_speaker_enable_calls(-1, 0);
speaker_enable(-1);

setup_speaker_enable_calls(-1, 0xff);
speaker_enable(-1);

setup_speaker_enable_calls(-1, 222);
speaker_enable(-1);

setup_speaker_enable_calls(-1, -1);
speaker_enable(-1);

setup_speaker_enable_calls(10000, 0);
speaker_enable(10000);

setup_speaker_enable_calls(10000, 0xff);
speaker_enable(10000);

setup_speaker_enable_calls(10000, 91);
speaker_enable(10000);

setup_speaker_enable_calls(10000, -1);
speaker_enable(10000);
}

static void setup_speaker_disable_calls(u8 value)
{
expect_value(inb, port, PC_SPEAKER_PORT);
will_return(inb, value);
expect_value(outb, val, value & 0xfc);
expect_value(outb, port, PC_SPEAKER_PORT);
}

static void test_speaker_disable(void **state)
{
setup_speaker_disable_calls(0);
speaker_disable();

setup_speaker_disable_calls(0xfc);
speaker_disable();

setup_speaker_disable_calls(0xff);
speaker_disable();

setup_speaker_disable_calls(0xff - 0xfc);
speaker_disable();
}

void arch_ndelay(uint64_t ns)
{
check_expected(ns);
}

static void setup_speaker_tone_calls(u16 freq, unsigned int duration)
{
setup_speaker_enable_calls(freq, ~freq & 0xff);
expect_value(arch_ndelay, ns, (uint64_t)duration * NSECS_PER_MSEC);
setup_speaker_disable_calls(0xff);
expect_any(arch_ndelay, ns);
}

static void test_speaker_tone(void **state)
{
setup_speaker_tone_calls(500, 100);
speaker_tone(500, 100);

setup_speaker_tone_calls(4321, 0);
speaker_tone(4321, 0);

setup_speaker_tone_calls(-1, -1);
speaker_tone(-1, -1);

setup_speaker_tone_calls(10000, 1000);
speaker_tone(10000, 1000);

setup_speaker_tone_calls(433, 890);
speaker_tone(433, 890);
}

int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_speaker_enable),
cmocka_unit_test(test_speaker_disable),
cmocka_unit_test(test_speaker_tone),
};

return lp_run_group_tests(tests, NULL, NULL);
}
52 changes: 52 additions & 0 deletions payloads/libpayload/tests/include/tests/test.h
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _TESTS_TEST_H
#define _TESTS_TEST_H

/*
* Standard test header that should be included in all tests. For now it just encapsulates the
* include dependencies for Cmocka. Test-specific APIs that are so generic we would want them
* available everywhere could also be added here.
*/

#include <arch/types.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* Helper macro to aviud checkpatch errors for some macros */
#define EMPTY_WRAP(...) __VA_ARGS__

/*
* Set symbol value and make it global.
*/
#define TEST_SYMBOL(symbol, value) asm(".set " #symbol ", " #value "\n\t.globl " #symbol)

/*
* Define memory region for testing purpose.
*
* Create buffer with specified name and size.
* Create end symbol for it.
*/
#define TEST_REGION(region, size) uint8_t _##region[size]; \
TEST_SYMBOL(_e##region, _##region + size); \
TEST_SYMBOL(_##region##_size, size)

/*
* Set start, end and size symbols describing region without allocating memory for it.
*/
#define TEST_REGION_UNALLOCATED(region, start, size) EMPTY_WRAP( \
TEST_SYMBOL(_##region, start); \
TEST_SYMBOL(_e##region, _##region + size); \
TEST_SYMBOL(_##region##_size, size) \
)

/* Wrapper for running cmocka test groups using name provided by build system in __TEST_NAME__
This should be used instead of cmocka_run_group_tests(). If there is a need to use custom
group name, then please use cmocka_run_group_tests_name(). */
#define lp_run_group_tests(group_tests, group_setup, group_teardown) \
cmocka_run_group_tests_name((__TEST_NAME__ "(" #group_tests ")"), group_tests, \
group_setup, group_teardown)

#endif /* _TESTS_TEST_H */
34 changes: 34 additions & 0 deletions spd/lp5/memory_parts.json
@@ -0,0 +1,34 @@
{
"parts": [
{
"name": "MT62F512M32D2DR-031 WT:B",
"attribs": {
"densityPerDieGb": 8,
"diesPerPackage": 2,
"bitWidthPerChannel": 16,
"ranksPerChannel": 1,
"speedMbps": 6400
}
},
{
"name": "MT62F1G32D4DR-031 WT:B",
"attribs": {
"densityPerDieGb": 8,
"diesPerPackage": 4,
"bitWidthPerChannel": 16,
"ranksPerChannel": 2,
"speedMbps": 6400
}
},
{
"name": "H9JCNNNCP3MLYR-N6E",
"attribs": {
"densityPerDieGb": 8,
"diesPerPackage": 4,
"bitWidthPerChannel": 16,
"ranksPerChannel": 2,
"speedMbps": 6400
}
}
]
}
4 changes: 4 additions & 0 deletions spd/lp5/platforms_manifest.generated.txt
@@ -0,0 +1,4 @@
# Generated by:
# util/spd_tools/bin/spd_gen spd/lp5/memory_parts.json lp5

ADL,set-0
6 changes: 6 additions & 0 deletions spd/lp5/set-0/parts_spd_manifest.generated.txt
@@ -0,0 +1,6 @@
# Generated by:
# util/spd_tools/bin/spd_gen spd/lp5/memory_parts.json lp5

MT62F512M32D2DR-031 WT:B,spd-1.hex
MT62F1G32D4DR-031 WT:B,spd-2.hex
H9JCNNNCP3MLYR-N6E,spd-2.hex
32 changes: 32 additions & 0 deletions spd/lp5/set-0/spd-1.hex
@@ -0,0 +1,32 @@
23 10 13 0E 15 1A 95 08 00 00 00 00 02 01 00 00
00 00 0A 00 00 00 00 00 AA 00 90 A8 90 90 06 C0
03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32 changes: 32 additions & 0 deletions spd/lp5/set-0/spd-2.hex
@@ -0,0 +1,32 @@
23 10 13 0E 15 1A B5 08 00 00 00 00 0A 01 00 00
00 00 0A 00 00 00 00 00 AA 00 90 A8 90 90 06 C0
03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32 changes: 32 additions & 0 deletions spd/lp5/set-0/spd-empty.hex
@@ -0,0 +1,32 @@
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
53 changes: 40 additions & 13 deletions src/Kconfig
Expand Up @@ -395,6 +395,16 @@ config FW_CONFIG
Enable support for probing devices with fw_config. This is a simple
bitmask broken into fields and options for probing.

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 FW_CONFIG_SOURCE_CBFS
bool "Obtain Firmware Configuration value from CBFS"
depends on FW_CONFIG
Expand All @@ -403,17 +413,18 @@ config FW_CONFIG_SOURCE_CBFS
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.
local image to preempt the mainboard selected source and can be used as
FW_CONFIG_SOURCE_CHROMEEC_CBI fallback option.

config FW_CONFIG_SOURCE_CHROMEEC_CBI
bool "Obtain Firmware Configuration value from Google Chrome EC CBI"
depends on FW_CONFIG && EC_GOOGLE_CHROMEEC
config FW_CONFIG_SOURCE_VPD
bool "Obtain Firmware Configuration value from VPD"
depends on FW_CONFIG && VPD
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.
With this option enabled coreboot will look for the 32bit firmware
configuration value in VPD key name "fw_config". This option will
override other sources and allow the local image to preempt the mainboard
selected source and can be used for other FW_CONFIG_SOURCEs fallback option.

config HAVE_RAMPAYLOAD
bool
Expand Down Expand Up @@ -677,12 +688,12 @@ config TIMER_QUEUE

config COOP_MULTITASKING
def_bool n
depends on TIMER_QUEUE && ARCH_X86
select TIMER_QUEUE
depends on ARCH_X86 && CPU_INFO_V2
help
Cooperative multitasking allows callbacks to be multiplexed on the
main thread of ramstage. With this enabled it allows for multiple
execution paths to take place when they have udelay() calls within
their code.
main thread. With this enabled it allows for multiple execution paths
to take place when they have udelay() calls within their code.

config NUM_THREADS
int
Expand Down Expand Up @@ -717,6 +728,7 @@ config PCI_IO_CFG_EXT

config IOAPIC
bool
default y if SMP
default n

config USE_WATCHDOG_ON_BOOT
Expand Down Expand Up @@ -784,6 +796,21 @@ config GENERATE_SMBIOS_TABLES

If unsure, say Y.

config SMBIOS_TYPE41_PROVIDED_BY_DEVTREE
bool
depends on ARCH_X86
help
If enabled, only generate SMBIOS Type 41 entries for PCI devices in
the devicetree for which Type 41 information is provided, e.g. with
the `smbios_dev_info` devicetree syntax. This is useful to manually
assign specific instance IDs to onboard devices irrespective of the
device traversal order. It is assumed that instance IDs for devices
of the same class are unique.
When disabled, coreboot autogenerates SMBIOS Type 41 entries for all
appropriate PCI devices in the devicetree. Instance IDs are assigned
successive numbers from a monotonically increasing counter, with one
counter for each device class.

config SMBIOS_PROVIDED_BY_MOBO
bool
default n
Expand Down Expand Up @@ -1152,7 +1179,7 @@ config DEBUG_INTEL_ME
endif

config DEBUG_FUNC
bool "Enable function entry and exit reporting macros" if DEFAULT_CONSOLE_LOGLEVEL_8
bool "Enable function entry and exit reporting macros" if DEFAULT_CONSOLE_LOGLEVEL_8 || CONSOLE_OVERRIDE_LOGLEVEL
default n
help
This option enables additional function entry and exit debug messages
Expand Down
25 changes: 17 additions & 8 deletions src/acpi/acpi.c
Expand Up @@ -263,6 +263,14 @@ void acpi_create_madt(acpi_madt_t *madt)
header->checksum = acpi_checksum((void *)madt, header->length);
}

static unsigned long acpi_fill_mcfg(unsigned long current)
{
current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)current,
CONFIG_ECAM_MMCONF_BASE_ADDRESS, 0, 0,
CONFIG_ECAM_MMCONF_BUS_NUMBER - 1);
return current;
}

/* MCFG is defined in the PCI Firmware Specification 3.0. */
void acpi_create_mcfg(acpi_mcfg_t *mcfg)
{
Expand All @@ -284,7 +292,8 @@ void acpi_create_mcfg(acpi_mcfg_t *mcfg)
header->length = sizeof(acpi_mcfg_t);
header->revision = get_acpi_table_revision(MCFG);

current = acpi_fill_mcfg(current);
if (CONFIG(ECAM_MMCONF_SUPPORT))
current = acpi_fill_mcfg(current);

/* (Re)calculate length and checksum. */
header->length = current - (unsigned long)mcfg;
Expand Down Expand Up @@ -1240,7 +1249,7 @@ unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
printk(BIOS_INFO, "%s: Device not enabled\n", __func__);
return current;
}
res = find_resource(dev, PCI_BASE_ADDRESS_0);
res = probe_resource(dev, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "%s: Unable to find resource for %s\n",
__func__, dev_path(dev));
Expand Down Expand Up @@ -1937,9 +1946,9 @@ int get_acpi_table_revision(enum acpi_tables table)
return 2;
case TPM2:
return 4;
case SSDT: /* ACPI 3.0 upto 6.3: 2 */
case SSDT: /* ACPI 3.0 up to 6.3: 2 */
return 2;
case SRAT: /* ACPI 2.0: 1, ACPI 3.0: 2, ACPI 4.0 upto 6.3: 3 */
case SRAT: /* ACPI 2.0: 1, ACPI 3.0: 2, ACPI 4.0 up to 6.3: 3 */
return 1; /* TODO Should probably be upgraded to 2 */
case HMAT: /* ACPI 6.4: 2 */
return 2;
Expand All @@ -1959,13 +1968,13 @@ int get_acpi_table_revision(enum acpi_tables table)
return IVRS_FORMAT_MIXED;
case DBG2:
return 0;
case FACS: /* ACPI 2.0/3.0: 1, ACPI 4.0 upto 6.3: 2 */
case FACS: /* ACPI 2.0/3.0: 1, ACPI 4.0 up to 6.3: 2 */
return 1;
case RSDT: /* ACPI 1.0 upto 6.3: 1 */
case RSDT: /* ACPI 1.0 up to 6.3: 1 */
return 1;
case XSDT: /* ACPI 2.0 upto 6.3: 1 */
case XSDT: /* ACPI 2.0 up to 6.3: 1 */
return 1;
case RSDP: /* ACPI 2.0 upto 6.3: 2 */
case RSDP: /* ACPI 2.0 up to 6.3: 2 */
return 2;
case EINJ:
return 1;
Expand Down
45 changes: 7 additions & 38 deletions src/acpi/acpigen.c
Expand Up @@ -994,7 +994,7 @@ void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
acpigen_pop_len();
}

void acpigen_write_CST_package_entry(acpi_cstate_t *cstate)
void acpigen_write_CST_package_entry(const acpi_cstate_t *cstate)
{
acpigen_write_package(4);
acpigen_write_register_resource(&cstate->resource);
Expand All @@ -1004,7 +1004,7 @@ void acpigen_write_CST_package_entry(acpi_cstate_t *cstate)
acpigen_pop_len();
}

void acpigen_write_CST_package(acpi_cstate_t *cstate, int nentries)
void acpigen_write_CST_package(const acpi_cstate_t *cstate, int nentries)
{
int i;
acpigen_write_name("_CST");
Expand Down Expand Up @@ -1798,13 +1798,11 @@ void acpigen_write_CPPC_package(const struct cppc_config *config)
acpigen_write_byte(config->version);

for (i = 0; i < max; ++i) {
const acpi_addr_t *reg = &(config->regs[i]);
if (reg->space_id == ACPI_ADDRESS_SPACE_MEMORY &&
reg->bit_width == 32 && reg->access_size == ACPI_ACCESS_SIZE_UNDEFINED) {
acpigen_write_dword(reg->addrl);
} else {
acpigen_write_register_resource(reg);
}
const cppc_entry_t *entry = &config->entries[i];
if (entry->type == CPPC_TYPE_DWORD)
acpigen_write_dword(entry->dword);
else
acpigen_write_register_resource(&entry->reg);
}
acpigen_pop_len();
}
Expand Down Expand Up @@ -2022,35 +2020,6 @@ void acpigen_write_rom(void *bios, const size_t length)
acpigen_pop_len();
}

/* Soc-implemented functions -- weak definitions. */
int __weak acpigen_soc_read_rx_gpio(unsigned int gpio_num)
{
printk(BIOS_ERR, "ERROR: %s not implemented\n", __func__);
acpigen_write_debug_string("read_rx_gpio not available");
return -1;
}

int __weak acpigen_soc_get_tx_gpio(unsigned int gpio_num)
{
printk(BIOS_ERR, "ERROR: %s not implemented\n", __func__);
acpigen_write_debug_string("get_tx_gpio not available");
return -1;
}

int __weak acpigen_soc_set_tx_gpio(unsigned int gpio_num)
{
printk(BIOS_ERR, "ERROR: %s not implemented\n", __func__);
acpigen_write_debug_string("set_tx_gpio not available");
return -1;
}

int __weak acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
{
printk(BIOS_ERR, "ERROR: %s not implemented\n", __func__);
acpigen_write_debug_string("clear_tx_gpio not available");
return -1;
}

/*
* Helper functions for enabling/disabling Tx GPIOs based on the GPIO
* polarity. These functions end up calling acpigen_soc_{set,clear}_tx_gpio to
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/device.c
Expand Up @@ -139,7 +139,7 @@ static ssize_t acpi_device_path_fill(const struct device *dev, char *buf,

/*
* Warning: just as with dev_path() this uses a static buffer
* so should not be called mulitple times in one statement
* so should not be called multiple times in one statement
*/
const char *acpi_device_path(const struct device *dev)
{
Expand Down
6 changes: 3 additions & 3 deletions src/acpi/dsdt_top.asl
Expand Up @@ -31,13 +31,13 @@ Method (_PIC, 1)
PICM = Arg0
}

#if CONFIG(MMCONF_SUPPORT)
#if CONFIG(ECAM_MMCONF_SUPPORT)
Scope(\_SB) {
/* Base address of PCIe config space */
Name(PCBA, CONFIG_MMCONF_BASE_ADDRESS)
Name(PCBA, CONFIG_ECAM_MMCONF_BASE_ADDRESS)

/* Length of PCIe config space, 1MB each bus */
Name(PCLN, CONFIG_MMCONF_LENGTH)
Name(PCLN, CONFIG_ECAM_MMCONF_LENGTH)

/* PCIe Configuration Space */
OperationRegion(PCFG, SystemMemory, PCBA, PCLN) /* Each bus consumes 1MB */
Expand Down
2 changes: 1 addition & 1 deletion src/arch/arm/armv7/cpu.S
Expand Up @@ -16,7 +16,7 @@
* the LSB of the set field, but the latter contains the LSB of the way field
* minus the highest valid set field... such that when you subtract it from a
* [way:0:level] field you end up with a [way - 1:highest_set:level] field
* through the magic of double subtraction. It's quite ingenius, really.
* through the magic of double subtraction. It's quite ingenious, really.
* Takes care to only use r0-r3 and ip so it's pefectly ABI-compatible without
* needing to write to memory.
*
Expand Down
15 changes: 0 additions & 15 deletions src/arch/arm/include/armv4/arch/smp/spinlock.h

This file was deleted.

2 changes: 1 addition & 1 deletion src/arch/arm64/include/arch/asm.h
Expand Up @@ -19,7 +19,7 @@
.size name, .-name

/*
* Certain SoCs have an alignment requiremnt for the CPU reset vector.
* Certain SoCs have an alignment requirement for the CPU reset vector.
* Align to a 64 byte typical cacheline for now.
*/
#define CPU_RESET_ENTRY(name) ENTRY_WITH_ALIGN(name, 6)
Expand Down
2 changes: 1 addition & 1 deletion src/arch/riscv/fit_payload.c
Expand Up @@ -7,7 +7,7 @@
#include <fit.h>
#include <endian.h>

/* Implements a Berkley Boot Loader (BBL) compatible payload loading */
/* Implements a Berkeley Boot Loader (BBL) compatible payload loading */

#define MAX_KERNEL_SIZE (64*MiB)

Expand Down
2 changes: 1 addition & 1 deletion src/arch/riscv/opensbi.c
Expand Up @@ -2,7 +2,7 @@

#include <sbi/fw_dynamic.h>
#include <arch/boot.h>
/* DO NOT INLCUDE COREBOOT HEADERS HERE */
/* DO NOT INCLUDE COREBOOT HEADERS HERE */

void run_opensbi(const int hart_id,
const void *fdt,
Expand Down
7 changes: 7 additions & 0 deletions src/arch/x86/Makefile.inc
Expand Up @@ -43,6 +43,13 @@ cbfs-files-$(CONFIG_VGA_BIOS_DGPU) += pci$(stripped_vgabios_dgpu_id).rom
pci$(stripped_vgabios_dgpu_id).rom-file := $(call strip_quotes,$(CONFIG_VGA_BIOS_DGPU_FILE))
pci$(stripped_vgabios_dgpu_id).rom-type := optionrom

# The AMD LPC SPI DMA controller requires source files to be 64 byte aligned.
ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA),y)
pci$(stripped_vgabios_id).rom-align := 64
pci$(stripped_second_vbios_id).rom-align := 64
pci$(stripped_vgabios_dgpu_id).rom-align := 64
endif # CONFIG_SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA

###############################################################################
# common support for early assembly includes
###############################################################################
Expand Down
3 changes: 0 additions & 3 deletions src/arch/x86/assembly_entry.S
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/x86/cpu_info.S.inc>
#include <rules.h>

/*
Expand Down Expand Up @@ -36,8 +35,6 @@ _start:
/* reset stack pointer to CAR/EARLYRAM stack */
mov $_STACK_TOP, %esp

push_cpu_info

/* clear .bss section as it is not shared */
cld
xor %eax, %eax
Expand Down
38 changes: 36 additions & 2 deletions src/arch/x86/c_start.S
Expand Up @@ -80,6 +80,21 @@ _start:

push_cpu_info

#if CONFIG(CPU_INFO_V2)
/* Allocate the per_cpu_segment_data on the stack */
push_per_cpu_segment_data

/*
* Update the BSP's per_cpu_segment_descriptor to point to the
* per_cpu_segment_data that was allocated on the stack.
*/
set_segment_descriptor_base $per_cpu_segment_descriptors, %esp

mov $per_cpu_segment_selector, %eax
movl (%eax), %eax
mov %eax, %gs
#endif

/*
* Now we are finished. Memory is up, data is copied and
* bss is cleared. Now we call the main routine and
Expand Down Expand Up @@ -127,6 +142,7 @@ gdb_stub_breakpoint:
#endif

.globl gdt, gdt_end
.global per_cpu_segment_descriptors, per_cpu_segment_selector

gdtaddr:
.word gdt_end - gdt - 1
Expand All @@ -136,7 +152,7 @@ gdtaddr:
.long gdt /* we know the offset */
#endif

.data
.data

/* This is the gdt for GCC part of coreboot.
* It is different from the gdt in ASM part of coreboot
Expand Down Expand Up @@ -206,8 +222,26 @@ gdt:
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xaf, 0x00
#endif
#if CONFIG(CPU_INFO_V2)
per_cpu_segment_descriptors:
.rept CONFIG_MAX_CPUS
/* flat data segment */
.word 0xffff, 0x0000
#if ENV_X86_64
.byte 0x00, 0x92, 0xcf, 0x00
#else
.byte 0x00, 0x93, 0xcf, 0x00
#endif
.endr
#endif /* CPU_INFO_V2 */
gdt_end:

#if CONFIG(CPU_INFO_V2)
/* Segment selector pointing to the first per_cpu_segment_descriptor. */
per_cpu_segment_selector:
.long per_cpu_segment_descriptors - gdt
#endif /* CPU_INFO_V2 */

.section ".text._start", "ax", @progbits
#if ENV_X86_64
SetCodeSelector:
Expand All @@ -217,7 +251,7 @@ SetCodeSelector:
# use iret to jump to a 64-bit offset in a new code segment
# iret will pop cs:rip, flags, then ss:rsp
mov %ss, %ax # need to push ss..
push %rax # push ss instuction not valid in x64 mode,
push %rax # push ss instruction not valid in x64 mode,
# so use ax
push %rsp
pushfq
Expand Down
32 changes: 29 additions & 3 deletions src/arch/x86/include/arch/cpu.h
Expand Up @@ -231,16 +231,42 @@ struct thread;
struct cpu_info {
struct device *cpu;
size_t index;
#if CONFIG(COOP_MULTITASKING)
struct thread *thread;
#endif
};

/*
* This structure describes the data allocated in the %gs segment for each CPU.
* In order to read from this structure you will need to use assembly to
* reference the segment.
*
* e.g., Reading the cpu_info pointer:
* %%gs:0
*/
struct per_cpu_segment_data {
/*
* Instead of keeping a `struct cpu_info`, we actually keep a pointer
* pointing to the cpu_info struct located in %ds. This prevents
* needing specific access functions to read the fields in the cpu_info.
*/
struct cpu_info *cpu_info;
};

static inline struct cpu_info *cpu_info(void)
{
/* We use a #if because we don't want to mess with the &s below. */
#if CONFIG(CPU_INFO_V2)
struct cpu_info *ci = NULL;

__asm__("mov %%gs:%c[offset], %[ci]"
: [ci] "=r" (ci)
: [offset] "i" (offsetof(struct per_cpu_segment_data, cpu_info))
);

return ci;
#else
char s;
uintptr_t info = ALIGN_UP((uintptr_t)&s, CONFIG_STACK_SIZE) - sizeof(struct cpu_info);
return (struct cpu_info *)info;
#endif /* CPU_INFO_V2 */
}

struct cpuinfo_x86 {
Expand Down
7 changes: 5 additions & 2 deletions src/arch/x86/include/arch/ioapic.h
Expand Up @@ -31,11 +31,14 @@ void io_apic_write(void *ioapic_base, u32 reg, u32 value);
void set_ioapic_id(void *ioapic_base, u8 ioapic_id);
u8 get_ioapic_id(void *ioapic_base);
u8 get_ioapic_version(void *ioapic_base);

unsigned int ioapic_get_max_vectors(void *ioapic_base);
void ioapic_set_max_vectors(void *ioapic_base, int mre_count);
void ioapic_lock_max_vectors(void *ioapic_base);

void setup_ioapic(void *ioapic_base, u8 ioapic_id);
void clear_ioapic(void *ioapic_base);

void ioapic_set_boot_config(void *ioapic_base, bool irq_on_fsb);
void setup_ioapic_helper(void *ioapic_base, u8 ioapic_id, bool enable_virtual_wire);
#endif

#endif
2 changes: 1 addition & 1 deletion src/arch/x86/include/arch/pci_io_cfg.h
Expand Up @@ -69,7 +69,7 @@ void pci_io_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
outl(value, 0xCFC);
}

#if !CONFIG(MMCONF_SUPPORT)
#if !CONFIG(ECAM_MMCONF_SUPPORT)

/* Avoid name collisions as different stages have different signature
* for these functions. The _s_ stands for simple, fundamental IO or
Expand Down
2 changes: 2 additions & 0 deletions src/arch/x86/include/arch/pci_ops.h
Expand Up @@ -4,6 +4,8 @@
#define ARCH_I386_PCI_OPS_H

#include <arch/pci_io_cfg.h>
#if CONFIG(ECAM_MMCONF_SUPPORT)
#include <device/pci_mmio_cfg.h>
#endif

#endif /* ARCH_I386_PCI_OPS_H */
14 changes: 0 additions & 14 deletions src/arch/x86/include/arch/smp/spinlock.h
Expand Up @@ -15,10 +15,6 @@ typedef struct {

#define SPIN_LOCK_UNLOCKED { 1 }

#define STAGE_HAS_SPINLOCKS !ENV_ROMSTAGE_OR_BEFORE

#if STAGE_HAS_SPINLOCKS

#define DECLARE_SPIN_LOCK(x) \
static spinlock_t x = SPIN_LOCK_UNLOCKED;

Expand Down Expand Up @@ -71,14 +67,4 @@ static __always_inline void spin_unlock(spinlock_t *lock)
: "=m" (lock->lock) : : "memory");
}

#else

#define DECLARE_SPIN_LOCK(x)
#define spin_is_locked(lock) 0
#define spin_unlock_wait(lock) do {} while (0)
#define spin_lock(lock) do {} while (0)
#define spin_unlock(lock) do {} while (0)

#endif

#endif /* ARCH_SMP_SPINLOCK_H */