170 changes: 170 additions & 0 deletions Documentation/mainboard/asus/a88xm-e.md
@@ -0,0 +1,170 @@
# ASUS A88XM-E

This page describes how to run coreboot on the [ASUS A88XM-E].

## Technology

Both "Trinity" and "Richland" FM2 desktop processing units are working,
the CPU architecture in these CPUs/APUs are [Piledriver],
and their GPU is [TeraScale 3] (VLIW4-based).

Kaveri is non-working at the moment (FM2+),
the CPU architecture in these CPUs/APUs are [Steamroller],
and their GPU is [Sea Islands] (GCN2-based).

A10 Richland is recommended for the best performance and working IOMMU.

```eval_rst
+------------------+--------------------------------------------------+
| A88XM-E | |
+------------------+--------------------------------------------------+
| DDR voltage IC | Nuvoton 3101S |
+------------------+--------------------------------------------------+
| Network | Realtek RTL8111G |
+------------------+--------------------------------------------------+
| Northbridge | Integrated into CPU with IMC and GPU (APUs only) |
+------------------+--------------------------------------------------+
| Southbridge | Bolton-D4 |
+------------------+--------------------------------------------------+
| Sound IC | Realtek ALC887 |
+------------------+--------------------------------------------------+
| Super I/O | ITE IT8603E |
+------------------+--------------------------------------------------+
| VRM controller | DIGI VRM ASP1206 |
+------------------+--------------------------------------------------+
```

## Flashing coreboot

```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
| Socketed flash | yes |
+---------------------+------------+
| Model | [GD25Q64] |
+---------------------+------------+
| Size | 8 MiB |
+---------------------+------------+
| Package | DIP-8 |
+---------------------+------------+
| Write protection | yes |
+---------------------+------------+
| Dual BIOS feature | no |
+---------------------+------------+
| Internal flashing | yes |
+---------------------+------------+
```

### Internal programming

The main SPI flash can be accessed using [flashrom], if the
AmdSpiRomProtect modules have been deleted in the factory image previously.

### External flashing

Using a PLCC Extractor or any other appropriate tool, carefully remove the
DIP-8 BIOS chip from its' socket while avoiding the bent pins, if possible.
To flash it, use a [flashrom]-supported USB CH341A programmer - preferably with a
green PCB - and double check that it's giving a 3.3V voltage on the socket pins.

## Integrated graphics

### Retrieve the VGA optionrom ("Retrieval via Linux kernel" method)

Make sure a proprietary UEFI is flashed and boot Linux with iomem=relaxed flag.
Some Linux drivers (e.g. radeon for AMD) make option ROMs like the video blob
available to user space via sysfs. To use that to get the blob you need to
enable it first. To that end you need to determine the path within /sys
corresponding to your graphics chip. It looks like this:

# /sys/devices/pci<domain>:<bus>/<domain>:<bus>:<slot>.<function>/rom.

You can get the respective information with lspci, for example:

# lspci -tv
# -[0000:00]-+-00.0 Advanced Micro Devices, Inc. [AMD] Family 16h Processor Root Complex
# +-01.0 Advanced Micro Devices, Inc. [AMD/ATI] Kabini [Radeon HD 8210]
# ...

Here the the needed bits (for the ROM of the Kabini device) are:

# PCI domain: (almost always) 0000
# PCI bus: (also very commonly) 00
# PCI slot: 01 (logical slot; different from any physical slots)
# PCI function: 0 (a PCI device might have multiple functions... shouldn't matter here)

To enable reading of the ROM you need to write 1 to the respective file, e.g.:

# echo 1 > /sys/devices/pci0000:00/0000:00:01.0/rom

The same file should then contain the video blob and it should be possible to simply copy it, e.g.:

# cp /sys/devices/pci0000:00/0000:00:01.0/rom vgabios.bin

romheaders should print reasonable output for this file.

This version is usable for all the GPUs.
1002,9901 Trinity (Radeon HD 7660D)
1002,9904 Trinity (Radeon HD 7560D)
1002,990c Richland (Radeon HD 8670D)
1002,990e Richland (Radeon HD 8570D)
1002,9991 Trinity (Radeon HD 7540D)
1002,9993 Trinity (Radeon HD 7480D)
1002,9996 Richland (Radeon HD 8470D)
1002,9998 Richland (Radeon HD 8370D)
1002,999d Richland (Radeon HD 8550D)
1002,130f Kaveri (Radeon R7)

## Known issues

- AHCI hot-plug
- S3 resume (sometimes)
- Windows 7 can't boot because of the incomplete ACPI implementation
- XHCI

### XHCI ports can break after using any of the blobs, restarting the
board with factory image makes it work again as fallback.
Tested even with/without the Bolton and Hudson blobs.

## Untested

- audio over HDMI

## TODOs

- one ATOMBIOS module for all the integrated GPUs
- manage to work with Kaveri/Godavary (they are using a binaryPI)
- IRQ routing is done incorrect way - common problem of fam15h boards

## Working

- ACPI
- CPU frequency scaling
- flashrom under coreboot
- Gigabit Ethernet
- Hardware monitoring
- Integrated graphics
- KVM virtualization
- Onboard audio
- PCI
- PCIe
- PS/2 keyboard mouse (during payload, bootloader)
- SATA
- Serial port
- SuperIO based fan control
- USB (disabling XHCI controller makes to work as fallback USB2.0 ports)
- IOMMU

## Extra resources

- [Board manual]

[ASUS A88XM-E]: https://www.asus.com/Motherboards/A88XME/
[Board manual]: https://dlcdnets.asus.com/pub/ASUS/mb/SocketFM2/A88XM-E/E9125_A88XM-E.pdf
[flashrom]: https://flashrom.org/Flashrom
[GD25Q64]: http://www.elm-tech.com/ja/products/spi-flash-memory/gd25q64/gd25q64.pdf
[Piledriver]: https://en.wikipedia.org/wiki/Piledriver_%28microarchitecture%29#APU_lines
[Sea Islands]: https://en.wikipedia.org/wiki/Graphics_Core_Next#GCN_2nd_generation
[Steamroller]: https://en.wikipedia.org/wiki/Steamroller_(microarchitecture)
[TeraScale 3]: https://en.wikipedia.org/wiki/TeraScale_%28microarchitecture%29#TeraScale_3
64 changes: 64 additions & 0 deletions Documentation/mainboard/emulation/qemu-i440fx.md
@@ -0,0 +1,64 @@
# qemu i440fx mainboard

## Running coreboot in qemu
Emulators like qemu don't need a firmware to do hardware init.
The hardware starts in the configured state already.

The coreboot port allows to test non mainboard specific code.
As you can easily attach a debugger, it's a good target for
experimental code.

## coreboot x86_64 support
coreboot historically runs in 32-bit protected mode, even though the
processor supports x86_64 instructions (long mode).

The qemu-i440fx mainboard has been ported to x86_64 and will serve as
reference platform to enable additional platforms.

To enable the support set the Kconfig option ``CONFIG_CPU_QEMU_X86_64=y``.

## Installing qemu

On debian you can install qemu by running:
```bash
$ sudo apt-get install qemu
```

On redhat you can install qemu by running:
```bash
$ sudo dnf install qemu
```

## Running coreboot

### To run the i386 version of coreboot (default)
Running on qemu-system-i386 will require a 32 bit operating system.

```bash
qemu-system-i386 -bios build/coreboot.rom -serial stdio -M pc
```

### To run the experimental x86_64 version of coreboot
Running on qemu-system-x86_64 allows to run a 32 bit or 64 bit operating system,
as well as firmware.

```bash
qemu-system-x86_64 -bios build/coreboot.rom -serial stdio -M pc
```

## Finding bugs
To test coreboot's x86 code it's recommended to run on a x86 host and enable KVM.
It will not only run faster, but is closer to real hardware. If you see the
following message:

KVM internal error. Suberror: 1
emulation failure

something went wrong. The same bug will likely cause a FAULT on real hardware,
too.

To enable KVM run:

```bash
qemu-system-x86_64 -bios build/coreboot.rom -serial stdio -M pc -accel kvm -cpu host
```
64 changes: 64 additions & 0 deletions Documentation/mainboard/emulation/qemu-q35.md
@@ -0,0 +1,64 @@
# qemu q35 mainboard

## Running coreboot in qemu
Emulators like qemu don't need a firmware to do hardware init.
The hardware starts in the configured state already.

The coreboot port allows to test non mainboard specific code.
As you can easily attach a debugger, it's a good target for
experimental code.

## coreboot x86_64 support
coreboot historically runs in 32-bit protected mode, even though the
processor supports x86_64 instructions (long mode).

The qemu-q35 mainboard has been ported to x86_64 and will serve as
reference platform to enable additional platforms.

To enable the support set the Kconfig option ``CONFIG_CPU_QEMU_X86_64=y``.

## Installing qemu

On debian you can install qemu by running:
```bash
$ sudo apt-get install qemu
```

On redhat you can install qemu by running:
```bash
$ sudo dnf install qemu
```

## Running coreboot
### To run the i386 version of coreboot (default)
Running on qemu-system-i386 will require a 32 bit operating system.

```bash
qemu-system-i386 -bios build/coreboot.rom -serial stdio -M q35
```

### To run the experimental x86_64 version of coreboot
Running on `qemu-system-x86_64` allows to run a 32 bit or 64 bit operating system
and firmware.

```bash
qemu-system-x86_64 -bios build/coreboot.rom -serial stdio -M q35
```

## Finding bugs
To test coreboot's x86 code it's recommended to run on a x86 host and enable KVM.
It will not only run faster, but is closer to real hardware. If you see the
following message:

KVM internal error. Suberror: 1
emulation failure

something went wrong. The same bug will likely cause a FAULT on real hardware,
too.

To enable KVM run:

```bash
qemu-system-x86_64 -bios build/coreboot.rom -serial stdio -M q35 -accel kvm -cpu host
```

4 changes: 2 additions & 2 deletions Documentation/mainboard/facebook/monolith.md
Expand Up @@ -2,7 +2,7 @@

This page describes how to run coreboot on the Facebook Monolith.

Please note: the coreboot implementation for this boards is in its
Please note: the coreboot implementation for this board is in its
Beta state and isn't fully tested yet.

## Required blobs
Expand Down Expand Up @@ -104,7 +104,7 @@ solution. Wires need to be connected to be able to flash using an external progr
- SMBus
- Initialization with FSP
- SeaBIOS payload (commit a5cab58e9a3fb6e168aba919c5669bea406573b4)
- TianoCore payload (commit a5cab58e9a3fb6e168aba919c5669bea406573b4)
- TianoCore payload (commit 860a8d95c2ee89c9916d6e11230f246afa1cd629)
- LinuxBoot (kernel kernel-4_19_97) (uroot commit 9c9db9dbd6b532f5f91a511a0de885c6562aadd7)
- eMMC

Expand Down
99 changes: 99 additions & 0 deletions Documentation/mainboard/hp/2560p.md
@@ -0,0 +1,99 @@
# HP EliteBook 2560p

This page is about the notebook [HP EliteBook 2560p].

## Release status

HP EliteBook 2560p was released in 2011 and is now end of life.
It can be bought from a secondhand market like Taobao or eBay.

## Required proprietary blobs

The following blobs are required to operate the hardware:
1. EC firmware
2. Intel ME firmware

EC firmware can be retrieved from the HP firmware update image, or the firmware
backup of the laptop. EC Firmware is part of the coreboot build process.
The guide on extracting EC firmware and using it to build coreboot is in
document [HP Laptops with KBC1126 Embedded Controller](hp_kbc1126_laptops).

Intel ME firmware is in the flash chip. It is not needed when building coreboot.

## Programming

The flash chip is located between the memory slots and the PCH,
covered by the base enclosure, which needs to be removed according to
the [Maintenance and Service Guide] to access the flash chip. An SPI
flash programmer using 3.3V voltage such as a ch341a programmer, and
an SOIC-8 clip can be used to read and flash the chip in-circuit.

Pin 1 of the flash chip is at the side near the PCH.

![Flash Chip in 2560p](2560p_flash.webp)

For more details have a look at the general [flashing tutorial].

## Debugging

The board can be debugged with EHCI debug. The EHCI debug port is the back
bottom USB port.

Schematic of this laptop can be found on [Lab One].

## Test status

### Known issues

- GRUB payload freezes if at_keyboard module is in the GRUB image
([bug #141])

### Untested

- Optical Drive
- VGA
- Fingerprint Reader
- Modem

### Working

- Integrated graphics init with libgfxinit
- SATA
- Audio: speaker and microphone
- Ethernet
- WLAN
- WWAN
- Bluetooth
- ExpressCard
- SD Card Reader
- SmartCard Reader
- eSATA
- USB
- DisplayPort
- Keyboard, touchpad and trackpoint
- EC ACPI support and thermal control
- Dock: all USB ports, DisplayPort, eSATA
- TPM
- Internal flashing when IFD is unlocked
- Using `me_cleaner`


## Technology

```eval_rst
+------------------+--------------------------------------------------+
| CPU | Intel Sandy/Ivy Bridge (FCPGA988) |
+------------------+--------------------------------------------------+
| PCH | Intel Cougar Point QM67 |
+------------------+--------------------------------------------------+
| EC | SMSC KBC1126 |
+------------------+--------------------------------------------------+
| Coprocessor | Intel Management Engine |
+------------------+--------------------------------------------------+
```

[HP EliteBook 2560p]: https://support.hp.com/us-en/product/hp-elitebook-2560p-notebook-pc/5071201
[Maintenance and Service Guide]: http://h10032.www1.hp.com/ctg/Manual/c03011618
[flashing tutorial]: ../../flash_tutorial/ext_power.md
[Lab One]: https://www.laboneinside.com/hp-elitebook-2560p-schematic-diagram/
[bug #141]: https://ticket.coreboot.org/issues/141
Binary file added Documentation/mainboard/hp/2560p_flash.webp
Binary file not shown.
7 changes: 7 additions & 0 deletions Documentation/mainboard/index.md
Expand Up @@ -37,6 +37,8 @@ The boards in this section are not real mainboards, but emulators.
- [Spike RISC-V emulator](emulation/spike-riscv.md)
- [Qemu RISC-V emulator](emulation/qemu-riscv.md)
- [Qemu AArch64 emulator](emulation/qemu-aarch64.md)
- [Qemu x86 Q35](emulation/qemu-q35.md)
- [Qemu x86 PC](emulation/qemu-i440fx.md)

## Facebook

Expand All @@ -59,6 +61,7 @@ The boards in this section are not real mainboards, but emulators.
### EliteBook series

- [HP Laptops with KBC1126 EC](hp/hp_kbc1126_laptops.md)
- [EliteBook 2560p](hp/2560p.md)
- [EliteBook 8760w](hp/8760w.md)

## Intel
Expand Down Expand Up @@ -135,6 +138,10 @@ The boards in this section are not real mainboards, but emulators.

- [Hermes](prodrive/hermes.md)

## Purism

- [Librem Mini](purism/librem_mini.md)

## Protectli

- [FW2B / FW4B](protectli/fw2b_fw4b.md)
Expand Down
2 changes: 1 addition & 1 deletion Documentation/mainboard/lenovo/montevina_series.md
Expand Up @@ -89,7 +89,7 @@ $ make
```

If your flash is not 8 MB, you need to change values of `flcomp_density1` and
`flreg1_limit` in the ifd-x200.set file according to following table:
`flreg1_limit` in the `ifd-x200.set` file according to following table:

```eval_rst
+-----------------+-------+-------+--------+
Expand Down
50 changes: 31 additions & 19 deletions Documentation/mainboard/ocp/deltalake.md
@@ -1,7 +1,8 @@
# OCP Delta Lake

This page describes coreboot support status for the [OCP] (Open Compute Project)
Delta Lake server platform.
Delta Lake server platform. This page is updated following each 4-weeks
build/test/release cycle.

## Introduction

Expand All @@ -22,7 +23,7 @@ This board currently requires:
- FSP blob: The blob (Intel Cooper Lake Scalable Processor Firmware Support Package)
is not yet available to the public. It will be made public some time after the MP
(Mass Production) of CooperLake Scalable Processor when the FSP is mature.
- Microcode: Not yet available to the public.
- Microcode: Available through github.com:otcshare/Intel-Generic-Microcode.git.
- ME binary: Not yet available to the public.

## Payload
Expand Down Expand Up @@ -55,26 +56,43 @@ as initramfs.
- Type 2 -- Baseboard Information
- Type 3 -- System Enclosure or Chassis
- Type 4 -- Processor Information
- Type 7 -- Cache Information
- Type 8 -- Port Connector Information
- Type 9 -- PCI Slot Information
- Type 11 -- OEM String
- Type 13 -- BIOS Language Information
- Type 16 -- Physical Memory Array
- Type 19 -- Memory Array Mapped Address
- Type 32 -- System Boot Information
- Type 38 -- IPMI Device Information
- Type 127 -- End-of-Table

- BMC integration:
- BMC readiness check
- IPMI commands
- watchdog timer
- POST complete pin acknowledgement
- Check BMC version: ipmidump -device
- SEL record generation
- Early serial output
- port 80h direct to GPIO
- ACPI tables: APIC/DSDT/FACP/FACS/HPET/MCFG/SPMI/SRAT/SLIT/SSDT
- ACPI tables: APIC/DMAR/DSDT/FACP/FACS/HPET/MCFG/SPMI/SRAT/SLIT/SSDT
- Skipping memory training upon subsequent reboots by using MRC cache
- BMC crash dump
- Error injection through ITP
- Versions
- Check FSP version: cbmem | grep LB_TAG_PLATFORM_BLOB_VERSION
- Check Microcode version: cat /proc/cpuinfo | grep microcode
- Devices:
- Boot drive
- NIC card
- All 5 data drives
- Power button
- localboot
- netboot from IPv6

## Stress/performance tests passed
- OS warm reboot overnight (6 hours)
- Mprime test (6 hours)
- MLC (Intel Memory Latency Check)
- Linkpack

## Firmware configurations
[ChromeOS VPD] is used to store most of the firmware configurations.
Expand All @@ -84,29 +102,23 @@ values.
VPD variables supported are:
- firmware_version: This variable holds overall firmware version. coreboot
uses that value to populate smbios type 1 version field.
- DeltaLake specific VPDs: check mb/ocp/deltalake/vpd.h.

## Known issues
- Even though CPX-SP FSP is based on FSP 2.2 framework, it does not
support FSP_USES_CB_STACK. An IPS ticket is filed with Intel.
- VT-d is not supported. An IPS ticket is filed with Intel.
- PCIe bifuration is not supported. An IPS ticket is filed with Intel.
- ME based power capping. This is a bug in ME. An IPS ticket is filed
with Intel.
- RO_VPD region as well as other RO regions are not write protected.
- HECI is not set up correctly, so BMC is not able to get PCH and DIMM
temperature sensor readings.
temperature sensor readings. An IPS ticket is filed.

## Feature gaps
- Delta Lake DVT is not supported, as we only have Delta Lake EVT servers
at the moment.
- SMBIOS:
- Type 7 -- Cache Information
- Type 16 -- Physical Memory Array
- Type 17 -- Memory Device
- Type 38 -- IPMI Device Information
- Type 19 -- Memory Array Mapped Address
- Type 41 -- Onboard Devices Extended Information
- ACPI:
- DMAR
- Hardware error injection, detection, reporting
- PFR/CBnT
- RO_VPD region as well as other RO regions are not write protected.

## Technology

Expand All @@ -116,7 +128,7 @@ VPD variables supported are:
+------------------------+---------------------------------------------+
| BMC | Aspeed AST 2500 |
+------------------------+---------------------------------------------+
| PCH | Intel Lewisburg C621 |
| PCH | Intel Lewisburg C620 Series |
+------------------------+---------------------------------------------+
```

Expand Down
Binary file added Documentation/mainboard/purism/librem_mini.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 122 additions & 0 deletions Documentation/mainboard/purism/librem_mini.md
@@ -0,0 +1,122 @@
# Purism Librem Mini

This page describes how to run coreboot on the [Purism Librem Mini].

```eval_rst
+------------------+--------------------------------------------------+
| CPU | Intel Core i7-8565U |
+------------------+--------------------------------------------------+
| PCH | Whiskey Lake / Cannon Point LP |
+------------------+--------------------------------------------------+
| Super I/O, EC | ITE IT8528E |
+------------------+--------------------------------------------------+
| Coprocessor | Intel Management Engine (CSME 12.x) |
+------------------+--------------------------------------------------+
```

![](librem_mini.jpg)
![](librem_mini_flash.jpg)

## Required proprietary blobs

To build a minimal working coreboot image some blobs are required (assuming
only the BIOS region is being modified).

```eval_rst
+-----------------+---------------------------------+---------------------+
| Binary file | Apply | Required / Optional |
+=================+=================================+=====================+
| FSP-M, FSP-S | Intel Firmware Support Package | Required |
+-----------------+---------------------------------+---------------------+
| microcode | CPU microcode | Required |
+-----------------+---------------------------------+---------------------+
| vgabios | VGA Option ROM | Optional |
+-----------------+---------------------------------+---------------------+
```

FSP-M and FSP-S are obtained after splitting the Coffee Lake FSP binary (done
automatically by the coreboot build system and included into the image) from
the `3rdparty/fsp` submodule.

Microcode updates are automatically included into the coreboot image by the build
system from the `3rdparty/intel-microcode` submodule. Official Purism release
images may include newer microcode, which is instead pulled from Purism's
[purism-blobs] repository.

VGA Option ROM is not required to boot, but if one needs graphics in pre-OS
stage, it should be included (if not using FSP/GOP display init). It can
be extracted via cbfstool from the existing board firmware or pulled from
the [purism-blobs] repository.

## Intel Management Engine

The Librem Mini uses version 12.x of the Intel Management Engine (ME) /
Converged Security Engine (CSE). The ME/CSE is disabled using the High
Assurance Platform (HAP) bit, which puts the ME into a disabled state
after platform bring-up (BUP) and disables all PCI/HECI interfaces.
This can be verified via the coreboot cbmem utility:
`sudo ./cbmem -1 | grep 'ME:'`
provided coreboot has been modified to output the ME status even when
the PCI device is not visible/active (as it is in Purism's release builds).

## Flashing coreboot

### Internal programming

The main SPI flash can be accessed using [flashrom]. The first version
supporting the chipset is flashrom v1.2. Firmware an be easily flashed
with internal programmer (either BIOS region or full image).

### External programming

The system has an internal flash chip which is a 8 MiB soldered SOIC-8 chip,
and has a diode attached to the VCC line for in-system programming.
This chip is located on the bottom side of the board under the CPU heatsink,
in line with the front USB 2.0 ports.

One has to remove all screws (in order):

* 2 top cover screws
* 4 screws securing the mainboard to the chassis
* 4 screws securing the heatsink/fan assembly to the mainboard (under the SODIMMs)

The m.2 SSD will need to be removed if the Wi-Fi antenna are connected to
an internal Wi-Fi/BT module. Use a SOIC-8 chip clip to program the chip.
Specifically, it's a Winbond W25Q128JV (3.3V) - [datasheet][W25Q128JV].

The EC firmware is stored on a separate SOIC-8 chip (a Winbond W25Q80DV),
but is not protected by a diode and therefore cannot be read/written to without
desoldering it from the mainboard.

## Known issues

* SeaBIOS can be finicky with detecting USB devices
* Booting can sometimes hang when a bootsplash image is used with SeaBIOS
and VGA option ROM display init, related to display mode changing
* Issues with some SATA devices have been mitigated by limiting the SATA speed to 3Gbps
until the correct HSIO PHY settings can be determined.

## Working

* External displays via HDMI/DislpayPort with VGA option ROM or FSP/GOP init
(no libgfxinit support yet)
* SeaBIOS (1.13.x), Tianocore (CorebootPayloadpkg), Heads (Purism downstream) payloads
* Ethernet, m.2 2230 Wi-Fi
* System firmware updates via flashrom
* PCIe NVMe
* m.2 and SATA III
* Audio via front 3.5mm jack, HDMI, and DisplayPort
* SMBus (reading SPD from DIMMs)
* Initialization with CFL FSP 2.0
* S3 Suspend/Resume
* Booting PureOS 9.x, Debian 10.x, Qubes 4.0.3, Linux Mint 19.3, Windows 10 2004

## Not working / untested

* ITE IT8528E Super IO functions


[Purism Librem Mini]: https://puri.sm/products/librem-mini/
[purism-blobs]: https://source.puri.sm/coreboot/purism-blobs
[W25Q128JV]: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf
[flashrom]: https://flashrom.org/Flashrom
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions Documentation/releases/coreboot-4.13-relnotes.md
Expand Up @@ -39,4 +39,14 @@ attributes as per their datasheet and convert those attributes into SPD files fo
the platforms. More details about the tools are added in
[README.md](https://review.coreboot.org/plugins/gitiles/coreboot/+/refs/heads/master/util/spd_tools/intel/lp4x/README.md).

### New version of SMM loader

A new version of the SMM loader which accomodates platforms with over 32 CPU
CPU threads. The existing version of SMM loader uses a 64K code/data
segment and only a limited number of CPU threads can fit into one segment
(because of save state, STM, other features, etc). This loader extends beyond
the 64K segment to accomodate additional CPUs and in theory allows as many
CPU threads as possible limited only by SMRAM space and not by 64K. By default
this loader version is disabled. Please see cpu/x86/Kconfig for more info.

### Add significant changes here
150 changes: 150 additions & 0 deletions Documentation/soc/intel/cse_fw_update/Layout_after.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions Documentation/soc/intel/cse_fw_update/Layout_before.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions Documentation/soc/intel/cse_fw_update/cse_fw_update.md
@@ -0,0 +1,127 @@
CSE FW update mechanism for devices in field

## Introduction

CSE Firmware and PMC Firmware are critical components of Intel SoCs.
CSE and PMC cooperate by providing platform services during boot and other
power transition flows.

## Problem Statement

Currently, on Chromium OS Systems, CSE region is not updatable. So, new CSE FW
versions that are released by Intel to address important functional and security
bugs post-product launch will not be available to the end-user. Hence, the proposed
solution allows in-field CSE FW update to propagate those bug fixes
to end user platforms.

## Design Proposal

### CSE FW design Proposal:

Key Elements:

- CSE FW layout is composed of two bootable partitions (RO Recovery Partition
and RW Normal Partition).

- Boot partition selection: An API-based mechanism is used to decide from which partition
CSE will boot.

- The HECI APIs below will be supported in this CSE FW:

- HMRFPO_ENABLE: This command requests the CSE enter a mode in which writes to
the CSE region from the CSE are disabled. It also grants temporary write access
to the RW partition from the host (RO is still protected by GPR0).

- GET_PARTITION_INFO: The command retrieves information for each boot partition from CSE
like version, start/end offsets of a partition within CSE region, and boot
partition status. Also, it provides below information:
- The current boot partition which was used during this boot,
- The boot partition that will be used on the next CSE reset
- The number of boot partitions available in the CSE region

- SET_BOOT_PARTITION_INFO: This command allows the firmware to request the
CSE to boot from either its RO or RW partition at its next reset.

- DATA_CLEAR: This command requests the CSE to reset its data partition back
to manufacturing defaults

FW Layout, RW/RO Partitions:

The CSE RO partition is the first in the CSE boot order, hence it will be used
out of G3. RO partition contains minimum CSE code capable to boot platform and
execute FW update of RW partition. In addition to CSE code, the RO partition also
contains PMC FW patch and other CSE-loadable platform FW components.

RW partition contains fully operational CSE FW, PMC FW, other CSE loadable
platform FW components.

Boot partition selection:

CSE FW shall support 2 APIs to get boot partition info, and set boot partition
info to notify CSE to select the partition on the next boot.

### HOST FW Design proposal:

Key Elements:

- Build time artifacts:

CSE RW Version update binary - The FW shall pack CSE RW update blob and
corresponding version binary which contains version of the CSE RW blob.

- FW Update:

coreboot will implement the logic to compare the CSE's FW version with CBFS
CSE RW binary's version in the firmware slot (FW_MAIN_A/FW_MAIN_B) and update
the CSE RW region if there is a version mismatch. If there is no version
mismatch, firmware skips CSE FW update.

- Handling of CSE FW Downgrade:

coreboot will send DATA_CLEAR HECI command when there is a CSE FW downgrade.
This must be done to avoid data mismatch due to CSE FW downgrade. Further,
CSE will restore the data back to manufacturing defaults after data reset.


## Implementation Details


To enable CSE FW update flow the following changes are required in coreboot:

* Descriptor change may be required to accommodate CSE binary. The CSE binary is tied with
a platform. So CSE size may vary from one platform to another.
* FMAP changes may be required to accommodate CSE binary and CSE RW blob in the RW CBFS region.
Please check platform specific CSE kit for CSE binary information.
* CSE Lite SKU binary and CSE RW blob
* Makefile change to pack CSE RW binaries in the CBFS
* Implementation of update flow:
- Get CSE boot partition info using GET_BOOT_PARTITION_INFO HECI command.
- Get the cbfs_me_rw.version from the currently selected RW slot.
- If the version from the above 2 locations don't match, then start CSE FW update.
- If CSE is not booting from RO, then
- Set the CSE's next boot partition to RO using SET_BOOT_PARTITION_INFO
HECI command.
- Send GLOBAL_RESET HECI command to reset the system.
- If RW update is a CSE FW downgrade, then coreboot has to send
DATA_CLEAR command to clear run time data of CSE.
- Enable HMRFPO Mode (Host ME Region Flash Protection Override) by
sending HMRFPO_ENABLE HECI command to CSE.
- Erase and Copy the CBFS CSE RW to CSE RW partition
- Set CSE's next boot partition to RW.
- Trigger Global Reset which resets both CSE and Host.
Then system should boot with the updated CSE.

* The resulting flash layout is shown below:

![Flash Layout](./Layout_before.svg) ![FlashLayout](./Layout_after.svg)


- Typical boot flow

- Vboot selects the RW FW (FW_MAIN_A or FW_MAIN_B) to boot.
- coreboot skips CSE FW update flow if boot mode is recovery.
- If CSE RW blob is not locatable in the CBFS, then RW Firmware skips update flow
and sends SET_BOOT_PARTITION_INFO command to switch CSE to boot from RW
and issues Global Reset if CSE is already not booting from RW partition.
- The RW firmware will compare the CSE RW version with CSE RW blob in the slot.
- If there is a mismatch, then firmware will carry out update flow as explained before.
2 changes: 2 additions & 0 deletions Documentation/soc/intel/index.md
Expand Up @@ -8,5 +8,7 @@ This section contains documentation about coreboot on specific Intel SOCs.
- [FSP](fsp/index.md)
- [Ice Lake/9th Gen Core-i series](icelake/index.md)
- [MP Initialization](mp_init/mp_init.md)
- [Microcode Updates](microcode.md)
- [Firmware Interface Table](fit.md)
- [Apollolake](apollolake/index.md)
- [CSE FW Update](cse_fw_update/cse_fw_update_model.md)
136 changes: 136 additions & 0 deletions Documentation/soc/intel/microcode.md
@@ -0,0 +1,136 @@
# Microcode updates

When booting a modern x86 platform, one task of the firmware is to update
[microcode] to correct hardware bugs and mitigate security issues found
after silicon has been shipped. The [Pentium FDIV bug] could have been
fixed with a microcode update, had the Pentium used updateable microcode.
Starting with the Pentium Pro, CPU microcode can be updated by software.

As per BIOS Writer's Guides, Intel defines a processor as the silicon and
the accompanying microcode update, and considers any processor that does
not have its microcode updated to be running out of specification. This
suggests that microcode is a crucial ingredient for correct operation.

On multi-processor or Hyper-Threading-enabled systems, each thread has
its own microcode. Therefore, microcode must be updated on every thread.

## When to update microcode

When a CPU core comes out of reset, it uses microcode from an internal
ROM. This “default” microcode often contains bugs, so it needs to be
updated as soon as possible. For example, Core 2 CPUs can boot without
microcode updates, but have stability problems. On newer platforms,
it is nearly impossible to boot without having updated the microcode.
On some platforms, an updated microcode is required in order to enable
Cache-As-RAM or to be able to successfully initialize the DRAM.

Plus, microcode needs to be loaded multiple times. Intel Document 504790
explains that this is because of so-called *enhanced microcode updates*,
which are large updates with errata workarounds for both core and uncore.
In order to correctly apply enhanced microcode updates, the [MP-Init]
algorithm must be decomposed into multiple initialization phases.

### Firmware Interface Table

Beginning with 4th generation Intel Core processors, it is possible for
microcode to be updated before the CPU is taken out of reset. This is
accomplished by means of [FIT], a data structure which contains pointers
to various firmware ingredients in the BIOS flash.

In rare cases, FIT microcode updates may not be successful. Therefore,
it is important to check that the microcode is up-to-date and, if not,
update it. This needs to be done as early as possible, like on older
processor generations without FIT support.

Whether all threads on a processor get their microcode updated through
FIT is not clear. According to Intel Documents 493770 and 535094, FIT
microcode updates are applied to all cores within the package. However,
Intel Document 550049 states that FIT microcode updates are applied to
all threads within the package.

## SMM bring-up

Prior to SMM relocation, microcode must have been updated at least once.

## Multi-Processor bring-up

The BWG briefly describes microcode updates as part of the *MP-Init*.

### MP-Init

As part of the [MP-Init] sequence, two microcode updates are required.

* The first update must happen as soon as one AP comes out of reset.
* The second update must happen after the MP-Init sequence has written MTRRs,
PRMRR, DCU mode and prefetcher configuration, SMM has been relocated, but
before clearing the MCE banks.

## Recommendations

The Linux kernel developer's recommendations are:
* Serialize microcode updates if possible.
* Idle as many APs as possible while updating.
* Idle the sibling thread on a Hyper-Threading enabled CPU while updating.

## Platform BWGs

The requirements specified in BWGs differ between platforms:

### Sandy Bridge

* Before setting up Cache-As-RAM, load microcode update into the SBSP.
* Losing (non-SBSP) NBSPs must load their microcode update before being placed
back in the wait-for-SIPI state.
* Sibling threads on HT must use a semaphore.
* Microcode update loading has been done prior to SMM relocation.
* In MP-Init the microcode update on an AP must be done before initializing the
cache, MTRRs, SMRRs and PRMRRs.
* In MP-Init a second update must happen on all threads after initializing the
cache, MTRRs, SMRRs and PRMRRs.

Refer to Intel Document 504790 for details.

### Haswell/Broadwell Client

* A microcode update must exist in FIT.
* During the race to the BSP semaphore, each NBSP must load its microcode update.
* All HT enabled threads can load microcode in parallel. However, the
IA32_BIOS_UPDT_TRIG MSR is core-scoped, just like on other platforms.
* Microcode update loading has been done prior to SMM relocation.
* In MP-Init the microcode update on an AP must be done before initializing the
cache, MTRRs, SMRRs and EMRR.
* In MP-Init a second update must happen on all threads after initializing the
cache, MTRRs, SMRRs and EMRR and after SMM initialization.

Refer to Intel Document 493770 and 535094 for details.

### Broadwell Server

* A microcode update must exist in FIT.
* Before setting up Cache-As-RAM, load microcode update into each BSP.
* In MP-Init the microcode update on an AP must be done before initializing the
cache, MTRRs, SMRRs and EMRR.
* In MP-Init a second update must happen on all threads after initializing the
cache, MTRRs, SMRRs and EMRR and after SMM initialization.

Refer to Intel Document 546625 for details.

### Skylake/Kaby Lake/Coffee Lake/Whiskey Lake/Comet Lake

* A microcode update must exist in FIT.
* Before setting up Cache-As-RAM, load microcode update into the BSP.
* Microcode update loading has been done prior to SMM relocation.
* In MP-Init the first update must happen as soon as one AP comes out of reset.
* In MP-Init the second update must happen after the MP-Init sequence has
written MTRRs, PRMRR, DCU mode and prefetcher configuration, but before
clearing the MCE banks.
* Microcode updates must happen on all threads.
* Sibling threads on HT should use a semaphore.

Refer to Intel Document 550049 for details.

[microcode]: https://en.wikipedia.org/wiki/Microcode
[Pentium FDIV bug]: https://en.wikipedia.org/wiki/Pentium_FDIV_bug
[FIT]: fit.md
[SDM]: https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf
[MP-Init]: mp_init/mp_init.md
20 changes: 18 additions & 2 deletions MAINTAINERS
Expand Up @@ -378,6 +378,13 @@ F: src/mainboard/siemens/mc_apl1/



SYSTEM76 MAINBOARDS
M: Jeremy Soller <jeremy@system76.com>
S: Maintained
F: src/mainboard/system76/



SUPERMICRO X10SLM+-F MAINBOARD
M: Tristan Corrick <tristan@corrick.kiwi>
S: Maintained
Expand All @@ -397,7 +404,6 @@ M: Julius Werner <jwerner@chromium.org>
S: Supported
F: src/arch/arm/
F: src/arch/arm64/
F: src/soc/mediatek/
F: src/soc/nvidia/
F: src/soc/rockchip/
F: util/nvidia/
Expand Down Expand Up @@ -438,6 +444,11 @@ M: Alexander Couzens <lynxis@fe80.eu>
S: Maintained
F: src/ec/lenovo/

SYSTEM76 EC
M: Jeremy Soller <jeremy@system76.com>
S: Maintained
F: src/ec/system76/

################################################################################
# Northbridges
################################################################################
Expand Down Expand Up @@ -535,10 +546,15 @@ F: src/soc/intel/xeon_sp
F: src/vendorcode/intel/fsp/fsp2_0/skylake_sp
F: src/vendorcode/intel/fsp/fsp2_0/copperlake_sp

MEDIATEK SOCS
M: Hung-Te Lin <hungte@chromium.org>
S: Supported
F: src/soc/mediatek

ORPHANED ARM SOCS
S: Orphaned
F: src/cpu/armltd/
F: src/cpu/ti/
F: src/soc/ti/
F: src/soc/qualcomm/
F: src/soc/samsung/
F: util/exynos/
Expand Down
8 changes: 6 additions & 2 deletions Makefile.inc
Expand Up @@ -411,17 +411,21 @@ CPPFLAGS_common += -include $(src)/commonlib/bsd/include/commonlib/bsd/compiler.
CPPFLAGS_common += -I3rdparty
CPPFLAGS_common += -D__BUILD_DIR__=\"$(obj)\"

ifeq ($(BUILD_TIMELESS),1)
CPPFLAGS_common += -D__TIMELESS__
endif

ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL)$(CONFIG_PCI_OPTION_ROM_RUN_REALMODE),y)
CPPFLAGS_ramstage += -Isrc/device/oprom/include
endif

CFLAGS_common += -pipe -g -nostdinc -std=gnu11
CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs -Wimplicit-fallthrough
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits -Wvla
CFLAGS_common += -Wshadow -Wdate-time -Wtype-limits -Wvla
CFLAGS_common += -Wlogical-op -Wduplicated-cond -Wdangling-else
CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
CFLAGS_common += -fstrict-aliasing -ffunction-sections -fdata-sections -fno-pie
ifeq ($(CONFIG_COMPILER_GCC),y)
# Don't add these GCC specific flags when running scan-build
ifeq ($(CCC_ANALYZER_OUTPUT_FORMAT),)
Expand Down
@@ -0,0 +1,44 @@
# Not meant for actual use. Exercises, among other things:
# + Code coverage
# + UBSAN
# + Debug options
# + SMMSTORE
# + Silicon Image SIL3114 driver
# + Genesys Logic GL9763E driver
# + EM100 support
CONFIG_COVERAGE=y
CONFIG_UBSAN=y
CONFIG_VENDOR_ASROCK=y
CONFIG_ONBOARD_VGA_IS_PRIMARY=y
CONFIG_CBFS_SIZE=0x200000
CONFIG_BOARD_ASROCK_B85M_PRO4=y
CONFIG_PCIEXP_L1_SUB_STATE=y
CONFIG_PCIEXP_CLK_PM=y
CONFIG_CONSOLE_POST=y
# CONFIG_INTEL_CHIPSET_LOCKDOWN is not set
# CONFIG_FINALIZE_USB_ROUTE_XHCI is not set
CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y
CONFIG_PCIEXP_HOTPLUG=y
CONFIG_SMMSTORE=y
CONFIG_SMMSTORE_SIZE=0x30000
CONFIG_SPI_FLASH_NO_FAST_READ=y
CONFIG_USBDEBUG=y
CONFIG_USBDEBUG_DONGLE_FTDI_FT232H=y
CONFIG_DRIVERS_SIL_3114=y
CONFIG_DRIVERS_GENESYSLOGIC_GL9763E=y
# CONFIG_SQUELCH_EARLY_SMP is not set
CONFIG_CONSOLE_SPI_FLASH=y
CONFIG_POST_DEVICE_PCI_PCIE=y
CONFIG_FATAL_ASSERTS=y
CONFIG_DEBUG_CBFS=y
CONFIG_DEBUG_SMBUS=y
CONFIG_DEBUG_SMI=y
CONFIG_DEBUG_PERIODIC_SMI=y
CONFIG_DEBUG_MALLOC=y
CONFIG_DEBUG_CONSOLE_INIT=y
CONFIG_DEBUG_SPI_FLASH=y
CONFIG_DEBUG_COVERAGE=y
CONFIG_DEBUG_BOOT_STATE=y
CONFIG_DEBUG_ADA_CODE=y
CONFIG_HAVE_EM100_SUPPORT=y
CONFIG_EM100=y
1 change: 1 addition & 0 deletions configs/config.emulation_qemu_x86_i440fx_x86_64
@@ -0,0 +1 @@
CONFIG_CPU_QEMU_X86_64=y
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.12.0.3"
CONFIG_LOCALVERSION="v4.12.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_NO_GFX_INIT=y
Expand All @@ -19,4 +19,4 @@ CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0b756257276729c1a12bc1d95e7a1f044894bda2"
CONFIG_SORTBOOTORDER_REVISION=y
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.19"
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.20"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.12.0.3"
CONFIG_LOCALVERSION="v4.12.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU2=y
Expand All @@ -21,4 +21,4 @@ CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0b756257276729c1a12bc1d95e7a1f044894bda2"
CONFIG_SORTBOOTORDER_REVISION=y
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.19"
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.20"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.12.0.3"
CONFIG_LOCALVERSION="v4.12.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU3=y
Expand All @@ -21,4 +21,4 @@ CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0b756257276729c1a12bc1d95e7a1f044894bda2"
CONFIG_SORTBOOTORDER_REVISION=y
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.19"
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.20"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu4
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.12.0.3"
CONFIG_LOCALVERSION="v4.12.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU4=y
Expand All @@ -21,4 +21,4 @@ CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0b756257276729c1a12bc1d95e7a1f044894bda2"
CONFIG_SORTBOOTORDER_REVISION=y
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.19"
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.20"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.12.0.3"
CONFIG_LOCALVERSION="v4.12.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
Expand All @@ -21,4 +21,4 @@ CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0b756257276729c1a12bc1d95e7a1f044894bda2"
CONFIG_SORTBOOTORDER_REVISION=y
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.19"
CONFIG_SORTBOOTORDER_REVISION_ID="v4.6.20"
8 changes: 8 additions & 0 deletions configs/config.purism_librem15_v4.txt_build_test
@@ -0,0 +1,8 @@
# Not meant for actual use. Exercises Intel TXT code. Since BIOS
# and SINIT ACM blobs are missing, use something else as placeholder.
CONFIG_VENDOR_PURISM=y
CONFIG_BOARD_PURISM_LIBREM15_V4=y
CONFIG_INTEL_TXT=y
CONFIG_INTEL_TXT_BIOSACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
CONFIG_INTEL_TXT_SINITACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
CONFIG_INTEL_TXT_LOGGING=y
4 changes: 2 additions & 2 deletions payloads/Kconfig
Expand Up @@ -30,7 +30,7 @@ config PAYLOAD_ELF

config PAYLOAD_FIT
bool "A FIT payload"
depends on ARCH_ARM64 || ARCH_RISCV
depends on ARCH_ARM64 || ARCH_RISCV || ARCH_ARM
select PAYLOAD_FIT_SUPPORT
help
Select this option if you have a payload image (a FIT file) which
Expand Down Expand Up @@ -97,7 +97,7 @@ config PAYLOAD_FIT_SUPPORT
bool "FIT support"
default n
default y if PAYLOAD_LINUX && (ARCH_ARM || ARCH_ARM64 || ARCH_RISCV)
depends on ARCH_ARM64 || ARCH_RISCV
depends on ARCH_ARM64 || ARCH_RISCV || ARCH_ARM
select FLATTENED_DEVICE_TREE
help
Select this option if your payload is of type FIT.
Expand Down
3 changes: 1 addition & 2 deletions payloads/coreinfo/Makefile
Expand Up @@ -128,10 +128,9 @@ include $(srck)/Makefile
else

clean:
rm -rf build/*.elf build/*.o .xcompile
rm -rf build lpbuild .xcompile

distclean: clean
rm -rf build lpbuild
rm -f .config* lp.config*

.PHONY: clean distclean
Expand Down
2 changes: 1 addition & 1 deletion payloads/coreinfo/bootlog_module.c
Expand Up @@ -110,7 +110,7 @@ static int bootlog_module_init(void)
return -1;
}

struct cbmem_console *console = lib_sysinfo.cbmem_cons;
struct cbmem_console *console = phys_to_virt(lib_sysinfo.cbmem_cons);
if (console == NULL) {
return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion payloads/coreinfo/timestamps_module.c
Expand Up @@ -147,7 +147,7 @@ static int timestamps_module_init(void)
if (ret)
return -1;

struct timestamp_table *timestamps = lib_sysinfo.tstamp_table;
struct timestamp_table *timestamps = phys_to_virt(lib_sysinfo.tstamp_table);

if (timestamps == NULL)
return -1;
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/SeaBIOS/Kconfig
Expand Up @@ -5,7 +5,7 @@ choice
default SEABIOS_STABLE

config SEABIOS_STABLE
bool "1.13.0"
bool "1.14.0"
help
Stable SeaBIOS version
config SEABIOS_MASTER
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/SeaBIOS/Makefile
@@ -1,5 +1,5 @@
TAG-$(CONFIG_SEABIOS_MASTER)=origin/master
TAG-$(CONFIG_SEABIOS_STABLE)=f21b5a4aeb020f2a5e2c6503f906a9349dd2f069
TAG-$(CONFIG_SEABIOS_STABLE)=155821a1990b6de78dde5f98fa5ab90e802021e0
TAG-$(CONFIG_SEABIOS_REVISION)=$(CONFIG_SEABIOS_REVISION_ID)

project_git_repo=https://github.com/pcengines/seabios.git
Expand Down
6 changes: 3 additions & 3 deletions payloads/external/tint/Makefile
Expand Up @@ -18,9 +18,9 @@ patch: download
cd tint; \
if [ -e debian ]; then \
rm -rf debian typedefs.h Makefile; \
touch Makefile; \
patch -l -p1 < ../libpayload_tint.patch; \
fi
touch Makefile; \
patch -l -p1 < ../libpayload_tint.patch; \
fi

download:
test -d tint || { wget $(project_url); \
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/arch/arm/cpu.S
Expand Up @@ -81,7 +81,7 @@
lsl ip, ip, r2 @ shift by that into way position
mov r0, #1
lsl r2, r0, r2 @ r2 now contains the way decr
mov r0, r3 @ get sets/level (no way yet)
mov r0, r3 @ get sets/level (no way yet)
orr r3, r3, ip @ merge way into way/set/level
bfc r0, #0, #4 @ clear low 4 bits (level) to get numset - 1
sub r2, r2, r0 @ subtract from way decr
Expand Down
17 changes: 2 additions & 15 deletions payloads/libpayload/arch/arm64/mmu.c
Expand Up @@ -625,14 +625,10 @@ static void mmu_extract_ranges(struct memrange *cb_ranges,
static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges)
{
struct mmu_memrange *fb_range;
static struct cb_framebuffer modified_fb;
struct cb_framebuffer *framebuffer = lib_sysinfo.framebuffer;
struct cb_framebuffer *framebuffer = &lib_sysinfo.framebuffer;
uint32_t fb_size;

/* Check whether framebuffer is needed */
if (framebuffer == NULL)
return;

fb_size = framebuffer->bytes_per_line * framebuffer->y_resolution;
if (!fb_size)
return;
Expand All @@ -652,16 +648,7 @@ static void mmu_add_fb_range(struct mmu_ranges *mmu_ranges)
if (fb_range == NULL)
mmu_error();

/*
* Set framebuffer address. However, one needs to use a freshly
* allocated framebuffer structure because the one in the coreboot
* table is part of a checksum calculation. Therefore, one cannot
* modify a field without recomputing the necessary checksum
* calcuation.
*/
modified_fb = *framebuffer;
modified_fb.physical_address = fb_range->base;
lib_sysinfo.framebuffer = &modified_fb;
framebuffer->physical_address = fb_range->base;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/arch/x86/coreboot.c
Expand Up @@ -49,7 +49,7 @@ static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info)

static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info)
{
info->mrc_cache = get_cbmem_ptr(ptr);
info->mrc_cache = get_cbmem_addr(ptr);
}

int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info)
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/configs/defconfig
Expand Up @@ -5,4 +5,4 @@ CONFIG_LP_USB_UHCI=y
CONFIG_LP_USB_OHCI=y
CONFIG_LP_USB_EHCI=y
CONFIG_LP_USB_XHCI=y
CONFIG_LP_HEAP_SIZE=262144
CONFIG_LP_HEAP_SIZE=1048576
16 changes: 8 additions & 8 deletions payloads/libpayload/curses/menu/eti.h
Expand Up @@ -36,19 +36,19 @@
#define NCURSES_ETI_H_incl 1

#define E_OK (0)
#define E_SYSTEM_ERROR (-1)
#define E_BAD_ARGUMENT (-2)
#define E_POSTED (-3)
#define E_CONNECTED (-4)
#define E_BAD_STATE (-5)
#define E_NO_ROOM (-6)
#define E_SYSTEM_ERROR (-1)
#define E_BAD_ARGUMENT (-2)
#define E_POSTED (-3)
#define E_CONNECTED (-4)
#define E_BAD_STATE (-5)
#define E_NO_ROOM (-6)
#define E_NOT_POSTED (-7)
#define E_UNKNOWN_COMMAND (-8)
#define E_NO_MATCH (-9)
#define E_NOT_SELECTABLE (-10)
#define E_NOT_CONNECTED (-11)
#define E_NOT_CONNECTED (-11)
#define E_REQUEST_DENIED (-12)
#define E_INVALID_FIELD (-13)
#define E_INVALID_FIELD (-13)
#define E_CURRENT (-14)

#endif
29 changes: 17 additions & 12 deletions payloads/libpayload/drivers/cbmem_console.c
Expand Up @@ -38,7 +38,7 @@ struct cbmem_console {
#define CURSOR_MASK ((1 << 28) - 1)
#define OVERFLOW (1 << 31)

static struct cbmem_console *cbmem_console_p;
static uintptr_t cbmem_console_p;

static struct console_output_driver cbmem_console_driver =
{
Expand All @@ -47,27 +47,32 @@ static struct console_output_driver cbmem_console_driver =

static void do_write(const void *buffer, size_t count)
{
memcpy(cbmem_console_p->body + (cbmem_console_p->cursor & CURSOR_MASK),
buffer, count);
cbmem_console_p->cursor += count;
struct cbmem_console *const cbmem_cons = phys_to_virt(cbmem_console_p);

memcpy(cbmem_cons->body + (cbmem_cons->cursor & CURSOR_MASK), buffer, count);
cbmem_cons->cursor += count;
}

void cbmem_console_init(void)
{
const struct cbmem_console *const cbmem_cons = phys_to_virt(lib_sysinfo.cbmem_cons);

cbmem_console_p = lib_sysinfo.cbmem_cons;
if (cbmem_console_p && cbmem_console_p->size)

if (cbmem_console_p && cbmem_cons->size)
console_add_output_driver(&cbmem_console_driver);
}

void cbmem_console_write(const void *buffer, size_t count)
{
while ((cbmem_console_p->cursor & CURSOR_MASK) + count >=
cbmem_console_p->size) {
size_t still_fits = cbmem_console_p->size -
(cbmem_console_p->cursor & CURSOR_MASK);
struct cbmem_console *const cbmem_cons = phys_to_virt(cbmem_console_p);

while ((cbmem_cons->cursor & CURSOR_MASK) + count >=
cbmem_cons->size) {
size_t still_fits = cbmem_cons->size - (cbmem_cons->cursor & CURSOR_MASK);
do_write(buffer, still_fits);
cbmem_console_p->cursor &= ~CURSOR_MASK;
cbmem_console_p->cursor |= OVERFLOW;
cbmem_cons->cursor &= ~CURSOR_MASK;
cbmem_cons->cursor |= OVERFLOW;
buffer += still_fits;
count -= still_fits;
}
Expand All @@ -77,7 +82,7 @@ void cbmem_console_write(const void *buffer, size_t count)

char *cbmem_console_snapshot(void)
{
const struct cbmem_console *console_p = cbmem_console_p;
const struct cbmem_console *const console_p = phys_to_virt(cbmem_console_p);
char *console_c;
uint32_t size, cursor, overflow;

Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/options.c
Expand Up @@ -53,7 +53,7 @@ struct nvram_accessor *use_mem = &(struct nvram_accessor) {

struct cb_cmos_option_table *get_system_option_table(void)
{
return lib_sysinfo.option_table;
return phys_to_virt(lib_sysinfo.cmos_option_table);
}

int options_checksum_valid(const struct nvram_accessor *nvram)
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/8250.c
Expand Up @@ -132,9 +132,9 @@ void serial_init(void)

void serial_console_init(void)
{
if (!lib_sysinfo.serial)
if (!lib_sysinfo.cb_serial)
return;
cb_serial = *lib_sysinfo.serial;
cb_serial = *(struct cb_serial *)phys_to_virt(lib_sysinfo.cb_serial);

serial_init();

Expand Down
4 changes: 1 addition & 3 deletions payloads/libpayload/drivers/serial/ipq40xx.c
Expand Up @@ -553,9 +553,7 @@ static struct console_output_driver consout = {};
/* For simplicity's sake, let's rely on coreboot initializing the UART. */
void serial_console_init(void)
{
struct cb_serial *sc_ptr = lib_sysinfo.serial;

if (!sc_ptr)
if (!lib_sysinfo.cb_serial)
return;

consin.havekey = serial_havechar;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/ipq806x.c
Expand Up @@ -343,9 +343,9 @@ int serial_getchar(void)
/* For simplicity's sake, let's rely on coreboot initializing the UART. */
void serial_console_init(void)
{
struct cb_serial *sc_ptr = lib_sysinfo.serial;
struct cb_serial *sc_ptr = phys_to_virt(lib_sysinfo.cb_serial);

if (!sc_ptr)
if (!lib_sysinfo.cb_serial)
return;

base_uart_addr = (void *) sc_ptr->baseaddr;
Expand Down
5 changes: 3 additions & 2 deletions payloads/libpayload/drivers/serial/qcom_qupv3_serial.c
Expand Up @@ -275,7 +275,8 @@ static struct console_output_driver consout = {

static struct qup_regs *uart_base_address(void)
{
return (void *)(uintptr_t)lib_sysinfo.serial->baseaddr;
const struct cb_serial *const serial = phys_to_virt(lib_sysinfo.cb_serial);
return phys_to_virt(serial->baseaddr);
}

static void uart_qupv3_tx_flush(void)
Expand Down Expand Up @@ -332,7 +333,7 @@ int serial_getchar(void)

void serial_console_init(void)
{
if (!lib_sysinfo.serial)
if (!lib_sysinfo.cb_serial)
return;

console_add_output_driver(&consout);
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/qcs405.c
Expand Up @@ -541,9 +541,9 @@ int serial_getchar(void)
/* For simplicity's sake, let's rely on coreboot initializing the UART. */
void serial_console_init(void)
{
struct cb_serial *sc_ptr = lib_sysinfo.serial;
struct cb_serial *sc_ptr = phys_to_virt(lib_sysinfo.cb_serial);

if (!sc_ptr)
if (!lib_sysinfo.cb_serial)
return;

uart_board_param.uart_dm_base = (void *)(uintptr_t)sc_ptr->baseaddr;
Expand Down
6 changes: 4 additions & 2 deletions payloads/libpayload/drivers/serial/s5p.c
Expand Up @@ -90,10 +90,12 @@ static struct console_input_driver s5p_serial_input =

void serial_init(void)
{
if (!lib_sysinfo.serial || !lib_sysinfo.serial->baseaddr)
const struct cb_serial *const serial = phys_to_virt(lib_sysinfo.cb_serial);

if (!lib_sysinfo.cb_serial || !serial->baseaddr)
return;

uart_regs = (struct s5p_uart *)lib_sysinfo.serial->baseaddr;
uart_regs = (struct s5p_uart *)serial->baseaddr;
}

void serial_console_init(void)
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/usb/usb.c
Expand Up @@ -275,7 +275,7 @@ usb_decode_mps0(usb_speed speed, u8 bMaxPacketSize0)
bMaxPacketSize0 = 9;
}
return 1 << bMaxPacketSize0;
default: /* GCC is stupid and cannot deal with enums correctly */
default: /* GCC is stupid and cannot deal with enums correctly */
return 8;
}
}
Expand Down
9 changes: 3 additions & 6 deletions payloads/libpayload/drivers/video/corebootfb.c
Expand Up @@ -60,7 +60,7 @@ static const u32 vga_colors[] = {
(0xFF << 16) | (0xFF << 8) | 0xFF,
};

struct cb_framebuffer fbinfo;
static struct cb_framebuffer fbinfo;
static unsigned short *chars;

/* Shorthand for up-to-date virtual framebuffer address */
Expand Down Expand Up @@ -223,13 +223,10 @@ static void corebootfb_set_cursor(unsigned int x, unsigned int y)

static int corebootfb_init(void)
{
if (lib_sysinfo.framebuffer == NULL)
if (!lib_sysinfo.framebuffer.physical_address)
return -1;

fbinfo = *lib_sysinfo.framebuffer;

if (fbinfo.physical_address == 0)
return -1;
fbinfo = lib_sysinfo.framebuffer;

font_init(fbinfo.x_resolution);

Expand Down
169 changes: 144 additions & 25 deletions payloads/libpayload/drivers/video/graphics.c
Expand Up @@ -45,8 +45,10 @@ static struct rect screen;
* Framebuffer is assumed to assign a higher coordinate (larger x, y) to
* a higher address
*/
static struct cb_framebuffer *fbinfo;
static uint8_t *fbaddr;
static const struct cb_framebuffer *fbinfo;

/* Shorthand for up-to-date virtual framebuffer address */
#define FB ((unsigned char *)phys_to_virt(fbinfo->physical_address))

#define LOG(x...) printf("CBGFX: " x)
#define PIVOT_H_MASK (PIVOT_H_LEFT|PIVOT_H_CENTER|PIVOT_H_RIGHT)
Expand All @@ -61,17 +63,53 @@ static const struct vector vzero = {
.y = 0,
};

struct color_transformation {
uint8_t base;
int16_t scale;
};

struct color_mapping {
struct color_transformation red;
struct color_transformation green;
struct color_transformation blue;
int enabled;
};

static struct color_mapping color_map;

static inline void set_color_trans(struct color_transformation *trans,
uint8_t bg_color, uint8_t fg_color)
{
trans->base = bg_color;
trans->scale = fg_color - bg_color;
}

int set_color_map(const struct rgb_color *background,
const struct rgb_color *foreground)
{
if (background == NULL || foreground == NULL)
return CBGFX_ERROR_INVALID_PARAMETER;

set_color_trans(&color_map.red, background->red, foreground->red);
set_color_trans(&color_map.green, background->green,
foreground->green);
set_color_trans(&color_map.blue, background->blue, foreground->blue);
color_map.enabled = 1;

return CBGFX_SUCCESS;
}

void clear_color_map(void)
{
color_map.enabled = 0;
}

struct blend_value {
uint8_t alpha;
struct rgb_color rgb;
};

static struct blend_value blend = {
.alpha = 0,
.rgb.red = 0,
.rgb.green = 0,
.rgb.blue = 0,
};
static struct blend_value blend;

int set_blend(const struct rgb_color *rgb, uint8_t alpha)
{
Expand Down Expand Up @@ -99,6 +137,11 @@ static void add_vectors(struct vector *out,
out->y = v1->y + v2->y;
}

static int fraction_equal(const struct fraction *f1, const struct fraction *f2)
{
return (int64_t)f1->n * f2->d == (int64_t)f2->n * f1->d;
}

static int is_valid_fraction(const struct fraction *f)
{
return f->d != 0;
Expand All @@ -109,19 +152,33 @@ static int is_valid_scale(const struct scale *s)
return is_valid_fraction(&s->x) && is_valid_fraction(&s->y);
}

static void add_fractions(struct fraction *out,
const struct fraction *f1, const struct fraction *f2)
static void reduce_fraction(struct fraction *out, int64_t n, int64_t d)
{
int64_t n, d;
int shift;
n = (int64_t)f1->n * f2->d + (int64_t)f2->n * f1->d;
d = (int64_t)f1->d * f2->d;
/* Simplest way to reduce the fraction until fitting in int32_t */
shift = log2(MAX(ABS(n), ABS(d)) >> 31) + 1;
int shift = log2(MAX(ABS(n), ABS(d)) >> 31) + 1;
out->n = n >> shift;
out->d = d >> shift;
}

/* out = f1 + f2 */
static void add_fractions(struct fraction *out,
const struct fraction *f1, const struct fraction *f2)
{
reduce_fraction(out,
(int64_t)f1->n * f2->d + (int64_t)f2->n * f1->d,
(int64_t)f1->d * f2->d);
}

/* out = f1 - f2 */
static void subtract_fractions(struct fraction *out,
const struct fraction *f1,
const struct fraction *f2)
{
reduce_fraction(out,
(int64_t)f1->n * f2->d - (int64_t)f2->n * f1->d,
(int64_t)f1->d * f2->d);
}

static void add_scales(struct scale *out,
const struct scale *s1, const struct scale *s2)
{
Expand Down Expand Up @@ -166,6 +223,15 @@ static int within_box(const struct vector *v, const struct rect *bound)
return -1;
}

/* Helper function that applies color_map to the color. */
static inline uint8_t apply_map(uint8_t color,
const struct color_transformation *trans)
{
if (!color_map.enabled)
return color;
return trans->base + trans->scale * color / UINT8_MAX;
}

/*
* Helper function that applies color and opacity from blend struct
* into the color.
Expand All @@ -184,13 +250,16 @@ static inline uint32_t calculate_color(const struct rgb_color *rgb,
{
uint32_t color = 0;

color |= (apply_blend(rgb->red, blend.rgb.red)
color |= (apply_blend(apply_map(rgb->red, &color_map.red),
blend.rgb.red)
>> (8 - fbinfo->red_mask_size))
<< fbinfo->red_mask_pos;
color |= (apply_blend(rgb->green, blend.rgb.green)
color |= (apply_blend(apply_map(rgb->green, &color_map.green),
blend.rgb.green)
>> (8 - fbinfo->green_mask_size))
<< fbinfo->green_mask_pos;
color |= (apply_blend(rgb->blue, blend.rgb.blue)
color |= (apply_blend(apply_map(rgb->blue, &color_map.blue),
blend.rgb.blue)
>> (8 - fbinfo->blue_mask_size))
<< fbinfo->blue_mask_pos;
if (invert)
Expand Down Expand Up @@ -229,7 +298,7 @@ static inline void set_pixel(struct vector *coord, uint32_t color)
break;
}

uint8_t * const pixel = fbaddr + rcoord.y * bpl + rcoord.x * bpp / 8;
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 All @@ -243,12 +312,9 @@ static int cbgfx_init(void)
if (initialized)
return 0;

fbinfo = lib_sysinfo.framebuffer;
if (!fbinfo)
return CBGFX_ERROR_FRAMEBUFFER_INFO;
fbinfo = &lib_sysinfo.framebuffer;

fbaddr = phys_to_virt((uint8_t *)(uintptr_t)(fbinfo->physical_address));
if (!fbaddr)
if (!fbinfo->physical_address)
return CBGFX_ERROR_FRAMEBUFFER_ADDR;

switch (fbinfo->orientation) {
Expand Down Expand Up @@ -477,6 +543,59 @@ int draw_rounded_box(const struct scale *pos_rel, const struct scale *dim_rel,
return CBGFX_SUCCESS;
}

int draw_line(const struct scale *pos1, const struct scale *pos2,
const struct fraction *thickness, const struct rgb_color *rgb)
{
struct fraction len;
struct vector top_left;
struct vector size;
struct vector p, t;

if (cbgfx_init())
return CBGFX_ERROR_INIT;

const uint32_t color = calculate_color(rgb, 0);

if (!is_valid_fraction(thickness))
return CBGFX_ERROR_INVALID_PARAMETER;

transform_vector(&top_left, &canvas.size, pos1, &canvas.offset);
if (fraction_equal(&pos1->y, &pos2->y)) {
/* Horizontal line */
subtract_fractions(&len, &pos2->x, &pos1->x);
struct scale dim = {
.x = { .n = len.n, .d = len.d },
.y = { .n = thickness->n, .d = thickness->d },
};
transform_vector(&size, &canvas.size, &dim, &vzero);
size.y = MAX(size.y, 1);
} else if (fraction_equal(&pos1->x, &pos2->x)) {
/* Vertical line */
subtract_fractions(&len, &pos2->y, &pos1->y);
struct scale dim = {
.x = { .n = thickness->n, .d = thickness->d },
.y = { .n = len.n, .d = len.d },
};
transform_vector(&size, &canvas.size, &dim, &vzero);
size.x = MAX(size.x, 1);
} else {
LOG("Only support horizontal and vertical lines\n");
return CBGFX_ERROR_INVALID_PARAMETER;
}

add_vectors(&t, &top_left, &size);
if (within_box(&t, &canvas) < 0) {
LOG("Line exceeds canvas boundary\n");
return CBGFX_ERROR_BOUNDARY;
}

for (p.y = top_left.y; p.y < t.y; p.y++)
for (p.x = top_left.x; p.x < t.x; p.x++)
set_pixel(&p, color);

return CBGFX_SUCCESS;
}

int clear_canvas(const struct rgb_color *rgb)
{
const struct rect box = {
Expand Down Expand Up @@ -507,7 +626,7 @@ int clear_screen(const struct rgb_color *rgb)
* 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(fbaddr, color & 0xff, fbinfo->y_resolution * bpl);
memset(FB, color & 0xff, fbinfo->y_resolution * bpl);
} else {
for (p.y = 0; p.y < screen.size.height; p.y++)
for (p.x = 0; p.x < screen.size.width; p.x++)
Expand Down
36 changes: 34 additions & 2 deletions payloads/libpayload/include/cbgfx.h
Expand Up @@ -132,6 +132,22 @@ int draw_rounded_box(const struct scale *pos_rel, const struct scale *dim_rel,
const struct fraction *thickness,
const struct fraction *radius);

/**
* Draw a horizontal or vertical line segment on screen. If horizontal, pos1
* must be the left endpoint. If vertical, pos1 must be the top endpoint. When
* the specified thickness is zero (or truncated to zero), a line with 1-pixel
* width will be drawn.
*
* @param[in] pos1 Start position of the line relative to the canvas.
* @param[in] pos2 End position of the line relative to the canvas.
* @param[in] thickness Thickness of the line relative to the canvas.
* @param[in] rgb Color of the line.
*
* @return CBGFX_* error codes
*/
int draw_line(const struct scale *pos1, const struct scale *pos2,
const struct fraction *thickness, const struct rgb_color *rgb);

/**
* Clear the canvas
*/
Expand Down Expand Up @@ -211,6 +227,24 @@ int draw_bitmap_direct(const void *bitmap, size_t size,
*/
int get_bitmap_dimension(const void *bitmap, size_t sz, struct scale *dim_rel);

/**
* Setup color mappings of background and foreground colors. Black and white
* pixels will be mapped to the background and foreground colors, respectively.
* Call clear_color_map() to disabled color mapping.
*
* @param[in] background Background color.
* @param[in] foreground Foreground color.
*
* @return CBGFX_* error codes
*/
int set_color_map(const struct rgb_color *background,
const struct rgb_color *foreground);

/**
* Clear color mappings.
*/
void clear_color_map(void);

/**
* Setup alpha and rgb values for alpha blending. When alpha is != 0,
* this enables a translucent layer of color (defined by rgb) to be
Expand All @@ -228,8 +262,6 @@ int set_blend(const struct rgb_color *rgb, uint8_t alpha);

/**
* Clear alpha and rgb values, thus disabling any alpha blending.
*
* @return CBGFX_* error codes
*/
void clear_blend(void);

Expand Down
44 changes: 27 additions & 17 deletions payloads/libpayload/include/compiler.h
@@ -1,29 +1,39 @@
/*
*
* Copyright 2017 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifndef __COMPILER_H__
#define __COMPILER_H__
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */

#ifndef _COMMONLIB_BSD_COMPILER_H_
#define _COMMONLIB_BSD_COMPILER_H_

#ifndef __packed
#if defined(__WIN32) || defined(__WIN64)
#define __packed __attribute__((gcc_struct, packed))
#else
#define __packed __attribute__((packed))
#endif
#endif

#ifndef __aligned
#define __aligned(x) __attribute__((aligned(x)))
#endif

#ifndef __always_unused
#define __always_unused __attribute__((unused))
#endif

#ifndef __must_check
#define __must_check __attribute__((warn_unused_result))
#endif

#ifndef __weak
#define __weak __attribute__((weak))
#endif

#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif

#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline))
#endif

/* This evaluates to the type of the first expression, unless that is constant
in which case it evalutates to the type of the second. This is useful when
Expand All @@ -32,7 +42,7 @@
literals. By using this macro, the promotion can happen at the time the
literal is assigned to the temporary variable. If the literal doesn't fit in
the chosen type, -Werror=overflow will catch it, so this should be safe. */
#define __TYPEOF_UNLESS_CONST(expr, fallback_expr) typeof( \
#define __TYPEOF_UNLESS_CONST(expr, fallback_expr) __typeof__( \
__builtin_choose_expr(__builtin_constant_p(expr), fallback_expr, expr))

/* This creates a unique local variable name for use in macros. */
Expand Down
3 changes: 2 additions & 1 deletion payloads/libpayload/include/coreboot_tables.h
Expand Up @@ -31,6 +31,7 @@

#include <arch/types.h>
#include <ipchksum.h>
#include <stdint.h>

enum {
CB_TAG_UNUSED = 0x0000,
Expand Down Expand Up @@ -395,5 +396,5 @@ static inline const char *cb_mb_part_string(const struct cb_mainboard *cbm)
+ (sizeof((_rec)->map[0]) * (_idx)))

/* Helper functions */
void *get_cbmem_ptr(unsigned char *ptr);
uintptr_t get_cbmem_addr(const void *cbmem_tab_entry);
#endif
63 changes: 32 additions & 31 deletions payloads/libpayload/include/sysinfo.h
Expand Up @@ -29,6 +29,8 @@
#ifndef _SYSINFO_H
#define _SYSINFO_H

#include <stdint.h>

/* Maximum number of memory range definitions. */
#define SYSINFO_MAX_MEM_RANGES 32
/* Allow a maximum of 8 GPIOs */
Expand All @@ -39,17 +41,16 @@

#include <coreboot_tables.h>

struct cb_serial;

/*
* All pointers in here shall be virtual.
* This is a collection of information and pointers gathered
* mostly from the coreboot table.
*
* If a relocation happens after the last call to lib_get_sysinfo(),
* it is up to the user to call lib_get_sysinfo() again.
* We do not store virtual pointers in here to avoid problems
* with self-relocating payloads.
*/
struct sysinfo_t {
unsigned int cpu_khz;
struct cb_serial *serial;
uintptr_t cb_serial;
unsigned short ser_ioport;
unsigned long ser_base; // for mmapped serial

Expand All @@ -61,56 +62,56 @@ struct sysinfo_t {
unsigned int type;
} memrange[SYSINFO_MAX_MEM_RANGES];

struct cb_cmos_option_table *option_table;
uintptr_t cmos_option_table;
u32 cmos_range_start;
u32 cmos_range_end;
u32 cmos_checksum_location;
u32 vbnv_start;
u32 vbnv_size;

char *version;
char *extra_version;
char *build;
char *compile_time;
char *compile_by;
char *compile_host;
char *compile_domain;
char *compiler;
char *linker;
char *assembler;
uintptr_t version;
uintptr_t extra_version;
uintptr_t build;
uintptr_t compile_time;
uintptr_t compile_by;
uintptr_t compile_host;
uintptr_t compile_domain;
uintptr_t compiler;
uintptr_t linker;
uintptr_t assembler;

char *cb_version;
uintptr_t cb_version;

struct cb_framebuffer *framebuffer;
struct cb_framebuffer framebuffer;

int num_gpios;
struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
int num_macs;
struct mac_address macs[SYSINFO_MAX_MACS];
char *serialno;
uintptr_t serialno;

unsigned long *mbtable; /** Pointer to the multiboot table */

struct cb_header *header;
struct cb_mainboard *mainboard;
uintptr_t cb_header;
uintptr_t cb_mainboard;

void *vboot_workbuf;
uintptr_t vboot_workbuf;

#if CONFIG(LP_ARCH_X86)
int x86_rom_var_mtrr_index;
#endif

void *tstamp_table;
void *cbmem_cons;
void *mrc_cache;
void *acpi_gnvs;
uintptr_t tstamp_table;
uintptr_t cbmem_cons;
uintptr_t mrc_cache;
uintptr_t acpi_gnvs;

#define UNDEFINED_STRAPPING_ID (~0)
u32 board_id;
u32 ram_code;
u32 sku_id;

void *wifi_calibration;
uintptr_t wifi_calibration;
uint64_t ramoops_buffer;
uint32_t ramoops_buffer_size;
struct {
Expand All @@ -124,11 +125,11 @@ struct sysinfo_t {
uint64_t boot_media_size;
uint64_t mtc_start;
uint32_t mtc_size;
void *chromeos_vpd;
int mmc_early_wake_status;
uintptr_t chromeos_vpd;
int mmc_early_wake_status;

/* Pointer to FMAP cache in CBMEM */
void *fmap_cache;
uintptr_t fmap_cache;
};

extern struct sysinfo_t lib_sysinfo;
Expand Down
40 changes: 21 additions & 19 deletions payloads/libpayload/libc/coreboot.c
Expand Up @@ -41,10 +41,10 @@
/* === Parsing code === */
/* This is the generic parsing code. */

void *get_cbmem_ptr(unsigned char *ptr)
uintptr_t get_cbmem_addr(const void *const cbmem_tab_entry)
{
struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
return phys_to_virt(cbmem->cbmem_tab);
const struct cb_cbmem_tab *const cbmem = cbmem_tab_entry;
return cbmem->cbmem_tab;
}

static void cb_parse_memory(void *ptr, struct sysinfo_t *info)
Expand Down Expand Up @@ -80,12 +80,12 @@ static void cb_parse_memory(void *ptr, struct sysinfo_t *info)

static void cb_parse_serial(void *ptr, struct sysinfo_t *info)
{
info->serial = ((struct cb_serial *)ptr);
info->cb_serial = virt_to_phys(ptr);
}

static void cb_parse_vboot_workbuf(unsigned char *ptr, struct sysinfo_t *info)
{
info->vboot_workbuf = get_cbmem_ptr(ptr);
info->vboot_workbuf = get_cbmem_addr(ptr);
}

static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
Expand Down Expand Up @@ -130,17 +130,17 @@ static void cb_parse_mac_addresses(unsigned char *ptr,

static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
{
info->tstamp_table = get_cbmem_ptr(ptr);
info->tstamp_table = get_cbmem_addr(ptr);
}

static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
{
info->cbmem_cons = get_cbmem_ptr(ptr);
info->cbmem_cons = get_cbmem_addr(ptr);
}

static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info)
{
info->acpi_gnvs = get_cbmem_ptr(ptr);
info->acpi_gnvs = get_cbmem_addr(ptr);
}

static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info)
Expand All @@ -164,8 +164,8 @@ static void cb_parse_sku_id(unsigned char *ptr, struct sysinfo_t *info)
#if CONFIG(LP_NVRAM)
static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info)
{
/* ptr points to a coreboot table entry and is already virtual */
info->option_table = ptr;
/* ptr is already virtual, but we want to keep physical addresses */
info->cmos_option_table = virt_to_phys(ptr);
}

static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
Expand All @@ -180,19 +180,21 @@ static void cb_parse_checksum(void *ptr, struct sysinfo_t *info)
#if CONFIG(LP_COREBOOT_VIDEO_CONSOLE)
static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info)
{
/* ptr points to a coreboot table entry and is already virtual */
info->framebuffer = ptr;
info->framebuffer = *(struct cb_framebuffer *)ptr;
}
#endif

static void cb_parse_string(unsigned char *ptr, char **info)
static void cb_parse_string(const void *const ptr, uintptr_t *const info)
{
*info = (char *)((struct cb_string *)ptr)->string;
/* ptr is already virtual (str->string just an offset to that),
but we want to keep physical addresses */
const struct cb_string *const str = ptr;
*info = virt_to_phys(str->string);
}

static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info)
{
info->wifi_calibration = get_cbmem_ptr(ptr);
info->wifi_calibration = get_cbmem_addr(ptr);
}

static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info)
Expand Down Expand Up @@ -233,12 +235,12 @@ static void cb_parse_boot_media_params(unsigned char *ptr,

static void cb_parse_vpd(void *ptr, struct sysinfo_t *info)
{
info->chromeos_vpd = get_cbmem_ptr(ptr);
info->chromeos_vpd = get_cbmem_addr(ptr);
}

static void cb_parse_fmap_cache(void *ptr, struct sysinfo_t *info)
{
info->fmap_cache = get_cbmem_ptr(ptr);
info->fmap_cache = get_cbmem_addr(ptr);
}

#if CONFIG(LP_TIMER_RDTSC)
Expand Down Expand Up @@ -282,7 +284,7 @@ int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
header->table_bytes) != header->table_checksum)
return -1;

info->header = header;
info->cb_header = virt_to_phys(header);

/* Initialize IDs as undefined in case they don't show up in table. */
info->board_id = UNDEFINED_STRAPPING_ID;
Expand Down Expand Up @@ -353,7 +355,7 @@ int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
break;
#endif
case CB_TAG_MAINBOARD:
info->mainboard = (struct cb_mainboard *)ptr;
info->cb_mainboard = virt_to_phys(ptr);
break;
case CB_TAG_GPIO:
cb_parse_gpios(ptr, info);
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/libc/memory.c
Expand Up @@ -90,7 +90,7 @@ static void *default_memmove(void *dst, const void *src, size_t n)
ssize_t i;

if (src > dst)
return memcpy(dst, src, n);
return default_memcpy(dst, src, n);

if (!IS_ALIGNED((uintptr_t)dst, sizeof(unsigned long)) ||
!IS_ALIGNED((uintptr_t)src, sizeof(unsigned long))) {
Expand Down
4 changes: 2 additions & 2 deletions payloads/nvramcui/Makefile
Expand Up @@ -26,9 +26,9 @@ else
endif

clean:
rm -f nvramcui.elf
rm -rf build libpayload nvramcui.elf

distclean: clean
rm -rf build libpayload .config .config.old
rm -rf .config .config.old

.PHONY: all clean distclean
39 changes: 39 additions & 0 deletions src/Kconfig
Expand Up @@ -270,6 +270,45 @@ config UBSAN
say N because it adds a small performance penalty and may abort
on code that happens to work in spite of the UB.

config HAVE_ASAN_IN_ROMSTAGE
bool
default n

config ASAN_IN_ROMSTAGE
bool
default n
help
Enable address sanitizer in romstage for platform.

config HAVE_ASAN_IN_RAMSTAGE
bool
default n

config ASAN_IN_RAMSTAGE
bool
default n
help
Enable address sanitizer in ramstage for platform.

config ASAN
bool "Address sanitizer support"
default n
select ASAN_IN_ROMSTAGE if HAVE_ASAN_IN_ROMSTAGE
select ASAN_IN_RAMSTAGE if HAVE_ASAN_IN_RAMSTAGE
help
Enable address sanitizer - runtime memory debugger,
designed to find out-of-bounds accesses and use-after-scope bugs.

This feature consumes up to 1/8 of available memory and brings about
~1.5x performance slowdown.

If unsure, say N.

if ASAN
comment "Before using this feature, make sure that "
comment "asan_shadow_offset_callback patch is applied to GCC."
endif

choice
prompt "Stage Cache for ACPI S3 resume"
default NO_STAGE_CACHE if !HAVE_ACPI_RESUME
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/acpi.c
Expand Up @@ -1628,7 +1628,7 @@ int get_acpi_table_revision(enum acpi_tables table)
case VFCT: /* ACPI 2.0/3.0/4.0: 1 */
return 1;
case IVRS:
return IVRS_FORMAT_FIXED;
return IVRS_FORMAT_MIXED;
case DBG2:
return 0;
case FACS: /* ACPI 2.0/3.0: 1, ACPI 4.0 upto 6.3: 2 */
Expand Down
43 changes: 37 additions & 6 deletions src/acpi/acpigen.c
Expand Up @@ -284,7 +284,6 @@ static void acpigen_emit_multi_namestring(const char *name)
pathlen[0] = count;
}


void acpigen_emit_namestring(const char *namepath)
{
int dotcount = 0, i;
Expand Down Expand Up @@ -687,7 +686,7 @@ void acpigen_write_empty_PTC(void)
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = 0,
.bit_offset = 0,
.access_size = 0,
.access_size = ACPI_ACCESS_SIZE_UNDEFINED,
.addrl = 0,
.addrh = 0,
};
Expand Down Expand Up @@ -930,8 +929,6 @@ void acpigen_write_TSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
acpigen_pop_len();
}



void acpigen_write_mem32fixed(int readwrite, u32 base, u32 size)
{
/*
Expand Down Expand Up @@ -1353,6 +1350,13 @@ void acpigen_write_to_integer(uint8_t src, uint8_t dst)
acpigen_emit_byte(dst);
}

void acpigen_write_to_integer_from_namestring(const char *source, uint8_t dst_op)
{
acpigen_emit_byte(TO_INTEGER_OP);
acpigen_emit_namestring(source);
acpigen_emit_byte(dst_op);
}

void acpigen_write_byte_buffer(uint8_t *arr, size_t size)
{
size_t i;
Expand Down Expand Up @@ -1553,7 +1557,7 @@ void acpigen_write_CPPC_package(const struct cppc_config *config)
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 == 0) {
reg->bit_width == 32 && reg->access_size == ACPI_ACCESS_SIZE_UNDEFINED) {
acpigen_write_dword(reg->addrl);
} else {
acpigen_write_register_resource(reg);
Expand Down Expand Up @@ -1772,7 +1776,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)
{
Expand Down Expand Up @@ -1971,3 +1974,31 @@ void acpigen_notify(const char *namestr, int value)
acpigen_emit_namestring(namestr);
acpigen_write_integer(value);
}

static void _create_field(uint8_t aml_op, uint8_t srcop, size_t byte_offset, const char *name)
{
acpigen_emit_byte(aml_op);
acpigen_emit_byte(srcop);
acpigen_write_integer(byte_offset);
acpigen_emit_namestring(name);
}

void acpigen_write_create_byte_field(uint8_t op, size_t byte_offset, const char *name)
{
_create_field(CREATE_BYTE_OP, op, byte_offset, name);
}

void acpigen_write_create_word_field(uint8_t op, size_t byte_offset, const char *name)
{
_create_field(CREATE_WORD_OP, op, byte_offset, name);
}

void acpigen_write_create_dword_field(uint8_t op, size_t byte_offset, const char *name)
{
_create_field(CREATE_DWORD_OP, op, byte_offset, name);
}

void acpigen_write_create_qword_field(uint8_t op, size_t byte_offset, const char *name)
{
_create_field(CREATE_QWORD_OP, op, byte_offset, name);
}
6 changes: 5 additions & 1 deletion src/acpi/acpigen_dptf.c
Expand Up @@ -2,6 +2,8 @@

#include <acpi/acpigen.h>
#include <acpi/acpigen_dptf.h>
#include <stdbool.h>
#include <stdint.h>

/* Defaults */
#define DEFAULT_RAW_UNIT "ma"
Expand All @@ -17,6 +19,7 @@ enum {
DEFAULT_TRIP_POINT = 0xFFFFFFFFull,
DEFAULT_WEIGHT = 100,
DPTF_MAX_ART_THRESHOLDS = 10,
FPS_REVISION = 0,
PPCC_REVISION = 2,
RAPL_PL1_INDEX = 0,
RAPL_PL2_INDEX = 1,
Expand Down Expand Up @@ -353,7 +356,8 @@ void dptf_write_fan_perf(const struct dptf_fan_perf *states, int max_count)

/* _FPS - Fan Performance States */
acpigen_write_name("_FPS");
pkg_count = acpigen_write_package(0);
pkg_count = acpigen_write_package(1); /* 1 for Revision */
acpigen_write_integer(FPS_REVISION); /* revision */

for (i = 0; i < max_count; ++i) {
/*
Expand Down
7 changes: 3 additions & 4 deletions src/acpi/acpigen_ps2_keybd.c
@@ -1,13 +1,12 @@
/*
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <acpi/acpi.h>
#include <acpi/acpigen.h>
#include <acpi/acpigen_ps2_keybd.h>
#include <console/console.h>
#include <input-event-codes.h>
#include <stdbool.h>
#include <stdint.h>

#define KEYMAP(scancode, keycode) (((uint32_t)(scancode) << 16) | (keycode & 0xFFFF))
#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/device.c
Expand Up @@ -8,6 +8,7 @@
#include <device/device.h>
#include <device/path.h>
#include <stdlib.h>
#include <types.h>
#include <crc_byte.h>

#if CONFIG(GENERIC_GPIO_LIB)
Expand Down Expand Up @@ -197,7 +198,6 @@ int acpi_device_status(const struct device *dev)
return ACPI_STATUS_DEVICE_ALL_ON;
}


/* Write the unique _UID based on ACPI device path. */
void acpi_device_write_uid(const struct device *dev)
{
Expand Down
1 change: 1 addition & 0 deletions src/arch/arm/Makefile.inc
Expand Up @@ -119,6 +119,7 @@ ramstage-y += memset.S
ramstage-y += memcpy.S
ramstage-y += memmove.S
ramstage-y += clock.c
ramstage-$(CONFIG_PAYLOAD_FIT_SUPPORT) += fit_payload.c

rmodules_arm-y += memset.S
rmodules_arm-y += memcpy.S
Expand Down
1 change: 0 additions & 1 deletion src/arch/arm/armv4/cache.c
Expand Up @@ -5,7 +5,6 @@
* Reference: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition
*/


#include <arch/cache.h>

void tlb_invalidate_all(void)
Expand Down
33 changes: 31 additions & 2 deletions src/arch/arm/armv7/bootblock.S
Expand Up @@ -62,14 +62,43 @@ init_stack_loop:
cmp r0, r1
bne init_stack_loop

/* Set stackpointer in internal RAM */
ldr sp, =_estack

/*
* For platforms where the flash is memory mapped (qemu), check if the
* bootblock needs to relocate itself.
*/
check_position:
adr r0, check_position
ldr r1, =check_position

cmp r0, r1
beq call_bootblock

/* Calculate source */
ldr r2, =_program
sub r1, r1, r2
sub r1, r0, r1
/* Get destination */
ldr r0, =_program
/* Get size */
ldr r2, =_eprogram
sub r2, r2, r0

bl memcpy

/* Get absolute address */
ldr lr, =call_bootblock
/* Directly modify pc as branch instruction changes the state */
mov pc, lr

call_bootblock:

/* Restore parameter passed in by maskrom/vendor firmware. */
ldr r0, =maskrom_param
str r10, [r0]

/* Set stackpointer in internal RAM to call bootblock main() */
ldr sp, =_estack
ldr r0,=0x00000000
/*
* The current design of cpu_info places the struct at the top of the
Expand Down
1 change: 0 additions & 1 deletion src/arch/arm/armv7/cache_m.c
Expand Up @@ -3,7 +3,6 @@
* cache.c: Cache maintenance routines for ARMv7-M
*/


#include <arch/cache.h>

void tlb_invalidate_all(void)
Expand Down
15 changes: 15 additions & 0 deletions src/arch/arm/armv7/cpu.S
Expand Up @@ -23,6 +23,19 @@
* THIS FUNCTION MUST PRESERVE THE VALUE OF r10
*/

#if ENV_USER_SPACE
/*
* Empty macro for code running in userspace. Trying to manipulate the
* cache from userspace hangs the system. To run code at a privileged level,
* the userspace code needs to execute an API call to the privileged mode
* code.
*/
.macro dcache_apply_all crm
bx lr
.endm

#else

.macro dcache_apply_all crm
dsb
mov r3, #-2 @ initialize level so that we start at 0
Expand Down Expand Up @@ -82,6 +95,8 @@
bx lr
.endm

#endif /* ENV_USER_SPACE */

/*
* Bring an ARM processor we just gained control of (e.g. from IROM) into a
* known state regarding caches/SCTLR. Completely cleans and invalidates
Expand Down
89 changes: 89 additions & 0 deletions src/arch/arm/fit_payload.c
@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <console/console.h>
#include <bootmem.h>
#include <program_loading.h>
#include <fit.h>
#include <symbols.h>

/**
* Place the region in free memory range.
*/
static bool fit_place_mem(const struct range_entry *r, void *arg)
{
struct region *region = arg;
resource_t start;

if (range_entry_tag(r) != BM_MEM_RAM)
return true;

/* Linux 4.15 doesn't like 4KiB alignment. Align to 1 MiB for now. */
start = ALIGN_UP(MAX(region->offset, range_entry_base(r)), 1 * MiB);

if (start + region->size < range_entry_end(r)) {
region->offset = (size_t)start;
return false;
}

return true;
}

bool fit_payload_arch(struct prog *payload, struct fit_config_node *config,
struct region *kernel,
struct region *fdt,
struct region *initrd)
{
void *arg = NULL;

/**
* The kernel ARM documentation recommends loading the kernel above 32MiB
* in order to avoid the need to need to relocate prior to decompression.
*/
kernel->offset = (uintptr_t)_dram + 32 * MiB;

/**
* The code assumes that bootmem_walk provides a sorted list of memory
* regions, starting from the lowest address.
* The order of the calls here doesn't matter, as the placement is
* enforced in the called functions.
* For details check code on top.
*/
if (!bootmem_walk(fit_place_mem, kernel))
return false;

/* Mark as reserved for future allocations. */
bootmem_add_range(kernel->offset, kernel->size, BM_MEM_PAYLOAD);

/**
* To ensure the fdt is not overwritten by the kernel decompressor, place
* the fdt above the 128 MB from the start of RAM, as recommended by the
* kernel documentation.
*/
fdt->offset = (uintptr_t)_dram + 128 * MiB;

if (!bootmem_walk(fit_place_mem, fdt))
return false;

/* Mark as reserved for future allocations. */
bootmem_add_range(fdt->offset, fdt->size, BM_MEM_PAYLOAD);

/* Place INITRD */
if (config->ramdisk) {
initrd->offset = fdt->offset + fdt->size;

if (!bootmem_walk(fit_place_mem, initrd))
return false;

/* Mark as reserved for future allocations. */
bootmem_add_range(initrd->offset, initrd->size, BM_MEM_PAYLOAD);
}

/* Kernel expects FDT as argument */
arg = (void *)fdt->offset;

prog_set_entry(payload, (void *)kernel->offset, arg);

bootmem_dump_ranges();

return true;
}
2 changes: 0 additions & 2 deletions src/arch/arm/include/armv4/arch/smp/spinlock.h
Expand Up @@ -4,12 +4,10 @@
#define _ARCH_SMP_SPINLOCK_H

#define DECLARE_SPIN_LOCK(x)
#define barrier() do {} while (0)
#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)
#define cpu_relax() do {} while (0)

#include <smp/node.h>
#define boot_cpu() 1
Expand Down
3 changes: 0 additions & 3 deletions src/arch/arm64/armv8/exception.c
Expand Up @@ -63,10 +63,8 @@ static void print_regs(struct exc_state *exc_state)
regs->x[30], regs->sp);
}


static struct exception_handler *handlers[NUM_EXC_VIDS];


int exception_handler_register(uint64_t vid, struct exception_handler *h)
{
if (vid >= NUM_EXC_VIDS)
Expand Down Expand Up @@ -122,7 +120,6 @@ static void print_exception_and_die(struct exc_state *state, uint64_t idx)
die("exception death");
}


static int handle_exception(struct exc_state *state, uint64_t idx)
{
int ret = EXC_RET_ABORT;
Expand Down
1 change: 0 additions & 1 deletion src/arch/arm64/include/armv8/arch/exception.h
Expand Up @@ -27,7 +27,6 @@ struct exception_handler {
struct exception_handler *next;
};


/*
* Register a handler provided with the associated vector id. Returns 0 on
* success, < 0 on error. Note that registration is not thread/interrupt safe.
Expand Down
2 changes: 0 additions & 2 deletions src/arch/ppc64/include/arch/io.h
Expand Up @@ -17,13 +17,11 @@ static inline void outl(uint32_t value, uint16_t port)
{
}


static inline uint8_t inb(uint16_t port)
{
return 0;
}


static inline uint16_t inw(uint16_t port)
{
return 0;
Expand Down
1 change: 0 additions & 1 deletion src/arch/riscv/arch_timer.c
Expand Up @@ -3,7 +3,6 @@
#include <device/mmio.h>
#include <arch/encoding.h>
#include <console/console.h>
#include <stddef.h>
#include <timer.h>
#include <mcall.h>

Expand Down
1 change: 0 additions & 1 deletion src/arch/riscv/include/vm.h
Expand Up @@ -12,7 +12,6 @@

void mstatus_init(void); // need to setup mstatus so we know we have virtual memory


#define DEFINE_MPRV_READ_FLAGS(name, type, insn, flags) \
static inline type name(type *p); \
static inline type name(type *p) \
Expand Down
3 changes: 0 additions & 3 deletions src/arch/riscv/misaligned.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stddef.h>
#include <stdint.h>
#include <vm.h>
#include <arch/exception.h>
Expand Down Expand Up @@ -132,7 +131,6 @@ static struct memory_instruction_info *match_instruction(uintptr_t insn)
return NULL;
}


static int fetch_16bit_instruction(uintptr_t vaddr, uintptr_t *insn, int *size)
{
uint16_t ins = mprv_read_mxr_u16((uint16_t *)vaddr);
Expand All @@ -158,7 +156,6 @@ static int fetch_32bit_instruction(uintptr_t vaddr, uintptr_t *insn, int *size)
return -1;
}


void handle_misaligned(trapframe *tf)
{
uintptr_t insn = 0;
Expand Down
1 change: 0 additions & 1 deletion src/arch/riscv/sbi.c
Expand Up @@ -49,7 +49,6 @@ static uintptr_t sbi_clear_ipi(void)
return 0;
}


/*
* sbi is triggered by the s-mode ecall
* parameter : register a0 a1 a2
Expand Down
1 change: 0 additions & 1 deletion src/arch/riscv/smp.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stddef.h>
#include <arch/encoding.h>
#include <arch/smp/smp.h>
#include <arch/smp/spinlock.h>
Expand Down
1 change: 1 addition & 0 deletions src/arch/x86/Kconfig
Expand Up @@ -4,6 +4,7 @@ config ARCH_X86
bool
select PCI
select RELOCATABLE_MODULES
select HAVE_ASAN_IN_RAMSTAGE

# stage selectors for x86

Expand Down
6 changes: 6 additions & 0 deletions src/arch/x86/Makefile.inc
Expand Up @@ -195,7 +195,11 @@ endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64
# postcar
###############################################################################

ifeq ($(CONFIG_ARCH_POSTCAR_X86_32),y)
$(eval $(call create_class_compiler,postcar,x86_32))
else
$(eval $(call create_class_compiler,postcar,x86_64))
endif
postcar-generic-ccopts += -D__POSTCAR__

postcar-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c
Expand Down Expand Up @@ -241,6 +245,7 @@ ramstage-$(CONFIG_ACPI_BERT) += acpi_bert_storage.c
ramstage-y += boot.c
ramstage-y += post.c
ramstage-y += c_start.S
ramstage-y += c_exit.S
ramstage-y += cpu.c
ramstage-y += cpu_common.c
ramstage-y += ebda.c
Expand All @@ -255,6 +260,7 @@ ramstage-$(CONFIG_GENERATE_MP_TABLE) += mpspec.c
ramstage-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.c
ramstage-y += rdrand.c
ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c
ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios_defaults.c
ramstage-y += tables.c
ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
Expand Down