75 changes: 65 additions & 10 deletions Documentation/mainboard/facebook/monolith.md
Expand Up @@ -3,22 +3,73 @@
This page describes how to run coreboot on the Facebook Monolith.

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

## Required blobs

This board currently requires:
fsp blobs 3rdparty/fsp/KabylakeFspBinPkg/Fsp_M.fd
3rdparty/fsp/KabylakeFspBinPkg/Fsp_S.fd
Mainboard is based on the Intel Kaby Lake U SoC.
Intel company provides [Firmware Support Package (2.0)](../../soc/intel/fsp/index.md)
(intel FSP 2.0) to initialize this generation silicon. Please see this
[document](../../soc/intel/code_development_model/code_development_model.md).

Microcode 3rdparty/intel-microcode/intel-ucode
FSP Information:

```eval_rst
+-----------------------------+-------------------+-------------------+
| FSP Project Name | Directory | Specification |
+-----------------------------+-------------------+-------------------+
| 7th Generation Intel® Core™ | KabylakeFspBinPkg | 2.0 |
| processors and chipsets | | |
| (formerly Kaby Lake) | | |
+-----------------------------+-------------------+-------------------+
```

Microcode: 3rdparty/intel-microcode/intel-ucode

## Flash components

To create a complete flash image, the flash descriptor, GBE and ME blobs are required. The
complete image can be used when e.g. a blank flash should be programmed. In other cases (when
only coreboot needs to be replaced) placeholders can be used for the GBE and ME regions.

These can be extracted from the original flash image as follows:
1) Read the complete image from flash.
2) Create a layout file with the following content:
```
00000000:00000fff fd
00700000:00ffffff bios
00003000:006FFFFF me
00001000:00002fff gbe
```
3) Use `ifdtool -n <layout_file> <flash_image>` to resize the *bios* region from the default 6MB
to 9 MB, this is required to create sufficient space for LinuxBoot.
NOTE: Please make sure only the firmware descriptor (*fd*) region is changed. Older versions
of the ifdtool corrupt the *me* region.
4) Use `ifdtool -x <resized_flash_image>` to extract the components.

The regions extracted can be used to generate a full flash image. The *bios* region is
not needed as this is replaced by the coreboot image.

NOTE: The gbe region contains the MAC address so be careful. When updating the flash using
flashrom it is advisable to leave out the *gbe* area.

## Flashing coreboot

### Internal programming

The SPI flash can be accessed using [flashrom].

The descriptor area needs to be updated once to resize the *bios* region.
`flashrom -p internal --ifd -i fd -w <coreboot.bin>`

After that only the bios area should to be updated.
`flashrom -p internal --ifd -i bios -w <coreboot.bin>`

The *gbe* and *me* regions should not be updated.

NOTE: As `flashrom --ifd` uses the flash descriptor it is required to update the
descriptor and bios regions in the right sequence. Don't update both in one command.

### External programming

The system has an internal flash chip which is a 16 MiB soldered SOIC-8 chip.
Expand All @@ -37,25 +88,29 @@ solution. Wires need to be connected to be able to flash using an external progr
## Untested

- Hardware monitor
- SDIO
- Full Embedded Controller support
- eMMC
- SATA
- xDCI

## Working

- USB
- Gigabit Ethernet
- Gigabit Ethernet (i219 and i210)
- Graphics (Using FSP GOP)
- flashrom
- PCIe
- PCIe including hotplug on FPGA root port
- EC serial port
- EC CPU temperature
- SMBus
- Initialization with FSP
- SeaBIOS payload (commit a5cab58e9a3fb6e168aba919c5669bea406573b4)
- TianoCore payload (commit a5cab58e9a3fb6e168aba919c5669bea406573b4)
- LinuxBoot (kernel kernel-4_19_97) (uroot commit 9c9db9dbd6b532f5f91a511a0de885c6562aadd7)
- eMMC

All of the above has been briefly tested by booting Linux from eMMC using the TianoCore payload
and LinuxBoot.

All of the above has been briefly tested by booting Linux from the TianoCore payload.
SeaBios has been checked to the extend that it runs to the boot selection and provides display
output.

Expand Down
7 changes: 4 additions & 3 deletions Documentation/mainboard/index.md
Expand Up @@ -82,16 +82,17 @@ The boards in this section are not real mainboards, but emulators.
### Sandy Bridge series

- [T420](lenovo/t420.md)
- [T420 / T520 / X220 / T420s / W520 common](lenovo/xx20_series.md)
- [x1](lenovo/x1.md)
- [T420 / T520 / X220 / T420s / W520 common](lenovo/Sandy_Bridge_series.md)
- [X1](lenovo/x1.md)

### Ivy Bridge series

- [T430](lenovo/t430.md)
- [T530](lenovo/w530.md)
- [W530](lenovo/w530.md)
- [T430 / T530 / X230 / W530 common](lenovo/xx30_series.md)
- [T430 / T530 / X230 / W530 common](lenovo/Ivy_Bridge_series.md)
- [T431s](lenovo/t431s.md)
- [Internal flashing](lenovo/ivb_internal_flashing.md)

### Haswell series

Expand Down
@@ -1,5 +1,7 @@
# Lenovo Ivy Bridge series

This information is valid for all supported models, except T430s and T431s.

## Flashing coreboot
```eval_rst
+---------------------+--------------------------------+
Expand Down Expand Up @@ -72,5 +74,5 @@ region. The update is then written into the EC once.

![][fl]

[fl]: flashlayout_xx30.svg
[fl]: flashlayout_Ivy_Bridge.svg

Expand Up @@ -44,5 +44,5 @@ region. The update is then written into the EC once.

![][fl]

[fl]: flashlayout_xx20.svg
[fl]: flashlayout_Sandy_Bridge.svg

File renamed without changes
File renamed without changes
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
361 changes: 361 additions & 0 deletions Documentation/mainboard/lenovo/ivb_internal_flashing.md
@@ -0,0 +1,361 @@
# Ivy Bridge Lenovo ThinkPad Internal Flashing

## Introduction

Old versions of stock BIOS for these models have several security issues.
In order to flash coreboot internally, two of them are of interest.

**First** is the fact the `SMM_BWP` and `BLE` are not enabled in BIOS
versions released before 2014. We have tested many versions on T430 and
X230 and found out that `SMM_BWP=1` only since the update, the changelog
of which contains following line:

> (New) Improved the UEFI BIOS security feature.

**Second** is [S3 Boot Script vulnerability](https://support.lenovo.com/eg/ru/product_security/s3_boot_protect),
that was discovered and fixed later.

## Requirements

- USB drive (in case you need to downgrade BIOS)
- Linux install that (can be) loaded in UEFI mode
- [CHIPSEC](https://github.com/chipsec/chipsec)

## BIOS versions

Below is a table of BIOS versions that are vulnerable enough for our
goals, per model. The version number means that you need to downgrade to
that or earlier version.

```eval_rst
+------------+--------------+
| Model | BIOS version |
+============+==============+
| X230 | 2.60 |
+------------+--------------+
| X230T | 2.58 |
+------------+--------------+
| T430 | 2.64 |
+------------+--------------+
| T430s | 2.59 |
+------------+--------------+
| T530 | 2.60 |
+------------+--------------+
| W530 | 2.58 |
+------------+--------------+
```

If your BIOS version is equal or lower, skip to the
**[Examining protections](#examining-protections-theory)** section. If not,
go through the downgrade process, described next.

## Downgrading BIOS

Go to the Lenovo web site and download BIOS Update Bootable CD for your
machine of needed version (see above).

Lenovo states that BIOS has "security rollback prevention", meaning once
you update it to some version X, you will not be able to downgrade it to
pre-X version. That's not true. It seems that this is completely
client-side restriction in flashing utilities (both Windows utility and
Bootable CD). You just need to call `winflash.exe` or `dosflash.exe`
directly. Therefore you need to modify the bootable CD image you just
downloaded.

Extract an El Torito image:

geteltorito -o ./bios.img g1uj41us.iso

Mount the partition in that image:

sudo mount -t vfat ./bios.img /mnt -o loop,offset=16384

List files, find the `AUTOEXEC.BAT` file and the `FLASH` directory:

ls /mnt
ls /mnt/FLASH

Inside the `FLASH` directory, there should be a directory called
`G1ET93WW` or similar (exact name depends on your ThinkPad model and
BIOS version). See what's inside:

ls /mnt/FLASH/G1ET93WW

There must be a file with `.FL1` extension called `$01D2000.FL1` or
something similar.

Now open the `AUTOEXEC.BAT` file:

sudo vim /mnt/AUTOEXEC.BAT

You will see a list of commands:

@ECHO OFF
PROMPT $p$g
cd c:\flash
command.com

Replace the last line (`command.com`) with this (change path to the
`.FL1` file according to yours):

dosflash.exe /sd /file G1ET93WW\$01D2000.FL1

Save the file, then unmount the partition:

sudo unmount /mnt

Write this image to a USB drive (replace `/dev/sdX` with your USB drive
device name):

sudo dd if=./bios.img of=/dev/sdX bs=1M

Now reboot and press F1 to enter BIOS settings. Open the **Startup** tab
and set the startup mode to **Legacy** (or **Both**/**Legacy First**):

![](ivb_bios_legacy_only.jpg)

Press F10 to save changes and reboot.

Now, before you process, make sure that AC adapter is connected! If your
battery will die during the process, you'll likely need external
programmer to recover.

Boot from the USB drive (press F12 to select boot device), and BIOS
flashing process should begin:

![](ivb_bios_flashing1.jpg)

![](ivb_bios_flashing2.jpg)

It may reboot a couple of times in the process. Do not interrupt it.

When it's completed, go back to the BIOS settings and set startup mode
to **UEFI** (or **Both**/**UEFI First**). This is required for
vulnerability exploitation.

![](ivb_bios_uefi_only.jpg)

Then boot to your system and make sure that `/sys/firmware/efi` or
`/sys/firmware/efivars` exist.

## Examining protections (theory)

There are two main ways that Intel platform provides to protect BIOS
chip:
- **BIOS_CNTL** register of LPC Interface Bridge Registers (accessible
via PCI configuration space, offset 0xDC). It has:
* **SMM_BWP** (*SMM BIOS Write Protect*) bit. If set to 1, the BIOS is
writable only in SMM. Once set to 1, cannot be changed anymore.
* **BLE** (*BIOS Lock Enable*) bit. If set to 1, setting BIOSWE to 1
will raise SMI. Once set to 1, cannot be changed anymore.
* **BIOSWE** (*BIOS Write Enable*) bit. Controls whether BIOS is
writable. This bit is always R/W.
- SPI Protected Range Registers (**PR0**-**PR4**) of SPI Configuration
Registers (SPIBAR+0x74 - SPIBAR+0x84). Each register has bits that
define protected range, plus WP bit, that defines whether write
protection is enabled.

There's also **FLOCKDN** bit of HSFS register (SPIBAR+0x04) of SPI
Configuration Registers. When set to 1, PR0-PR4 registers cannot be
written. Once set to 1, cannot be changed anymore.

To be able to flash, we need `SMM_BWP=0`, `BIOSWE=1`, `BLE=0`, `FLOCKDN=0` or
SPI protected ranges (PRx) to have a WP bit set to 0.

Let's see what we have. Examine `HSFS` register:

sudo chipsec_main -m chipsec.modules.common.spi_lock

You should see that `FLOCKDN=1`:

[x][ =======================================================================
[x][ Module: SPI Flash Controller Configuration Locks
[x][ =======================================================================
[*] HSFS = 0xE009 << Hardware Sequencing Flash Status Register (SPIBAR + 0x4)
[00] FDONE = 1 << Flash Cycle Done
[01] FCERR = 0 << Flash Cycle Error
[02] AEL = 0 << Access Error Log
[03] BERASE = 1 << Block/Sector Erase Size
[05] SCIP = 0 << SPI cycle in progress
[13] FDOPSS = 1 << Flash Descriptor Override Pin-Strap Status
[14] FDV = 1 << Flash Descriptor Valid
[15] FLOCKDN = 1 << Flash Configuration Lock-Down

Then check `BIOS_CNTL` and PR0-PR4:

sudo chipsec_main -m common.bios_wp

Good news: on old BIOS versions, `SMM_BWP=0` and `BLE=0`.

Bad news: there are 4 write protected SPI ranges:

[x][ =======================================================================
[x][ Module: BIOS Region Write Protection
[x][ =======================================================================
[*] BC = 0x 8 << BIOS Control (b:d.f 00:31.0 + 0xDC)
[00] BIOSWE = 0 << BIOS Write Enable
[01] BLE = 0 << BIOS Lock Enable
[02] SRC = 2 << SPI Read Configuration
[04] TSS = 0 << Top Swap Status
[05] SMM_BWP = 0 << SMM BIOS Write Protection
[-] BIOS region write protection is disabled!

[*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF
SPI Protected Ranges
------------------------------------------------------------
PRx (offset) | Value | Base | Limit | WP? | RP?
------------------------------------------------------------
PR0 (74) | 00000000 | 00000000 | 00000000 | 0 | 0
PR1 (78) | 8BFF0B40 | 00B40000 | 00BFFFFF | 1 | 0
PR2 (7C) | 8B100B10 | 00B10000 | 00B10FFF | 1 | 0
PR3 (80) | 8ADE0AD0 | 00AD0000 | 00ADEFFF | 1 | 0
PR4 (84) | 8AAF0800 | 00800000 | 00AAFFFF | 1 | 0

Other way to examine SPI configuration registers is to just dump SPIBAR:

sudo chipsec_util mmio dump SPIBAR

You will see `SPIBAR` address (0xFED1F800) and registers (for example,
`00000004` is `HSFS`):

[mmio] MMIO register range [0x00000000FED1F800:0x00000000FED1F800+00000200]:
+00000000: 0BFF0500
+00000004: 0004E009
...

As you can see, the only thing we need is to unset WP bit on PR0-PR4.
But that cannot be done once `FLOCKDN` is set to 1.

Now the fun part!

`FLOCKDN` may only be cleared by a hardware reset, which includes S3
state. On S3 resume boot path, the chipset configuration has to be
restored and it's done by executing so-called S3 Boot Scripts. You can
dump these scripts by executing:

sudo chipsec_util uefi s3bootscript

There are many entries. Along them, you can find instructions to write
to `HSFS` (remember, we know that `SPIBAR` is 0xFED1F800):

Entry at offset 0x2B8F (len = 0x17, header len = 0x0):
Data:
02 00 17 02 00 00 00 01 00 00 00 04 f8 d1 fe 00 |
00 00 00 09 e0 04 00 |
Decoded:
Opcode : S3_BOOTSCRIPT_MEM_WRITE (0x0002)
Width : 0x02 (4 bytes)
Address: 0xFED1F804
Count : 0x1
Values : 0x0004E009

These scripts are stored in memory. The vulnerability is that we can
overwrite this memory, change these instructions and they will be
executed on S3 resume. Once we patch that instruction to not set `FLOCKDN`
bit, we will be able to write to PR0-PR4 registers.

## Creating a backup

Before you proceed, please create a backup of the `bios` region. Then,
in case something goes wrong, you'll be able to flash it back externally.

The `me` region is locked, so an attempt to create a full dump will fail.
But you can back up the `bios`:

sudo flashrom -p internal -r bios_backup.rom --ifd -i bios

If you will ever need to flash it back, use `--ifd -i bios` as well:

sudo flashrom -p <YOUR_PROGRAMMER> -w bios_backup.rom --ifd -i bios

**Caution:** if you will omit `--ifd -i bios` for flashing, you will
brick your machine, because your backup has `FF`s in place of `fd` and
`me` regions. Flash only `bios` region!

## Removing protections (practice)

The original boot script writes 0xE009 to `HSFS`. `FLOCKDN` is 15th bit, so
let's write 0x6009 instead:

sudo chipsec_main -m tools.uefi.s3script_modify -a replace_op,mmio_wr,0xFED1F804,0x6009,0x2

You will get a lot of output and in the end you should see something
like this:

[*] Modifying S3 boot script entry at address 0x00000000DAF49B8F..
[mem] 0x00000000DAF49B8F
[*] Original entry:
2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 |
0 0 0 9 e0 4 0 |
[mem] buffer len = 0x17 to PA = 0x00000000DAF49B8F
2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 |
0 0 0 9 60 0 0 | `
[mem] 0x00000000DAF49B8F
[*] Modified entry:
2 0 17 2 0 0 0 1 0 0 0 4 f8 d1 fe 0 |
0 0 0 9 60 0 0 | `
[*] After sleep/resume, check the value of register 0xFED1F804 is 0x6009
[+] PASSED: The script has been modified. Go to sleep..

Now go to S3, then resume and check `FLOCKDN`. It should be 0:

sudo chipsec_main -m chipsec.modules.common.spi_lock

...
[x][ =======================================================================
[x][ Module: SPI Flash Controller Configuration Locks
[x][ =======================================================================
[*] HSFS = 0x6008 << Hardware Sequencing Flash Status Register (SPIBAR + 0x4)
[00] FDONE = 0 << Flash Cycle Done
[01] FCERR = 0 << Flash Cycle Error
[02] AEL = 0 << Access Error Log
[03] BERASE = 1 << Block/Sector Erase Size
[05] SCIP = 0 << SPI cycle in progress
[13] FDOPSS = 1 << Flash Descriptor Override Pin-Strap Status
[14] FDV = 1 << Flash Descriptor Valid
[15] FLOCKDN = 0 << Flash Configuration Lock-Down
[-] SPI Flash Controller configuration is not locked
[-] FAILED: SPI Flash Controller not locked correctly.
...

Remove WP from protected ranges:

sudo chipsec_util mmio write SPIBAR 0x74 0x4 0xAAF0800
sudo chipsec_util mmio write SPIBAR 0x78 0x4 0xADE0AD0
sudo chipsec_util mmio write SPIBAR 0x7C 0x4 0xB100B10
sudo chipsec_util mmio write SPIBAR 0x80 0x4 0xBFF0B40

Verify that it worked:

sudo chipsec_main -m common.bios_wp

[x][ =======================================================================
[x][ Module: BIOS Region Write Protection
[x][ =======================================================================
[*] BC = 0x 9 << BIOS Control (b:d.f 00:31.0 + 0xDC)
[00] BIOSWE = 1 << BIOS Write Enable
[01] BLE = 0 << BIOS Lock Enable
[02] SRC = 2 << SPI Read Configuration
[04] TSS = 0 << Top Swap Status
[05] SMM_BWP = 0 << SMM BIOS Write Protection
[-] BIOS region write protection is disabled!

[*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF
SPI Protected Ranges
------------------------------------------------------------
PRx (offset) | Value | Base | Limit | WP? | RP?
------------------------------------------------------------
PR0 (74) | 0AAF0800 | 00800000 | 00AAF000 | 0 | 0
PR1 (78) | 0ADE0AD0 | 00AD0000 | 00ADE000 | 0 | 0
PR2 (7C) | 0B100B10 | 00B10000 | 00B10000 | 0 | 0
PR3 (80) | 0BFF0B40 | 00B40000 | 00BFF000 | 0 | 0
PR4 (84) | 00000000 | 00000000 | 00000000 | 0 | 0

Bingo!

Now you can [flash internally](/flash_tutorial/int_flashrom.md).
Remember to flash only the `bios` region (use `--ifd -i bios -N`
flashrom arguments). `fd` and `me` are still locked.

Note that you should have an external SPI programmer as a backup method.
It will help you recover if you flash non-working ROM by mistake.
8 changes: 3 additions & 5 deletions Documentation/mainboard/lenovo/t420.md
Expand Up @@ -14,12 +14,10 @@ W25Q64CVSIG. Do not rely on dots painted in the corner of the chip (such as
the blue dot pictured) to orient the pins!

For more details have a look at [T420 / T520 / X220 / T420s / W520 common] and

```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
the general [flashing tutorial].

Steps to access the flash IC are described here [T4xx series].

[T4xx series]: t4xx_series.md
[T420 / T520 / X220 / T420s / W520 common]: xx20_series.md
[flashing tutorial]: ../../flash_tutorial/ext_power.md
[T420 / T520 / X220 / T420s / W520 common]: Sandy_Bridge_series.md
7 changes: 3 additions & 4 deletions Documentation/mainboard/lenovo/t430.md
Expand Up @@ -5,11 +5,10 @@ You have to disassemble the whole device, as the flash ICs are on the bottom
of the mainboard.

For more details have a look at [T430 / T530 / X230 / T430s / W530 common] and
```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
the general [flashing tutorial].

Steps to access the flash IC are described here [T4xx series].

[flashing tutorial]: ../../flash_tutorial/ext_power.md
[T4xx series]: t4xx_series.md
[T430 / T530 / X230 / T430s / W530 common]: xx30_series.md
[T430 / T530 / X230 / T430s / W530 common]: Ivy_Bridge_series.md
6 changes: 2 additions & 4 deletions Documentation/mainboard/lenovo/t431s.md
Expand Up @@ -26,9 +26,7 @@ the programmer.

![t431s_programming](t431s_programming.jpg)

```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
The general [flashing tutorial] has more details.

Currently, detecting the model of soldered RAM at runtime and loading
the corresponding SPD datum from CBFS is not implemented yet. You may
Expand All @@ -39,4 +37,4 @@ inteltool, and replace the content of the SPD hex with what is dumped.
I do not know how to find gpio ports for that, and SPD data stored in
vendor firmware.)

[T420 / T520 / X220 / T420s / W520 common]: xx20_series.md
[T420 / T520 / X220 / T420s / W520 common]: Sandy_Bridge_series.md
7 changes: 3 additions & 4 deletions Documentation/mainboard/lenovo/w530.md
Expand Up @@ -10,9 +10,7 @@ As all lines except /CS are shared between the flash ICs you can access
both with an external programmer.

For more details have a look at [T430 / T530 / X230 / T430s / W530 common] and
```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
the general [flashing tutorial].

### After removing the keyboard and palm rest
![][w530-1]
Expand All @@ -24,4 +22,5 @@ For more details have a look at [T430 / T530 / X230 / T430s / W530 common] and

[w530-2]: w530-2.jpg

[T430 / T530 / X230 / T430s / W530 common]: xx30_series.md
[flashing tutorial]: ../../flash_tutorial/ext_power.md
[T430 / T530 / X230 / T430s / W530 common]: Ivy_Bridge_series.md
8 changes: 3 additions & 5 deletions Documentation/mainboard/lenovo/x1.md
Expand Up @@ -13,12 +13,10 @@ The flash IC can be a SOIC-8 one or a WSON-8 one, and may be covered with
a piece of insulation tape.

For more details have a look at [T420 / T520 / X220 / T420s / W520 common] and

```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
the general [flashing tutorial].

Steps to access the flash IC are described here [X2xx series].

[X2xx series]: x2xx_series.md
[T420 / T520 / X220 / T420s / W520 common]: xx20_series.md
[flashing tutorial]: ../../flash_tutorial/ext_power.md
[T420 / T520 / X220 / T420s / W520 common]: Sandy_Bridge_series.md
39 changes: 21 additions & 18 deletions Documentation/mainboard/lenovo/x301.md
Expand Up @@ -22,23 +22,26 @@ SOIC-8 one (you might need to add the chip to the IFD VSCC list), as
what is done in the photo.

The vendor IFD VSCC list contains:
-MACRONIX_MX25L6405 (0xc2, 0x2017)
-WINBOND_NEX_W25X64 (0xef, 0x3017)
-ATMEL_AT25DF641 (0x1f, 0x4800)
- MACRONIX_MX25L6405 (0xc2, 0x2017)
- WINBOND_NEX_W25X64 (0xef, 0x3017)
- ATMEL_AT25DF641 (0x1f, 0x4800)

The general [flashing tutorial] has more details.

```eval_rst
:doc:`../../flash_tutorial/ext_power`
```
Tested:
- CPU Core 2 Duo U9400
- Slotted DIMM 4GiB*2 from samsung
- Camera
- pci-e slots
- sata and usb2
- libgfxinit-based graphic init
- NVRAM options for North and South bridges
- Sound
- Thinkpad EC
- S3
- Linux 4.19.67-2 within Debian GNU/Linux stable, loaded from
Linux payload (Heads) and Seabios.
- Core 2 Duo U9400 CPU
- Slotted DIMM 4GiB*2 from Samsung
- Camera
- PCI-e slots
- SATA and USB2
- libgfxinit-based graphics init
- NVRAM options for North and South bridges
- Sound
- ThinkPad EC
- S3
- Linux 4.19.67-2 within Debian GNU/Linux stable, loaded from
Linux payload (Heads) and SeaBIOS.


[flashing tutorial]: ../../flash_tutorial/ext_power.md

2 changes: 1 addition & 1 deletion Documentation/mainboard/msi/ms7707/ms7707.md
Expand Up @@ -75,7 +75,7 @@ Put all back in place and restart the board. It might need 1-2 AC power cycles
to reinitialize (running at full fan speed - don't panic).
* External flashing has been tested with RPi2 without main power connected.
3.3V provided by RPi2. Read more about flashing methods [here](https://doc.coreboot.org/flash_tutorial/index.html).
* In case of going back to proprietary BIOS create/save cmos settings as early
* In case of going back to proprietary BIOS create/save CMOS settings as early
as possible (do not leave BIOS on first start without saving settings).
The BIOS might corrupt nvram (not cmos!) and leave the system in a dead state
that needs an external flasher to revive. If stuck, reset the Fintek (see
Expand Down
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.6-relnotes.md
Expand Up @@ -164,7 +164,7 @@ Drivers (29 commits)
* i2c/hid: Add generic I2C HID driver
* i2c/max98927: add i2c driver for Maxim 98927 codec
* i2c/wacom_ts: Add support for WCOM touchscreen device driver
* pc80/rtc: Check cmos checksum BEFORE reading cmos value
* pc80/rtc: Check CMOS checksum BEFORE reading CMOS value
* regulator: Add driver for handling GPIO-based fixed regulator
* storage: Add SD/MMC/eMMC driver based upon depthcharge

Expand Down
2 changes: 1 addition & 1 deletion Documentation/releases/coreboot-4.8.1-relnotes.md
Expand Up @@ -40,7 +40,7 @@ possible

Lenovo mainboards
-----------------
* Started integration of VBT (Video Bios Table) binary files to
* Started integration of VBT (Video BIOS Table) binary files to
support native graphics initialisation

Internal changes
Expand Down
1 change: 1 addition & 0 deletions Documentation/soc/amd/family15h.md
Expand Up @@ -47,3 +47,4 @@ structure.
3. [Models 30h-3Fh BKDG](https://www.amd.com/system/files/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf)
4. [Models 60h-6Fh BKDG](https://www.amd.com/system/files/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf)
5. [Models 70h-7Fh BKDG](https://www.amd.com/system/files/TechDocs/55072_AMD_Family_15h_Models_70h-7Fh_BKDG.pdf)
6. [PSP Integration](psp_integration.md)
131 changes: 78 additions & 53 deletions Documentation/soc/amd/family17h.md
Expand Up @@ -14,13 +14,12 @@ Family 17h products are x86-based designs. This documentation assumes
familiarity with x86, its reset state and its early initialization
requirements.

To the extent necessary, the role of the Platform Security Processor
(a.k.a. PSP) in system initialization is addressed here. AMD has
historically required an NDA for access to the PSP
specification<sup>1</sup>. coreboot relies on util/amdfwtool to build
the structures and add various other firmware to the final image. The
Family 17h PSP design guide adds a new BIOS Directory Table, similar to
the PSP Directory Table.
To the extent necessary, the role of the AMD Secure Processor (a.k.a.
Platform Security Processor or PSP) in system initialization is addressed
here. The PSP specification<sup>1</sup> is available only with an NDA.
coreboot relies on util/amdfwtool to build the structures and add various
other firmware to the final image<sup>2</sup>. The Family 17h PSP design
guide adds a new BIOS Directory Table, similar to the PSP Directory Table.

Support in coreboot for modern AMD products is based on AMD’s
reference code: AMD Generic Encapsulated Software Architecture
Expand All @@ -29,12 +28,12 @@ configuring proprietary core logic, assistance with generating ACPI
tables, and other features.

AGESA for products earlier than Family 17h is known as v5 or
Arch2008<sup>2</sup>. Also note that coreboot currently contains both
Arch2008<sup>3</sup>. Also note that coreboot currently contains both
open source AGESA and closed source implementations (binaryPI) compiled
from AGESA.

The first AMD Family 17h device ported to coreboot is codenamed
“Picasso”<sup>3</sup>, and will be added to soc/amd/picasso.
“Picasso”<sup>4</sup>, and will be added to soc/amd/picasso.

## Additional Definitions

Expand All @@ -51,8 +50,13 @@ related firmware images
* Embedded Firmware Structure - Signature and pointers used by the
PSP to locate the PSP Directory Table and BIOS Directory Table; these
items are generated during coreboot build and are located in the SPI ROM
* Verstage - The code to verify the firmware contained in the
writable section of the SPI ROM
* vboot - The generic technology name for verifying/choosing a RW A/B
or fallback RO path.
* verstage - The code (vboot) to verify the firmware contained in the
writable section of the SPI ROM, traditionally run on the x86 processor,
and in some cases a separate stage added to coreboot
* vboot app - A portion of vboot technology designed and compiled
to run on the PSP
* APCB - AMD PSP Customization Block - A binary containing PSP and
system configuration preferences (analogous to v5 BUILDOPT_ options),
and generated by APCBTool to be added to coreboot/utils later
Expand Down Expand Up @@ -90,7 +94,8 @@ dependency expressions, much functionality is rewritten as libraries,
etc. It would, in no way, fit into the v5 model used in coreboot.

* For the foreseeable future, AGESA source will distributed only
under NDA.
under NDA. Furthermore, because AGESA's integrated debug services divulge
NDA information, no debug builds will be released to the general public.

## Basic Pre-x86 Boot Flow

Expand All @@ -102,15 +107,15 @@ The following steps occur prior to x86 processor operation.
the SPI ROM
* PSP verifies and executes the PSP off-chip bootloader
* ChromeOS systems:
* Off-chip bootloader attempts to locate verstage via the RO BIOS
* Off-chip bootloader attempts to locate vboot app via the RO BIOS
Directory Table
* If verstage is not found, booting continues with ABLs below
* Verstage initializes, setting up GPIOs, UART if needed,
* If vboot app is not found, booting continues with ABLs below
* vboot app initializes, setting up GPIOs, UART if needed,
communication path to the EC, and the SPI controller for direct access
to the flash device.
* Verstage verifies the RW sections (as is typically performed by
* vboot app verifies the RW sections (as is typically performed by
the main processor)
* Verstage locates the Embedded Firmware Directory within the
* vboot app locates the Embedded Firmware Directory within the
verified FMAP section and passes a pointer to the PSP bootloader. If
the verification fails, it passes a pointer to the RO header to the
bootloader.
Expand Down Expand Up @@ -166,59 +171,79 @@ jump to protected mode must jump to the physical address in DRAM. Any
code that is position-dependent must be linked to run at the final
destination.

## Initial coreboot Implementation
## Implementation for coreboot

Supporting Picasso doesn’t fit well with many of the coreboot
assumptions. Initial porting shall attempt to fit within existing
coreboot paradigms and make minimal changes to common code.
Supporting Picasso doesn’t fit perfectly with many of the coreboot
assumptions about x86 processors. Changes are introduced primarily
into arch/x86 to accommodate a processor starting in DRAM and at a
nontraditional reset vector.

### CAR and bootblock
### CAR and early stages

The coreboot bootblock contains features Picasso doesn’t require or
can’t use, and is assumed to execute in an unusable location.
Picasso’s requirement for bootblock in coreboot will be eliminated.
The traditional coreboot bootblock and romstage rely on cache-as-RAM
and a linker script that positions temporary storage accordingly. A
substitute for the DCACHE variables, called EARLYRAM, is introduced.
Like DCACHE, this allows for a consistent mapping of early regions
required across multiple stages prior to cbmem coming online.
Examples are the _preram_cbmem_console and _timestamp.

### Hybrid romstage
Due to Picasso's unique nature of starting with DRAM already available,
no early stages run as execute-in-place (XIP). All post-bootblock
stages are copied from the BIOS flash into DRAM for faster
performance, and these regions are marked reserved later in POST.

Picasso’s x86 reset state doesn’t meet the coreboot expectations
for jumping directly to ramstage. The primary feature of romstage is
also not needed, however there are other important features that are
typically in romstage that Picasso does need.
Unlike CAR-based systems, and because Picasso does not run early
stages as XIP, its early stages are not constrained in their use
of .bss or .data sections. All stages' .bss is zeroed, and all
.data sections are fully R/W at load time.

The romstage architecture is designed around the presence of CAR.
Several features implement ROMSTAGE_CBMEM_INIT_HOOK, expecting to move
data from CAR to cbmem. The hybrid romstage consumes DRAM for the
purpose of implementing the expected CAR storage. This region as well
as the DRAM where romstage is decompressed must be reserved and
unavailable to the OS.
### bootblock

The initial Picasso port implements a hybrid romstage that contains the
first instruction fetched at the reset vector. It minimally configures
flat protected mode, initializes cbmem, then loads the next stage.
Future work will consider breaking the dependencies mentioned above
and/or potentially loading ramstage directly from the PSP.
Picasso uses a bootblock that mirrors a traditional bootblock as much
as possible. Because the image is loaded by the PSP, the bootblock is
not restricted to the top of the BIOS flash device. The compressed
image is added into the PSP's `amdfw.rom` build.

### vboot app and verstage

Development is currently underway for the vboot app, and potentially
an x86-based verstage companion. This document shall be updated once
the design is finalized and functioning. Support for the PSP honoring
the presence of the vboot app is available only in certain SKUs.

### romstage and postcar

A traditional romstage is maintained for Picasso. The primary reason for
this choice is to remain compatible with coreboot conventions and
to support the FSP 2.0 driver. Picasso's romstage uses an
fsp_memory_init() call to glean the memory map from AGESA. (See below.)
fsp_memory_init() brings cbmem online before returning to the caller.

No postcar stage is required or supported.

## AGESA v9 on Picasso

Due to the current inability to publish AGESA source, a pre-built
binary solution remains a requirement. The rewrite from v5 to v9 for
direct inclusion into UEFI source makes modifying it for conforming to
the existing v5 interface impractical.
Due to the current restriction on publishing AGESA source, a pre-built
binary solution remains a requirement. Modifying v9 to conform to the
existing v5 binaryPI interface was considered impractical.

Given the UEFI nature of modern AGESA, and the existing open source
work from Intel, Picasso shall support AGESA via an FSP-like prebuilt
image. The Intel Firmware Support Package<sup>4</sup> combines
image. The Intel Firmware Support Package<sup>5</sup> combines
reference code with EDK II source to create a modular image with
discoverable entry points. coreboot source already contains knowledge
of FSP, how to parse it, integrate it, and how to communicate with it.
Picasso's FSP is compatible with rev. 2.0 of the External Architecture
Specification. Deviations, e.g., no FSP-T support, shall be published
in an Integration Guide.

## Footnotes

1. AMD Platform Security Processor BIOS Architecture Design Guide
for AMD Family 17h Processors (PID #55758) and AMD Platform
Security Processor BIOS Architecture Design Guide (PID #54267) for
1. *AMD Platform Security Processor BIOS Architecture Design Guide
for AMD Family 17h Processors* (PID #55758) and *AMD Platform
Security Processor BIOS Architecture Design Guide* (PID #54267) for
earlier products
2. [https://www.amd.com/system/files/TechDocs/44065_Arch2008.pdf](https://www.amd.com/system/files/TechDocs/44065_Arch2008.pdf)
3. [https://en.wikichip.org/wiki/amd/cores/picasso](https://en.wikichip.org/wiki/amd/cores/picasso)
4. [https://www.intel.com/content/www/us/en/intelligent-systems/intel-firmware-support-package/intel-fsp-overview.html](https://www.intel.com/content/www/us/en/intelligent-systems/intel-firmware-support-package/intel-fsp-overview.html)

2. [PSP Integration](psp_integration.md)
3. [https://www.amd.com/system/files/TechDocs/44065_Arch2008.pdf](https://www.amd.com/system/files/TechDocs/44065_Arch2008.pdf)
4. [https://en.wikichip.org/wiki/amd/cores/picasso](https://en.wikichip.org/wiki/amd/cores/picasso)
5. [https://www.intel.com/content/www/us/en/intelligent-systems/intel-firmware-support-package/intel-fsp-overview.html](https://www.intel.com/content/www/us/en/intelligent-systems/intel-firmware-support-package/intel-fsp-overview.html)
1 change: 1 addition & 0 deletions Documentation/soc/amd/index.md
Expand Up @@ -6,6 +6,7 @@ This section contains documentation about coreboot on specific AMD SOCs.

- [Family 15h](family15h.md)
- [Family 17h](family17h.md)
- [Platform Security Processor Integration](psp_integration.md)

## amd_blobs Repository License

Expand Down
383 changes: 383 additions & 0 deletions Documentation/soc/amd/psp_integration.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Documentation/soc/intel/fit.md
Expand Up @@ -57,4 +57,4 @@ execution of the IA32 reset vector happens.
## References

* [Intel TXT LAB handout](https://downloadmirror.intel.com/18931/eng/Intel%20TXT%20LAB%20Handout.pdf)
* [FIT bios specification](https://www.intel.com/content/dam/www/public/us/en/documents/guides/fit-bios-specification.pdf)
* [FIT BIOS specification](https://www.intel.com/content/dam/www/public/us/en/documents/guides/fit-bios-specification.pdf)
46 changes: 23 additions & 23 deletions Documentation/superio/common/pnp.md
Expand Up @@ -15,13 +15,13 @@ specification is still the main reference though.

Super I/O chips connected via LPC to the southbridge usually have their
I/O-mapped configuration interface with a size of two bytes at the base
address 0x2e or 0x4e. Other PNP devices have their configuration
address `0x2e` or `0x4e`. Other PNP devices have their configuration
interface at other addresses.

The two byte registers allow access to an indirect 256 bytes big
register space that contains the configuration. By writing the index
to the lower byte (e.g. 0x2e), you can access the register contents at
that index by reading/writing the higher byte (e.g. 0x2f).
register space that contains the configuration. By writing the index to
the lower byte (e.g. `0x2e`), you can access the register contents at
that index by reading/writing the higher byte (e.g. `0x2f`).

To prevent accidental changes of the Super I/O (SIO) configuration,
the SIOs need a configuration mode unlock sequence. After changing the
Expand All @@ -31,18 +31,18 @@ the configuration mode lock sequence.
## Logical device numbers (LDN)

Each PNP device can contain multiple logical devices. The bytes from
0x00 to 0x2f in the indirect configuration register space are common
for all LDNs, but some SIO chips require a certain LDN to be selected
in order to write certain registers in there. An LDN gets selected by
writing the LDN number to the LDN select register 0x07. Registers 0x30
to 0xFF are specific to each LDN number.
`0x00` to `0x2f` in the indirect configuration register space are common
for all LDNs, but some SIO chips require a certain LDN to be selected in
order to write certain registers in there. An LDN gets selected by
writing the LDN number to the LDN select register `0x07`. Registers
`0x30` to `0xff` are specific to each LDN number.

coreboot encodes the physical LDN number in the lower byte of the LDN
number.

### Virtual logical device numbers

Register 0x30 is the LDN enable register and since it is an 8 bit
Register `0x30` is the LDN enable register and since it is an 8 bit
register, it can contain up to 8 enable bits for different parts of
the functionality of that logical device. To set a certain enable bit
in one physical LDN, the concept of virtual LDNs was introduced.
Expand All @@ -54,7 +54,7 @@ part in the lower 3 bits of the higher byte of the LDN number.

## I/O resources

Starting at register address 0x60, each LDN has 2 byte wide I/O base
Starting at register address `0x60`, each LDN has 2 byte wide I/O base
address registers. The size of an I/O resource is always a power of
two.

Expand All @@ -67,29 +67,29 @@ number of LSBs being zero, which can also be zero if the LSB is a one,
the resource has N address bits and a size of 2\*\*N bytes. The mask
address is also the highest possible address to map the I/O region.

A typical example for an I/O resource mask is 0x07f8 which is
0b0000011111111000 in binary notation. The three LSBs are zeros here,
A typical example for an I/O resource mask is `0x07f8` which is
`0b0000011111111000` in binary notation. The three LSBs are zeros here,
so it's an eight byte I/O resource with three address offset bits
inside the resource. The highest base address it can be mapped to is
0x07f8, so the region will end at 0x07ff.
`0x07f8`, so the region will end at `0x07ff`.

The Super I/O datasheets typically contain the information about the
I/O resource masks. On most Super I/O chips the mask can also be found
out by writing 0xffff to the corresponding I/O base address register
out by writing `0xffff` to the corresponding I/O base address register
and reading back the value; since the lowest and highest bits are
hard-wired to zero according to the I/O resource size and maximal
possible I/O address, this gives the mask.

## IRQ resources

Each physical LDN has up to two configurable interrupt request
register pairs 0x70, 0x71 and 0x72, 0x73. Each pair can be configured
to use a certain IRQ number. Writing 1 to 15 into the first register
Each physical LDN has up to two configurable interrupt request register
pairs `0x70`, `0x71` and `0x72`, `0x73`. Each pair can be configured to
use a certain IRQ number. Writing 1 to 15 into the first register
selects the IRQ number generated by the corresponding IRQ source and
enables IRQ generation; writing 0 to it disables the generation of
IRQs for the source. The second register selects the IRQ type (level
or edge) and IRQ level (high or low). For LPC SIOs the IRQ type is
hard-wired to edge.
enables IRQ generation; writing 0 to it disables the generation of IRQs
for the source. The second register selects the IRQ type (level or edge)
and IRQ level (high or low). For LPC SIOs the IRQ type is hard-wired to
edge.

On the LPC bus a shared SERIRQ line is used to signal IRQs to the
host; the IRQ number gets encoded by the number of LPC clock cycles
Expand All @@ -106,7 +106,7 @@ number. The quiet mode is often broken.
## DRQ resources

Each physical LDN has two legacy ISA-style DMA request channel
registers at 0x74 and 0x75. Those are only used for legacy devices
registers at `0x74` and `0x75`. Those are only used for legacy devices
like parallel printer ports or floppy disk controllers.

Each device using LPC legacy DMA needs its own LDMA line to the host.
Expand Down
47 changes: 29 additions & 18 deletions Documentation/tutorial/part1.md
@@ -1,14 +1,18 @@
Tutorial, part 1: Starting from scratch
===========================================

From a fresh Ubuntu 16.04 or 18.04 install, here are all the steps required for
a very basic build:
This tutorial will guide you through the process of setting up a working
coreboot toolchain. In same cases you will find specific instructions for Debian (apt-get),
Fedora (dnf) and Arch Linux (pacman) based package management systems. Use the
instructions according to your system.

Download, configure, and build coreboot
---------------------------------------

### Step 1 - Install tools and libraries needed for coreboot
$ sudo apt-get install -y bison build-essential curl flex git gnat libncurses5-dev m4 zlib1g-dev
$ sudo pacman -S base-devel curl git gcc-ada ncurses zlib
$ sudo dnf install git make gcc-gnat flex bison xz bzip2 gcc g++ ncurses-devel wget zlib-devel

### Step 2 - Download coreboot source tree
$ git clone https://review.coreboot.org/coreboot
Expand Down Expand Up @@ -78,6 +82,8 @@ Test the image using QEMU

### Step 7 - Install QEMU
$ sudo apt-get install -y qemu
$ sudo pacman -S qemu
$ sudo dnf install qemu

### Step 8 - Run QEMU
Start QEMU, and point it to the ROM you just built:
Expand All @@ -91,20 +97,24 @@ Summary
-------

### Step 1 summary - Install tools and libraries needed for coreboot
You installed the minimum additional requirements for ubuntu to download and
build coreboot. Ubuntu already has most of the other tools that would be
required installed by default.
Depending on your distribution you have installed the minimum additional
software requirements to continue with downloading and building coreboot.
Not every distribution has the tools, that would be required,
installed by default. In the following we shortly introduce the purpose of the
installed packages:

* `build-essential` is the basic tools for doing builds. It comes pre-installed
on some Ubuntu flavors, and not on others.
* `build-essential` or `base-devel` are the basic tools for building software.
* `git` is needed to download coreboot from the coreboot git repository.
* `libncurses5-dev` is needed to build the menu for 'make menuconfig'
* `libncurses5-dev` or `ncurses` is needed to build the menu for 'make menuconfig'
* `m4, bison, curl, flex, zlib1g-dev, gcc, gnat` and `g++` or `clang`
are needed to build the coreboot toolchain. `gcc` and `gnat` have to be
of the same version.

If you started with a different distribution, you might need to install many
other items which vary by distribution.
If you started with a different distribution or package management system you
might need to install other packages. Most likely they are named sightly
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.

### Step 2 summary - Download coreboot source tree
This will download a 'read-only' copy of the coreboot tree. This just means
Expand All @@ -124,12 +134,12 @@ system during the build process.

### Step 4 summary - Build the payload
To actually do anything useful with coreboot, you need to build a payload to
include in the rom. The idea behind coreboot is that it does the minimum amount
include into the rom. The idea behind coreboot is that it does the minimum amount
possible before passing control of the machine to a payload. There are various
payloads such as grub or SeaBIOS that are typically used to boot the operating
system. Instead, we used coreinfo, a small demonstration payload that allows the
user to look at various things such as memory and the contents of coreboot's
cbfs - the pieces that make up the coreboot rom.
user to look at various things such as memory and the contents of the coreboot
file system (CBFS) - the pieces that make up the coreboot rom.

### Step 5 summary - Configure the build
This step configures coreboot's build options using the menuconfig interface to
Expand All @@ -154,16 +164,17 @@ build directory as 'coreboot.rom'. At the end of the build process, the build
displayed the contents of the rom file.

### Step 7 summary - Install QEMU
QEMU is a processor emulator which we can use to show coreboot
QEMU is a processor emulator which we can use to show the coreboot boot
process in a virtualised environment.

### Step 8 summary - Run QEMU
Here's the command line broken down:
Here's the command line instruction broken down:
* `qemu-system-x86_64`
This starts the QEMU emulator with the i440FX host PCI bridge and PIIX3 PCI to
ISA bridge.
* `-bios build/coreboot.rom`
Use the bios rom image that we just built. If this is left off, the standard
SeaBIOS image that comes with QEMU is used.
Use the coreboot rom image that we just built. If this flag is left out, the
standard SeaBIOS image that comes with QEMU is used.
* `-serial stdio`
Send the serial output to the console. This allows you to view the coreboot
debug output.
boot log.
119 changes: 96 additions & 23 deletions Documentation/vendorcode/eltan/security.md
@@ -1,38 +1,111 @@
# Eltan Security

## Security
This code enables measured boot and verified boot support.
Verified boot is available in coreboot, but based on ChromeOS. This vendorcode
uses a small encryption library and leave much more space in flash for the
payload.
Verified boot is available in coreboot, but based on ChromeOS. This vendorcode security
solution is intended to be used for system without ChromeOS support.

This solution allows implementing verified boot support for systems that do not contain a TPM.

## Hashing Library
The library suppports SHA-1, SHA-256 and SHA-512. The required routines of
`3rdparty/vboot/firmware/2lib` are used.
The API functions of `3rdparty/vboot/firmware` are used.

## Measured boot
measured boot support will use TPM2 device if available. The items specified
in `mb_log_list[]` will be measured.
Measured boot support requires a TPM2 device.

The items specified in `mb_log_list[]` and `*_verify_list[]` will be measured.

The `mb_log_list[]` should only contain items that are not contained in one of the verify_lists
below (except for the `bootblock_verify_list[]`).

The list can contain the following items: `config`, `revision`, `cmos_layout.bin`.
`oemmanifest.bin` should be added to the list when Verified boot is enabled.

## Verified boot
verified boot support will use TPM2 device if available. The items specified
in the next table will be verified:
* `bootblock_verify_list[]`
* `verify_item_t romstage_verify_list[]`
* `ram_stage_additional_list[]`
* `ramstage_verify_list[]`
* `payload_verify_list[]`
* `oprom_verify_list[]`
Verified boot support will use the OEM manifest to verify the items.

The verification process is controlled using the following verify lists:
* `bootblock_verify_list[]` (will not be measured, verified in bootblock)
* `romstage_verify_list[]` (verified in early romstage)
* `postcar_verify_list[]` (verified in just before postcar loading)
* `ramstage_verify_list[]` (verified in just before ramstage loading)
* `payload_verify_list[]` (verified in just before payload loading)
* `oprom_verify_list[]` (verified before option rom execution)

A verify_list entry contains a `related_items` member. This can point to an additional `verify_list`
which will be verified before the specified item is verified. As an example the `grub` entry in
`payload_verify_list[]` can point to the `grub_additional_list[]` that contains the items used by
the grub payload and the `seabios` entry in `payload_verify_list[]` can point to the
`seabios_additional_list[]` that contains the items used by the seabios payload. By doing this the
entries that are verified (and measured) depend on the payload selected at runtime.

## Creating private and public keys
Create private key in RSA2048 format: `openssl genrsa -F4 -out <private_key_file> 2048`

Create public key using private key:
`futility --vb1 create <private_key_file> <public_key_file_without_extension>`

The public key will be included into coreboot and used for verified boot only.

## Enabling support
To enable measured boot support:
* Enabled *VENDORCODE_ELTAN_MBOOT*
* Create `mb_log_list` table with list of items to measure

To enable verified boot support:
* Enable *VENDORCODE_ELTAN_VBOOT*
* Create the verify lists `*_verify_list[]`
* *VENDORCODE_ELTAN_VBOOT_KEY_FILE* must point to location of the public key file created with `futility`

## Creating signed binary

During build of coreboot binary an empty `oemmanifest.bin` is added to the binary.

This binary must be replaced by a correct (signed) binary when *VENDORCODE_ELTAN_VBOOT* is enabled

The `oemmanifest.bin` file contains the SHA-256 (or SHA-512) hashes of all the different parts
contained in verify_lists.

When *VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST* is enabled the manifest should be signed and the
signature should appended to the manifest.

Please make sure the public key is in the RO part of the coreboot image. The `oemmanifest.bin` file
should be in the RW part of the coreboot image.

### Hashing

The `oemmanifest.bin` file contains the hashes of different binaries parts of the binary e.g.:
bootblock, romstage, postcar, ramstage, fsp etc.

The total number of items must match `VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS`.

For every part the SHA (SHA-256) must be calculated. First extract the binary from the coreboot
image using: `cbfstool <coreboot_file_name> extract -n <cbfs_name> -f <item_binary_file_name>`
followed by: `openssl dgst -sha256 -binary -out <hash_file_name> <item_binary_file_name>`

Replace -sha256 with -sha512 when `VENDORCODE_ELTAN_VBOOT_USE_SHA512` is enabled.

All the hashes must be combined to a hash binary. The hashes need to be placed in the same order as
defined by the `HASH_IDX_XXX` values.

### Signing

The oemmanifest needs to be signed when `VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST` is enabled.

This can be done with the following command:
`openssl dgst -sign <private_key_file_name> -sha256 -out <signature_binary> <hash_binary>`

The signed manifest can be created by adding the signature to the manifest:
`cat <hash_binary> <signature_binary> >hash_table.bin`

## Create binary
The `oemmanifest.bin` file must be replaced in the coreboot binary by the generated
`hash_table.bin`.

* Measured boot can be enabled using **CONFIG_MBOOT**
* Create mb_log_list table with list of item to measure
* Create tables bootblock_verify_list[], verify_item_t romstage_verify_list[],
ram_stage_additional_list[], ramstage_verify_list[], payload_verify_list[],
oprom_verify_list[]
* Verified boot can be enabled using **CONFIG_VERIFIED_BOOT**
* Added Kconfig values for verbose console output
To replace the binary: Remove using:
`cbfstool <coreboot_file_name> remove -n oemmanifest.bin`
Then add the new image using:
`cbfstool coreboot.bin add -f <hash_table_file_name> -n oemmanifest.bin -t raw \`
`-b <CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC>`

## Debugging

Expand Down
19 changes: 14 additions & 5 deletions Makefile.inc
Expand Up @@ -159,7 +159,7 @@ ws_to_under=$(shell echo '$1' | tr ' \t' '_')
#######################################################################
# Helper functions for ramstage postprocess
spc :=
spc +=
spc := $(spc) $(spc)
comma := ,

# Returns all files and dirs below `dir` (recursively).
Expand Down Expand Up @@ -261,7 +261,16 @@ EMPTY_RESOURCE_TEMPLATE_WARNING = 3150
# Redundant offset remarks are not useful in any way and are masking useful
# ones that might indicate an issue so it is better to hide them.
REDUNDANT_OFFSET_REMARK = 2158
# Ignore _HID & _ADR coexisting in Intel Lynxpoint and Broadwell ASL code.
# See cb:38803 & cb:38802
# "Multiple types (Device object requires either a _HID or _ADR, but not both)"
MULTIPLE_TYPES_WARNING = 3073

ifeq ($(CONFIG_SOUTHBRIDGE_INTEL_LYNXPOINT)$(CONFIG_SOC_INTEL_BROADWELL),y)
IGNORED_IASL_WARNINGS = -vw $(EMPTY_RESOURCE_TEMPLATE_WARNING) -vw $(REDUNDANT_OFFSET_REMARK) -vw $(MULTIPLE_TYPES_WARNING)
else
IGNORED_IASL_WARNINGS = -vw $(EMPTY_RESOURCE_TEMPLATE_WARNING) -vw $(REDUNDANT_OFFSET_REMARK)
endif

define asl_template
$(CONFIG_CBFS_PREFIX)/$(1).aml-file = $(obj)/$(1).aml
Expand All @@ -284,7 +293,7 @@ $(obj)/$(1).aml: $(src)/mainboard/$(MAINBOARDDIR)/$(1).asl $(obj)/config.h
endef

#######################################################################
# Parse plaintext cmos defaults into binary format
# Parse plaintext CMOS defaults into binary format
# arg1: source file
# arg2: binary file name
cbfs-files-processor-nvramtool= \
Expand All @@ -307,15 +316,16 @@ cbfs-files-processor-vsa= \
# Reduce a .config file to its minimal representation
# arg1: input
# arg2: output
cbfs-files-processor-defconfig= \
define cbfs-files-processor-defconfig
$(eval $(2): $(1) $(obj)/build.h $(objutil)/kconfig/conf; \
+printf " CREATE $(2) (from $(1))\n"; \
printf "\# This image was built using coreboot " > $(2).tmp && \
printf "# This image was built using coreboot " > $(2).tmp && \
grep "\<COREBOOT_VERSION\>" $(obj)/build.h |cut -d\" -f2 >> $(2).tmp && \
$(MAKE) DOTCONFIG=$(1) DEFCONFIG=$(2).tmp2 savedefconfig && \
cat $(2).tmp2 >> $(2).tmp && \
rm -f $(2).tmp2 && \
\mv -f $(2).tmp $(2))
endef

#######################################################################
# Compile a C file with a bare struct definition into binary
Expand Down Expand Up @@ -414,7 +424,6 @@ CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits -Wvla
CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
ifeq ($(CONFIG_COMPILER_GCC),y)
CFLAGS_common += -fno-delete-null-pointer-checks
# Don't add these GCC specific flags when running scan-build
ifeq ($(CCC_ANALYZER_OUTPUT_FORMAT),)
CFLAGS_common += -Wno-packed-not-aligned
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.3"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_NO_GFX_INIT=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.3"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU2=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu2_vboot
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.1"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_VBOOT=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.3"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU3=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu4
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.3"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU4=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.11.0.3"
CONFIG_LOCALVERSION="v4.11.0.4"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
Expand Down
4 changes: 4 additions & 0 deletions configs/config.stm
@@ -0,0 +1,4 @@
CONFIG_VENDOR_PURISM=y
CONFIG_BOARD_PURISM_LIBREM15_V4=y
CONFIG_STM=y
CONFIG_IED_REGION_SIZE=0
8 changes: 7 additions & 1 deletion payloads/Kconfig
Expand Up @@ -57,10 +57,16 @@ config PAYLOAD_FILE
choice
prompt "Payload compression algorithm"
default COMPRESSED_PAYLOAD_LZMA
default COMPRESSED_PAYLOAD_NONE if PAYLOAD_LINUX || PAYLOAD_LINUXBOOT || PAYLOAD_FIT
depends on !PAYLOAD_NONE && !PAYLOAD_LINUX && !PAYLOAD_LINUXBOOT && !PAYLOAD_FIT
help
Choose the compression algorithm for the chosen payloads.
You can choose between LZMA and LZ4.
You can choose between None, LZMA, or LZ4.

config COMPRESSED_PAYLOAD_NONE
bool "Use no compression for payloads"
help
Do not compress the payload.

config COMPRESSED_PAYLOAD_LZMA
bool "Use LZMA compression for payloads"
Expand Down
5 changes: 4 additions & 1 deletion payloads/coreinfo/coreinfo.c
Expand Up @@ -290,8 +290,11 @@ static void loop(void)
}
}

int main(void)
int main(int argc, char **argv)
{
(void)argc;
(void)argv;

int j;

if (CONFIG(LP_USB))
Expand Down
2 changes: 1 addition & 1 deletion payloads/coreinfo/cpuinfo_module.c
Expand Up @@ -233,7 +233,7 @@ static int cpuinfo_module_redraw(WINDOW *win)
}

if (cpu_khz != 0)
mvwprintw(win, row++, 1, "CPU Speed: %d Mhz", cpu_khz / 1000);
mvwprintw(win, row++, 1, "CPU Speed: %d MHz", cpu_khz / 1000);
else
mvwprintw(win, row++, 1, "CPU Speed: Error");

Expand Down
4 changes: 3 additions & 1 deletion payloads/external/SeaBIOS/Kconfig
Expand Up @@ -88,12 +88,14 @@ config SEABIOS_BOOTORDER_FILE

config SEABIOS_BOOTORDER_MAP_FILE
string "SeaBIOS bootorder_map file"
default "$(top)/src/mainboard/$(MAINBOARDDIR)/bootorder_map_apu5" if BOARD_PCENGINES_APU5
default "$(top)/src/mainboard/$(MAINBOARDDIR)/bootorder_map"
help
Determine mapping of keystrokes to group of positions in bootorder

config SEABIOS_BOOTORDER_DEF_FILE
string "SeaBIOS bootorder_def file"
default "$(top)/src/mainboard/$(MAINBOARDDIR)/bootorder_def_apu5" if BOARD_PCENGINES_APU5
default "$(top)/src/mainboard/$(MAINBOARDDIR)/bootorder_def"
help
Determine default boot order and default values for runtime config
Expand Down Expand Up @@ -172,7 +174,7 @@ config SEABIOS_DEBUG_LEVEL
level 1 - Basic output, interrupts 5, 18h, 19h, 40h, SMP, PNP, PMM
level 2 - AHCI, Floppy, Basic ps2, interrupts 11h, 12h, 14h, 17h
level 3 - bootsplash, initializations, SeaBIOS VGA BIOS interrupts
level 4 - bios tables, more optionrom
level 4 - BIOS tables, more optionrom
level 5 - Extra bootsplash, more XHCI
level 6 - ATA commands, extra optionrom
level 7 - extra ps2 commands, more OHCI & EHCI
Expand Down
15 changes: 15 additions & 0 deletions payloads/libpayload/arch/arm64/cpu.S
Expand Up @@ -29,6 +29,7 @@
*/

#include <arch/asm.h>
#include <arch/lib_helpers.h>

.macro dcache_apply_all crm
dsb sy
Expand Down Expand Up @@ -96,3 +97,17 @@ ENDPROC(dcache_clean_all)
ENTRY(dcache_clean_invalidate_all)
dcache_apply_all crm=cisw
ENDPROC(dcache_clean_invalidate_all)

/* This must be implemented in assembly to ensure there are no accesses to
memory (e.g. the stack) in between disabling and flushing the cache. */
ENTRY(mmu_disable)
str x30, [sp, #-0x8]
mrs x0, sctlr_el2
mov x1, #~(SCTLR_C | SCTLR_M)
and x0, x0, x1
msr sctlr_el2, x0
isb
bl dcache_clean_invalidate_all
ldr x30, [sp, #-0x8]
ret
ENDPROC(mmu_disable)
4 changes: 4 additions & 0 deletions payloads/libpayload/arch/arm64/head.S
Expand Up @@ -28,11 +28,15 @@
*/

#include <arch/asm.h>
#include <arch/lib_helpers.h>

/*
* Our entry point
*/
ENTRY(_entry)
/* Initialize SCTLR to intended state (icache and stack-alignment on) */
ldr w1, =(SCTLR_RES1 | SCTLR_I | SCTLR_SA)
msr sctlr_el2, x1

/* Save off the location of the coreboot tables */
ldr x1, 1f
Expand Down
24 changes: 0 additions & 24 deletions payloads/libpayload/arch/arm64/mmu.c
Expand Up @@ -303,30 +303,6 @@ static uint32_t is_mmu_enabled(void)
return (sctlr & SCTLR_M);
}

/*
* Func: mmu_disable
* Desc: Invalidate caches and disable mmu
*/
void mmu_disable(void)
{
uint32_t sctlr;

sctlr = raw_read_sctlr_el2();
sctlr &= ~(SCTLR_C | SCTLR_M | SCTLR_I);

tlbiall_el2();
dcache_clean_invalidate_all();

dsb();
isb();

raw_write_sctlr_el2(sctlr);

dcache_clean_invalidate_all();
dsb();
isb();
}

/*
* Func: mmu_enable
* Desc: Initialize MAIR, TCR, TTBR and enable MMU by setting appropriate bits
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/i8042/keyboard.c
Expand Up @@ -349,7 +349,7 @@ static int set_scancode_set(void)

/*
* Set default parameters.
* Fix for broken QEMU ps/2 make scancodes.
* Fix for broken QEMU PS/2 make scancodes.
*/
ret = keyboard_cmd(I8042_KBCMD_SET_DEFAULT);
if (!ret) {
Expand Down
8 changes: 4 additions & 4 deletions payloads/libpayload/drivers/options.c
Expand Up @@ -157,7 +157,7 @@ static struct cb_cmos_entries *lookup_cmos_entry(struct cb_cmos_option_table *op
struct cb_cmos_entries *cmos_entry;
int len = name ? strnlen(name, CB_CMOS_MAX_NAME_LENGTH) : 0;

/* cmos entries are located right after the option table */
/* CMOS entries are located right after the option table */
cmos_entry = first_cmos_entry(option_table);
while (cmos_entry) {
if (memcmp((const char*)cmos_entry->name, name, len) == 0)
Expand Down Expand Up @@ -186,12 +186,12 @@ struct cb_cmos_entries *next_cmos_entry(struct cb_cmos_entries *cmos_entry)
struct cb_cmos_enums *first_cmos_enum(struct cb_cmos_option_table *option_table)
{
struct cb_cmos_entries *cmos_entry;
/* cmos entries are located right after the option table. Skip them */
/* CMOS entries are located right after the option table. Skip them */
cmos_entry = (struct cb_cmos_entries *)((unsigned char *)option_table + option_table->header_length);
while (cmos_entry->tag == CB_TAG_OPTION)
cmos_entry = (struct cb_cmos_entries*)((unsigned char *)cmos_entry + cmos_entry->size);

/* cmos enums are located after cmos entries. */
/* CMOS enums are located after CMOS entries. */
return (struct cb_cmos_enums *)cmos_entry;
}

Expand Down Expand Up @@ -237,7 +237,7 @@ static struct cb_cmos_enums *lookup_cmos_enum_core(struct cb_cmos_option_table *
{
int len = strnlen(text, CB_CMOS_MAX_TEXT_LENGTH);

/* cmos enums are located after cmos entries. */
/* CMOS enums are located after CMOS entries. */
struct cb_cmos_enums *cmos_enum;
for ( cmos_enum = first_cmos_enum_of_id(option_table, config_id);
cmos_enum;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/ipq40xx.c
Expand Up @@ -442,7 +442,7 @@ static unsigned int msm_boot_uart_dm_reset(void *base)
}

/*
* msm_boot_uart_dm_init - initilaizes UART controller
* msm_boot_uart_dm_init - Initializes UART controller
* @uart_dm_base: UART controller base address
*/
unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Expand Down Expand Up @@ -550,7 +550,7 @@ int serial_getchar(void)
static struct console_input_driver consin = {};
static struct console_output_driver consout = {};

/* For simplicity sake let's rely on coreboot initalizing the UART. */
/* 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;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/ipq806x.c
Expand Up @@ -235,7 +235,7 @@ static unsigned int msm_boot_uart_dm_reset(void *base)
}

/*
* msm_boot_uart_dm_init - initilaizes UART controller
* msm_boot_uart_dm_init - Initializes UART controller
* @uart_dm_base: UART controller base address
*/
static unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Expand Down Expand Up @@ -340,7 +340,7 @@ int serial_getchar(void)
return byte;
}

/* For simplicity sake let's rely on coreboot initalizing the UART. */
/* 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;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/serial/qcs405.c
Expand Up @@ -434,7 +434,7 @@ static unsigned int msm_boot_uart_dm_reset(void *base)
}

/*
* msm_boot_uart_dm_init - initilaizes UART controller
* msm_boot_uart_dm_init - Initializes UART controller
* @uart_dm_base: UART controller base address
*/
unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Expand Down Expand Up @@ -538,7 +538,7 @@ int serial_getchar(void)
return byte;
}

/* For simplicity sake let's rely on coreboot initalizing the UART. */
/* 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;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/udc/dwc2.c
Expand Up @@ -253,7 +253,7 @@ static void dwc2_halt_ep(struct usbdev_ctrl *this, int ep, int in_dir)

usb_debug("dwc2_halt_ep ep %d-%d\n", ep, in_dir);
depctl.d32 = readl(&ep_reg->depctl);
/*Alread disabled*/
/* Already disabled */
if (!depctl.epena)
return;
/* First step: disable EP */
Expand Down Expand Up @@ -558,7 +558,7 @@ static void dwc2_outep_intr(struct usbdev_ctrl *this, dwc2_ep_t *ep)
writel(DXEPINT_AHBERR, &ep->ep_regs->depint);
}

/* Handle Setup Phase Done (Contorl Ep) */
/* Handle Setup Phase Done (Control Ep) */
if (depint.setup) {
usb_debug("DEPINT_SETUP\n");
writel(DXEPINT_SETUP, &ep->ep_regs->depint);
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/usb/dwc2.c
Expand Up @@ -233,7 +233,7 @@ dwc2_do_xfer(endpoint_t *ep, int size, int pid, ep_dir_t dir,
packet_size = ep->maxpacketsize;
packet_cnt = ALIGN_UP(size, packet_size) / packet_size;
inpkt_length = packet_cnt * packet_size;
/* At least 1 packet should be programed */
/* At least 1 packet should be programmed */
packet_cnt = (packet_cnt == 0) ? 1 : packet_cnt;

/*
Expand Down
6 changes: 3 additions & 3 deletions payloads/libpayload/drivers/usb/ehci.c
Expand Up @@ -78,7 +78,7 @@ static void dump_qh(ehci_qh_t *cur)
usb_debug("+===================================================+\n");
usb_debug("| ############# EHCI QH at [0x%08lx] ########### |\n", virt_to_phys(cur));
usb_debug("+---------------------------------------------------+\n");
usb_debug("| Horizonal Link Pointer [0x%08lx] |\n", cur->horiz_link_ptr);
usb_debug("| Horizontal Link Pointer [0x%08lx] |\n", cur->horiz_link_ptr);
usb_debug("+------------------[ 0x%08lx ]-------------------+\n", cur->epchar);
usb_debug("| | Maximum Packet Length | [%04ld] |\n", ((cur->epchar & (0x7ffUL << 16)) >> 16));
usb_debug("| | Device Address | [%ld] |\n", cur->epchar & 0x7F);
Expand Down Expand Up @@ -133,7 +133,7 @@ static void ehci_reset (hci_t *controller)
{
short count = 0;
ehci_stop(controller);
/* wait 10 ms just to be shure */
/* wait 10 ms just to be sure */
mdelay(10);
if (EHCI_INST(controller)->operation->usbsts & HC_OP_HC_HALTED) {
EHCI_INST(controller)->operation->usbcmd = HC_OP_HC_RESET;
Expand Down Expand Up @@ -215,7 +215,7 @@ static int fill_td(qtd_t *td, void* data, int datalen)
total_len += page_len;

while (page_no < 5) {
/* we have a continguous mapping between virtual and physical memory */
/* we have a contiguous mapping between virtual and physical memory */
page += 4096;

td->bufptrs[page_no++] = page;
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/usb/ohci.c
Expand Up @@ -66,7 +66,7 @@ dump_td (td_t *cur)
usb_debug("|:| C | Condition Code | [%02ld] |:|\n", (cur->config & (0xFUL << 28)) >> 28);
usb_debug("|:| O | Direction/PID | [%ld] |:|\n", (cur->config & (3UL << 19)) >> 19);
usb_debug("|:| N | Buffer Rounding | [%ld] |:|\n", (cur->config & (1UL << 18)) >> 18);
usb_debug("|:| F | Delay Intterrupt | [%ld] |:|\n", (cur->config & (7UL << 21)) >> 21);
usb_debug("|:| F | Delay Interrupt | [%ld] |:|\n", (cur->config & (7UL << 21)) >> 21);
usb_debug("|:| I | Data Toggle | [%ld] |:|\n", (cur->config & (3UL << 24)) >> 24);
usb_debug("|:| G | Error Count | [%ld] |:|\n", (cur->config & (3UL << 26)) >> 26);
usb_debug("|:+-----------------------------------------------+:|\n");
Expand Down Expand Up @@ -879,7 +879,7 @@ ohci_process_done_queue(ohci_t *const ohci, const int spew_debug)
intrq_td_t *const td = INTRQ_TD_FROM_TD(done_td);
intr_queue_t *const intrq = td->intrq;
/* Check if the corresponding interrupt
queue is still beeing processed. */
queue is still being processed. */
if (intrq->destroy) {
/* Free this TD, and */
free(td);
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/usb/usb.c
Expand Up @@ -499,7 +499,7 @@ set_address (hci_t *controller, usb_speed speed, int hubport, int hubaddr)
break;
}

/* Gather up all endpoints belonging to this inteface */
/* Gather up all endpoints belonging to this interface */
dev->num_endp = 1;
for (; ptr + 2 <= end && ptr[0] && ptr + ptr[0] <= end; ptr += ptr[0]) {
if (ptr[1] == DT_INTF || ptr[1] == DT_CFG ||
Expand Down Expand Up @@ -654,7 +654,7 @@ usb_detach_device(hci_t *controller, int devno)
controller->devices[devno]->configuration = NULL;

/* Tear down the device itself *after* destroy_device()
* has had a chance to interoogate it. */
* has had a chance to interrogate it. */
free(controller->devices[devno]);
controller->devices[devno] = NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/usb/usbhub.c
Expand Up @@ -285,7 +285,7 @@ usb_hub_init(usbdev_t *const dev)
return;
}

/* Get number of ports from hub decriptor */
/* Get number of ports from hub descriptor */
int type = is_usb_speed_ss(dev->speed) ? 0x2a : 0x29; /* similar enough */
hub_descriptor_t desc; /* won't fit the whole thing, we don't care */
if (get_descriptor(dev, gen_bmRequestType(device_to_host, class_type,
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/drivers/usb/usbmsc.c
Expand Up @@ -538,7 +538,7 @@ usb_msc_test_unit_ready (usbdev_t *dev)
time_t start_time_secs;
struct timeval tv;
/* SCSI/ATA specs say we have to wait up to 30s, but most devices
* are ready much sooner. Use a 5 sec timeout to better accomodate
* are ready much sooner. Use a 5 sec timeout to better accommodate
* devices which fail to respond. */
const int timeout_secs = 5;

Expand Down Expand Up @@ -569,7 +569,7 @@ usb_msc_test_unit_ready (usbdev_t *dev)
MSC_INST (dev)->ready = USB_MSC_NOT_READY;
}

/* Don't bother spinning up the stroage device if the device is not
/* Don't bother spinning up the storage device if the device is not
* ready. This can happen when empty card readers are present.
* Polling will pick it back up if readiness changes. */
if (!MSC_INST (dev)->ready)
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/usb/xhci_devconf.c
Expand Up @@ -227,7 +227,7 @@ xhci_set_address (hci_t *controller, usb_speed speed, int hubport, int hubaddr)
}

dev->endpoints[0].maxpacketsize = usb_decode_mps0(speed, buf[7]);
if (dev->endpoints[0].maxpacketsize != 8) {
if (dev->endpoints[0].maxpacketsize != speed_to_default_mps(speed)) {
memset((void *)ic->dev.ep0, 0x00, ctxsize);
*ic->add = (1 << 1); /* EP0 Context */
EC_SET(MPS, ic->dev.ep0, dev->endpoints[0].maxpacketsize);
Expand Down
11 changes: 6 additions & 5 deletions payloads/libpayload/drivers/video/corebootfb.c
Expand Up @@ -64,11 +64,11 @@ static const u32 vga_colors[] = {
/* Addresses for the various components */
static unsigned long fbinfo;
static unsigned long fbaddr;
static unsigned long chars;
static unsigned short *chars;

#define FI ((struct cb_framebuffer *) phys_to_virt(fbinfo))
#define FB ((unsigned char *) phys_to_virt(fbaddr))
#define CHARS ((unsigned short *) phys_to_virt(chars))
#define CHARS (chars)

static void corebootfb_scroll_up(void)
{
Expand Down Expand Up @@ -243,9 +243,10 @@ static int corebootfb_init(void)
coreboot_video_console.columns = FI->x_resolution / font_width;
coreboot_video_console.rows = FI->y_resolution / font_height;

/* See setting of fbinfo above. */
chars = virt_to_phys(malloc(coreboot_video_console.rows *
coreboot_video_console.columns * 2));
chars = malloc(coreboot_video_console.rows *
coreboot_video_console.columns * 2);
if (!chars)
return -1;

// clear boot splash screen if there is one.
corebootfb_clear();
Expand Down
8 changes: 4 additions & 4 deletions payloads/libpayload/drivers/video/graphics.c
Expand Up @@ -349,16 +349,16 @@ int draw_rounded_box(const struct scale *pos_rel, const struct scale *dim_rel,
/* Use 64 bits to avoid overflow */
int32_t x, y;
uint64_t yy;
const uint64_t rrx = r.x * r.x, rry = r.y * r.y;
const uint64_t ssx = s.x * s.x, ssy = s.y * s.y;
const uint64_t rrx = (uint64_t)r.x * r.x, rry = (uint64_t)r.y * r.y;
const uint64_t ssx = (uint64_t)s.x * s.x, ssy = (uint64_t)s.y * s.y;
x_begin = 0;
x_end = 0;
for (y = r.y - 1; y >= 0; y--) {
/*
* The inequality is valid in the beginning of each iteration:
* y^2 + x_end^2 < r^2
*/
yy = y * y;
yy = (uint64_t)y * y;
/* Check yy/ssy + xx/ssx < 1 */
while (yy * ssx + x_begin * x_begin * ssy < ssx * ssy)
x_begin++;
Expand Down Expand Up @@ -509,7 +509,7 @@ static int draw_bitmap_v3(const struct vector *top_left,
* When d hits the right bottom corner, s0 also hits the right bottom
* corner of the pixel array because that's how scale->x and scale->y
* have been set. Since the pixel array size is already validated in
* parse_bitmap_header_v3, s0 is guranteed not to exceed pixel array
* parse_bitmap_header_v3, s0 is guaranteed not to exceed pixel array
* boundary.
*/
struct vector s0, s1, d;
Expand Down
32 changes: 0 additions & 32 deletions payloads/libpayload/include/arm64/arch/cache.h
Expand Up @@ -35,38 +35,6 @@
#include <stddef.h>
#include <stdint.h>

/* SCTLR bits */
#define SCTLR_M (1 << 0) /* MMU enable */
#define SCTLR_A (1 << 1) /* Alignment check enable */
#define SCTLR_C (1 << 2) /* Data/unified cache enable */
/* Bits 4:3 are reserved */
#define SCTLR_CP15BEN (1 << 5) /* CP15 barrier enable */
/* Bit 6 is reserved */
#define SCTLR_B (1 << 7) /* Endianness */
/* Bits 9:8 */
#define SCTLR_SW (1 << 10) /* SWP and SWPB enable */
#define SCTLR_Z (1 << 11) /* Branch prediction enable */
#define SCTLR_I (1 << 12) /* Instruction cache enable */
#define SCTLR_V (1 << 13) /* Low/high exception vectors */
#define SCTLR_RR (1 << 14) /* Round Robin select */
/* Bits 16:15 are reserved */
#define SCTLR_HA (1 << 17) /* Hardware Access flag enable */
/* Bit 18 is reserved */
/* Bits 20:19 reserved virtualization not supported */
#define SCTLR_WXN (1 << 19) /* Write permission implies XN */
#define SCTLR_UWXN (1 << 20) /* Unprivileged write permission
implies PL1 XN */
#define SCTLR_FI (1 << 21) /* Fast interrupt config enable */
#define SCTLR_U (1 << 22) /* Unaligned access behavior */
#define SCTLR_VE (1 << 24) /* Interrupt vectors enable */
#define SCTLR_EE (1 << 25) /* Exception endianness */
/* Bit 26 is reserved */
#define SCTLR_NMFI (1 << 27) /* Non-maskable FIQ support */
#define SCTLR_TRE (1 << 28) /* TEX remap enable */
#define SCTLR_AFE (1 << 29) /* Access flag enable */
#define SCTLR_TE (1 << 30) /* Thumb exception enable */
/* Bit 31 is reserved */

/*
* Cache maintenance API
*/
Expand Down
20 changes: 20 additions & 0 deletions payloads/libpayload/include/arm64/arch/lib_helpers.h
Expand Up @@ -30,11 +30,29 @@
#ifndef __ARCH_LIB_HELPERS_H__
#define __ARCH_LIB_HELPERS_H__

#define SCTLR_M (1 << 0) /* MMU enable */
#define SCTLR_A (1 << 1) /* Alignment check enable */
#define SCTLR_C (1 << 2) /* Data/unified cache enable */
#define SCTLR_SA (1 << 3) /* Stack alignment check enable */
#define SCTLR_NAA (1 << 6) /* non-aligned access STA/LDR */
#define SCTLR_I (1 << 12) /* Instruction cache enable */
#define SCTLR_ENDB (1 << 13) /* Pointer auth (data B) */
#define SCTLR_WXN (1 << 19) /* Write permission implies XN */
#define SCTLR_IESB (1 << 21) /* Implicit error sync event */
#define SCTLR_EE (1 << 25) /* Exception endianness (BE) */
#define SCTLR_ENDA (1 << 27) /* Pointer auth (data A) */
#define SCTLR_ENIB (1 << 30) /* Pointer auth (insn B) */
#define SCTLR_ENIA (1 << 31) /* Pointer auth (insn A) */
#define SCTLR_RES1 ((0x3 << 4) | (0x1 << 11) | (0x1 << 16) | \
(0x1 << 18) | (0x3 << 22) | (0x3 << 28))

#define DAIF_DBG_BIT (1 << 3)
#define DAIF_ABT_BIT (1 << 2)
#define DAIF_IRQ_BIT (1 << 1)
#define DAIF_FIQ_BIT (1 << 0)

#ifndef __ASSEMBLER__

#include <stdint.h>

#define MAKE_REGISTER_ACCESSORS(reg) \
Expand Down Expand Up @@ -273,4 +291,6 @@ static inline void tlbivaa_el1(uint64_t va)
#define dsb() dsb_opt(sy)
#define isb() isb_opt()

#endif /* __ASSEMBLER__ */

#endif /* __ARCH_LIB_HELPERS_H__ */
10 changes: 6 additions & 4 deletions payloads/libpayload/include/endian.h
Expand Up @@ -86,28 +86,30 @@ static inline uint16_t be16dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;

return ((p[0] << 8) | p[1]);
return (uint16_t)((p[0] << 8) | p[1]);
}

static inline uint32_t be32dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;

return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
return (((uint32_t)p[0] << 24) | (uint32_t)(p[1] << 16) |
(uint32_t)(p[2] << 8) | p[3]);
}

static inline uint16_t le16dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;

return ((p[1] << 8) | p[0]);
return (uint16_t)((p[1] << 8) | p[0]);
}

static inline uint32_t le32dec(const void *pp)
{
uint8_t const *p = (uint8_t const *)pp;

return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
return ((uint32_t)(p[3] << 24) | (uint32_t)(p[2] << 16) |
(uint32_t)(p[1] << 8) | p[0]);
}

static inline void bebitenc(void *pp, uint32_t u, uint8_t b)
Expand Down
8 changes: 4 additions & 4 deletions payloads/libpayload/include/pci.h
Expand Up @@ -91,11 +91,11 @@ typedef u32 pcidev_t;
#define HEADER_TYPE_CARDBUS 2
#define HEADER_TYPE_MULTIFUNCTION 0x80

#define PCI_ADDR(_bus, _dev, _fn, _reg) \
(0x80000000 | (_bus << 16) | (_dev << 11) | (_fn << 8) | (_reg & ~3))
#define PCI_DEV(_bus, _dev, _fn) (0x80000000 | \
(uint32_t)(_bus << 16) | (uint32_t)(_dev << 11) | (uint32_t)(_fn << 8))

#define PCI_DEV(_bus, _dev, _fn) \
(0x80000000 | (_bus << 16) | (_dev << 11) | (_fn << 8))
#define PCI_ADDR(_bus, _dev, _fn, _reg) \
(PCI_DEV(_bus, _dev, _fn) | (uint8_t)(_reg & ~3))

#define PCI_BUS(_d) ((_d >> 16) & 0xff)
#define PCI_SLOT(_d) ((_d >> 11) & 0x1f)
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/libc/args.c
Expand Up @@ -52,7 +52,7 @@ int string_argc;
*
* @param caller to be used as argv[0] (may be NULL to ignore)
* @param string to process
* @return 0 if no error occured.
* @return 0 if no error occurred.
*/
int string_to_args(char *caller, char *string)
{
Expand All @@ -66,7 +66,7 @@ int string_to_args(char *caller, char *string)

/* Terminate if the string ends */
while (string && *string) {
/* whitespace occured? */
/* whitespace occurred? */
if ((*string == ' ') || (*string == '\t')) {
/* skip all whitespace (and null it) */
while (*string == ' ' || *string == '\t')
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/libc/malloc.c
Expand Up @@ -318,7 +318,7 @@ void *realloc(void *ptr, size_t size)

struct align_region_t
{
/* If alignment is 0 then the region reqpresents a large region which
/* If alignment is 0 then the region represents a large region which
* has no metadata for tracking subelements. */
int alignment;
/* start in memory, and size in bytes */
Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/libc/readline.c
Expand Up @@ -129,7 +129,7 @@ char *readline(const char *prompt)
if (ch < 0x20)
break;

/* ignore unprintables */
/* ignore unprintable characters */
if (ch >= 0x7f)
break;

Expand Down
6 changes: 3 additions & 3 deletions payloads/libpayload/libc/string.c
Expand Up @@ -268,7 +268,7 @@ size_t strlcat(char *d, const char *s, size_t n)
*
* @param s The string.
* @param c The character.
* @return A pointer to the first occurence of the character in the
* @return A pointer to the first occurrence of the character in the
* string, or NULL if the character was not encountered within the string.
*/
char *strchr(const char *s, int c)
Expand All @@ -288,7 +288,7 @@ char *strchr(const char *s, int c)
*
* @param s The string.
* @param c The character.
* @return A pointer to the last occurence of the character in the
* @return A pointer to the last occurrence of the character in the
* string, or NULL if the character was not encountered within the string.
*/

Expand Down Expand Up @@ -327,7 +327,7 @@ char *strdup(const char *s)
*
* @param h The haystack string.
* @param n The needle string (substring).
* @return A pointer to the first occurence of the substring in
* @return A pointer to the first occurrence of the substring in
* the string, or NULL if the substring was not encountered within the string.
*/
char *strstr(const char *h, const char *n)
Expand Down
5 changes: 5 additions & 0 deletions payloads/libpayload/liblzma/lzma.c
Expand Up @@ -28,6 +28,11 @@ unsigned long ulzman(const unsigned char *src, unsigned long srcn,
SizeT mallocneeds;
unsigned char *scratchpad;

if (srcn < data_offset) {
printf("lzma: Input too small.\n");
return 0;
}

memcpy(properties, src, LZMA_PROPERTIES_SIZE);
memcpy(&outSize, src + LZMA_PROPERTIES_SIZE, sizeof(outSize));
if (outSize > dstn)
Expand Down
40 changes: 20 additions & 20 deletions payloads/libpayload/libpci/libpci.c
Expand Up @@ -40,34 +40,34 @@ static pcidev_t libpci_to_lb(struct pci_dev *dev)
/* libpci interface */
u8 pci_read_byte(struct pci_dev *dev, int pos)
{
return pci_read_config8(libpci_to_lb(dev), pos);
return pci_read_config8(libpci_to_lb(dev), (uint16_t)pos);
}

u16 pci_read_word(struct pci_dev *dev, int pos)
{
return pci_read_config16(libpci_to_lb(dev), pos);
return pci_read_config16(libpci_to_lb(dev), (uint16_t)pos);
}

u32 pci_read_long(struct pci_dev *dev, int pos)
{
return pci_read_config32(libpci_to_lb(dev), pos);
return pci_read_config32(libpci_to_lb(dev), (uint16_t)pos);
}

int pci_write_byte(struct pci_dev *dev, int pos, u8 data)
{
pci_write_config8(libpci_to_lb(dev), pos, data);
pci_write_config8(libpci_to_lb(dev), (uint16_t)pos, data);
return 1; /* success */
}

int pci_write_word(struct pci_dev *dev, int pos, u16 data)
{
pci_write_config16(libpci_to_lb(dev), pos, data);
pci_write_config16(libpci_to_lb(dev), (uint16_t)pos, data);
return 1; /* success */
}

int pci_write_long(struct pci_dev *dev, int pos, u32 data)
{
pci_write_config32(libpci_to_lb(dev), pos, data);
pci_write_config32(libpci_to_lb(dev), (uint16_t)pos, data);
return 1; /* success */
}

Expand Down Expand Up @@ -110,29 +110,29 @@ char *pci_filter_parse_slot(struct pci_filter* filter, const char* id)

char *funcp = strrchr(id, '.');
if (funcp) {
filter->func = strtoul(funcp+1, &endptr, 0);
filter->func = strtol(funcp+1, &endptr, 0);
if (endptr[0] != '\0') return invalid_pci_device_string;
}

char *devp = strrchr(id, ':');
if (!devp) {
filter->dev = strtoul(id, &endptr, 0);
filter->dev = strtol(id, &endptr, 0);
} else {
filter->dev = strtoul(devp+1, &endptr, 0);
filter->dev = strtol(devp+1, &endptr, 0);
}
if (endptr != funcp) return invalid_pci_device_string;
if (!devp) return NULL;

char *busp = strchr(id, ':');
if (busp == devp) {
filter->bus = strtoul(id, &endptr, 0);
filter->bus = strtol(id, &endptr, 0);
} else {
filter->bus = strtoul(busp+1, &endptr, 0);
filter->bus = strtol(busp+1, &endptr, 0);
}
if (endptr != funcp) return invalid_pci_device_string;
if (busp == devp) return NULL;

filter->domain = strtoul(id, &endptr, 0);
filter->domain = strtol(id, &endptr, 0);
if (endptr != busp) return invalid_pci_device_string;

return NULL;
Expand All @@ -155,15 +155,15 @@ int pci_filter_match(struct pci_filter* pf, struct pci_dev* dev)
return 1;
}

static struct pci_dev *pci_scan_single_bus(struct pci_dev *dev, int bus)
static struct pci_dev *pci_scan_single_bus(struct pci_dev *dev, uint8_t bus)
{
int devfn;
u32 val;
unsigned char hdr;

for (devfn = 0; devfn < 0x100; devfn++) {
int func = devfn & 0x7;
int slot = (devfn >> 3) & 0x1f;
uint8_t func = devfn & 0x7;
uint8_t slot = (devfn >> 3) & 0x1f;

val = pci_read_config32(PCI_DEV(bus, slot, func),
REG_VENDOR_ID);
Expand All @@ -179,18 +179,18 @@ static struct pci_dev *pci_scan_single_bus(struct pci_dev *dev, int bus)
dev->dev = slot;
dev->func = func;
dev->vendor_id = val & 0xffff;
dev->device_id = val >> 16;
dev->device_id = (uint16_t)(val >> 16);
dev->next = 0;

hdr = pci_read_config8(PCI_DEV(bus, slot, func),
REG_HEADER_TYPE);
hdr &= 0x7F;

if (hdr == HEADER_TYPE_BRIDGE || hdr == HEADER_TYPE_CARDBUS) {
unsigned int busses;
busses = pci_read_config32(PCI_DEV(bus, slot, func),
REG_PRIMARY_BUS);
busses = (busses >> 8) & 0xFF;
uint8_t busses;
busses = (uint8_t)(pci_read_config32(
PCI_DEV(bus, slot, func),
REG_PRIMARY_BUS) >> 8);

/* Avoid recursion if the new bus is the same as
* the old bus (insert lame The Who joke here) */
Expand Down
21 changes: 20 additions & 1 deletion src/Kconfig
Expand Up @@ -205,7 +205,7 @@ config INCLUDE_CONFIG_FILE
Alignment: 64 bytes

Name Offset Type Size
cmos_layout.bin 0x0 cmos layout 1159
cmos_layout.bin 0x0 CMOS layout 1159
fallback/romstage 0x4c0 stage 339756
fallback/ramstage 0x53440 stage 186664
fallback/payload 0x80dc0 payload 51526
Expand Down Expand Up @@ -354,6 +354,25 @@ config RAMPAYLOAD
Skip PCI enumeration logic and only allocate BAR for fixed devices
(bootable devices, TPM over GSPI).

config HAVE_CONFIGURABLE_RAMSTAGE
bool

config CONFIGURABLE_RAMSTAGE
bool "Enable a configurable ramstage."
default y if ARCH_X86
depends on HAVE_CONFIGURABLE_RAMSTAGE
help
A configurable ramstage allows you to select which parts of the ramstage
to run. Currently, we can only select a minimal PCI scanning step.
The minimal PCI scanning will only check those parts that are enabled
in the devicetree.cb. By convention none of those devices should be bridges.

config MINIMAL_PCI_SCANNING
bool "Enable minimal PCI scanning"
depends on CONFIGURABLE_RAMSTAGE && PCI
help
If this option is enabled, coreboot will scan only PCI devices
marked as mandatory in devicetree.cb
endmenu

menu "Mainboard"
Expand Down
5 changes: 1 addition & 4 deletions src/arch/arm64/Makefile.inc
Expand Up @@ -184,10 +184,7 @@ BL31_MAKEARGS += BUILD_PLAT="$(BL31_BUILD)"
BL31_MAKEARGS += IS_ANYTHING_TO_BUILD=1

# Set a consistent build timestamp: the same coreboot has
# The \# \" complications exist to satisfy both gnu make's parser and editors
# with non-semantic quote-handling (that would assume that this line starts a
# multi line string.
BL31_MAKEARGS += BUILD_MESSAGE_TIMESTAMP='"$(shell grep "\#define COREBOOT_BUILD\>" $(obj)/build.h |cut -d\" -f2 \# \")"'
BL31_MAKEARGS += BUILD_MESSAGE_TIMESTAMP='"$(shell sed -n 's/^.define COREBOOT_BUILD\>.*"\(.*\)".*/\1/p' $(obj)/build.h)"'

BL31_CFLAGS := -fno-pic -fno-stack-protector -Wno-deprecated-declarations -Wno-unused-function
BL31_LDFLAGS := --emit-relocs
Expand Down
2 changes: 1 addition & 1 deletion src/arch/x86/acpi.c
Expand Up @@ -946,7 +946,7 @@ unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
acpi_addr_t address;

if (!dev) {
printk(BIOS_ERR, "%s: Device not found\n", __func__);
printk(BIOS_DEBUG, "%s: Device not found\n", __func__);
return current;
}
if (!dev->enabled) {
Expand Down
6 changes: 3 additions & 3 deletions src/arch/x86/acpi_device.c
Expand Up @@ -537,9 +537,9 @@ void acpi_device_write_spi(const struct acpi_spi *spi)
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
{
static const char *power_res_dev_states[] = { "_PR0", "_PR3" };
unsigned int reset_gpio = params->reset_gpio->pins[0];
unsigned int enable_gpio = params->enable_gpio->pins[0];
unsigned int stop_gpio = params->stop_gpio->pins[0];
unsigned int reset_gpio = params->reset_gpio ? params->reset_gpio->pins[0] : 0;
unsigned int enable_gpio = params->enable_gpio ? params->enable_gpio->pins[0] : 0;
unsigned int stop_gpio = params->stop_gpio ? params->stop_gpio->pins[0] : 0;

if (!reset_gpio && !enable_gpio && !stop_gpio)
return;
Expand Down
75 changes: 75 additions & 0 deletions src/arch/x86/acpigen.c
Expand Up @@ -1758,3 +1758,78 @@ int acpigen_disable_tx_gpio(struct acpi_gpio *gpio)
else
return acpigen_soc_clear_tx_gpio(gpio->pins[0]);
}

/* refer to ACPI 6.4.3.5.3 Word Address Space Descriptor section for details */
void acpigen_resource_word(u16 res_type, u16 gen_flags, u16 type_flags, u16 gran,
u16 range_min, u16 range_max, u16 translation, u16 length)
{
acpigen_emit_byte(0x88);
/* Byte 1+2: length (0x000d) */
acpigen_emit_byte(0x0d);
acpigen_emit_byte(0x00);
/* resource type */
acpigen_emit_byte(res_type); // 0 - mem, 1 - io, 2 - bus
/* general flags */
acpigen_emit_byte(gen_flags);
/* type flags */
// refer to ACPI Table 6-234 (Memory), 6-235 (IO), 6-236 (Bus) for details
acpigen_emit_byte(type_flags);
/* granularity, min, max, translation, length */
acpigen_emit_word(gran);
acpigen_emit_word(range_min);
acpigen_emit_word(range_max);
acpigen_emit_word(translation);
acpigen_emit_word(length);
}

/* refer to ACPI 6.4.3.5.2 DWord Address Space Descriptor section for details */
void acpigen_resource_dword(u16 res_type, u16 gen_flags, u16 type_flags,
u32 gran, u32 range_min, u32 range_max, u32 translation, u32 length)
{
acpigen_emit_byte(0x87);
/* Byte 1+2: length (0023) */
acpigen_emit_byte(23);
acpigen_emit_byte(0x00);
/* resource type */
acpigen_emit_byte(res_type); // 0 - mem, 1 - io, 2 - bus
/* general flags */
acpigen_emit_byte(gen_flags);
/* type flags */
// refer to ACPI Table 6-234 (Memory), 6-235 (IO), 6-236 (Bus) for details
acpigen_emit_byte(type_flags);
/* granularity, min, max, translation, length */
acpigen_emit_dword(gran);
acpigen_emit_dword(range_min);
acpigen_emit_dword(range_max);
acpigen_emit_dword(translation);
acpigen_emit_dword(length);
}

static void acpigen_emit_qword(u64 data)
{
acpigen_emit_dword(data & 0xffffffff);
acpigen_emit_dword((data >> 32) & 0xffffffff);
}

/* refer to ACPI 6.4.3.5.1 QWord Address Space Descriptor section for details */
void acpigen_resource_qword(u16 res_type, u16 gen_flags, u16 type_flags,
u64 gran, u64 range_min, u64 range_max, u64 translation, u64 length)
{
acpigen_emit_byte(0x8a);
/* Byte 1+2: length (0x002b) */
acpigen_emit_byte(0x2b);
acpigen_emit_byte(0x00);
/* resource type */
acpigen_emit_byte(res_type); // 0 - mem, 1 - io, 2 - bus
/* general flags */
acpigen_emit_byte(gen_flags);
/* type flags */
// refer to ACPI Table 6-234 (Memory), 6-235 (IO), 6-236 (Bus) for details
acpigen_emit_byte(type_flags);
/* granularity, min, max, translation, length */
acpigen_emit_qword(gran);
acpigen_emit_qword(range_min);
acpigen_emit_qword(range_max);
acpigen_emit_qword(translation);
acpigen_emit_qword(length);
}
9 changes: 9 additions & 0 deletions src/arch/x86/include/arch/acpigen.h
Expand Up @@ -472,4 +472,13 @@ int acpigen_soc_clear_tx_gpio(unsigned int gpio_num);
int acpigen_enable_tx_gpio(struct acpi_gpio *gpio);
int acpigen_disable_tx_gpio(struct acpi_gpio *gpio);

/* refer to ACPI 6.4.3.5.3 Word Address Space Descriptor section for details */
void acpigen_resource_word(u16 res_type, u16 gen_flags, u16 type_flags, u16 gran,
u16 range_min, u16 range_max, u16 translation, u16 length);
/* refer to ACPI 6.4.3.5.2 DWord Address Space Descriptor section for details */
void acpigen_resource_dword(u16 res_type, u16 gen_flags, u16 type_flags,
u32 gran, u32 range_min, u32 range_max, u32 translation, u32 length);
/* refer to ACPI 6.4.3.5.1 QWord Address Space Descriptor section for details */
void acpigen_resource_qword(u16 res_type, u16 gen_flags, u16 type_flags,
u64 gran, u64 range_min, u64 range_max, u64 translation, u64 length);
#endif
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/cpu.h
Expand Up @@ -261,7 +261,6 @@ static inline struct cpu_info *cpu_info(void)
return ci;
}

/* romcc is segfaulting in some cases. */
struct cpuinfo_x86 {
uint8_t x86; /* CPU family */
uint8_t x86_vendor; /* CPU vendor */
Expand All @@ -281,7 +280,6 @@ static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)

}

/* romcc does not understand regparm. */
#define asmlinkage __attribute__((regparm(0)))

/*
Expand Down
7 changes: 7 additions & 0 deletions src/arch/x86/include/arch/rom_segs.h
Expand Up @@ -18,4 +18,11 @@
#define ROM_DATA_SEG 0x10
#define ROM_CODE_SEG64 0x18

/*
* This define is placed here to make sure future romstage programmers
* know about it.
* It is used for STM setup code.
*/
#define SMM_TASK_STATE_SEG 0x20

#endif /* ROM_SEGS_H */
2 changes: 1 addition & 1 deletion src/commonlib/cbfs.c
Expand Up @@ -44,7 +44,7 @@ static size_t cbfs_next_offset(const struct region_device *cbfs,
if (f == NULL)
return 0;

/* The region_device objects store absolute offets over the whole
/* The region_device objects store absolute offsets over the whole
* region. Therefore a relative offset needs to be calculated. */
offset = rdev_relative_offset(cbfs, &f->data);
offset += region_device_sz(&f->data);
Expand Down
2 changes: 1 addition & 1 deletion src/commonlib/include/commonlib/cbfs.h
Expand Up @@ -24,7 +24,7 @@ struct cbfsf {
struct region_device data;
};

/* Locate file by name and optional type. Returns 0 on succcess else < 0 on
/* Locate file by name and optional type. Returns 0 on success else < 0 on
* error.*/
int cbfs_locate(struct cbfsf *fh, const struct region_device *cbfs,
const char *name, uint32_t *type);
Expand Down
2 changes: 1 addition & 1 deletion src/commonlib/include/commonlib/cbmem_id.h
Expand Up @@ -72,7 +72,7 @@
#define CBMEM_ID_VBOOT_WORKBUF 0x78007343
#define CBMEM_ID_VPD 0x56504420
#define CBMEM_ID_WIFI_CALIBRATION 0x57494649
#define CBMEM_ID_EC_HOSTEVENT 0x63ccbbc3
#define CBMEM_ID_EC_HOSTEVENT 0x63ccbbc3 /* deprecated */
#define CBMEM_ID_EXT_VBT 0x69866684
#define CBMEM_ID_ROM0 0x524f4d30
#define CBMEM_ID_ROM1 0x524f4d31
Expand Down
12 changes: 6 additions & 6 deletions src/commonlib/include/commonlib/coreboot_tables.h
Expand Up @@ -431,15 +431,15 @@ struct lb_macs {

#define MAX_SERIALNO_LENGTH 32

/* The following structures are for the cmos definitions table */
/* cmos header record */
/* The following structures are for the CMOS definitions table */
/* CMOS header record */
struct cmos_option_table {
uint32_t tag; /* CMOS definitions table type */
uint32_t size; /* size of the entire table */
uint32_t header_length; /* length of header */
};

/* cmos entry record
/* CMOS entry record
* This record is variable length. The name field may be
* shorter than CMOS_MAX_NAME_LENGTH. The entry may start
* anywhere in the byte, but can not span bytes unless it
Expand All @@ -459,7 +459,7 @@ struct cmos_entries {
};


/* cmos enumerations record
/* CMOS enumerations record
* This record is variable length. The text field may be
* shorter than CMOS_MAX_TEXT_LENGTH.
*/
Expand All @@ -473,8 +473,8 @@ struct cmos_enums {
variable length int aligned */
};

/* cmos defaults record
* This record contains default settings for the cmos ram.
/* CMOS defaults record
* This record contains default settings for the CMOS ram.
*/
struct cmos_defaults {
uint32_t tag; /* default type */
Expand Down
2 changes: 1 addition & 1 deletion src/commonlib/include/commonlib/storage.h
Expand Up @@ -57,7 +57,7 @@
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_BUS_WIDTH_STROBE (1<<7) /* Enhanced strobe mode */

#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
#define EXT_CSD_TIMING_BC 0 /* Backwards compatibility */
#define EXT_CSD_TIMING_HS 1 /* High speed */
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
Expand Down
4 changes: 2 additions & 2 deletions src/commonlib/include/commonlib/timestamp_serialized.h
Expand Up @@ -156,8 +156,8 @@ static const struct timestamp_id_to_name {
/* Marker to report base_time. */
{ 0, "1st timestamp" },
{ TS_START_ROMSTAGE, "start of romstage" },
{ TS_BEFORE_INITRAM, "before ram initialization" },
{ TS_AFTER_INITRAM, "after ram initialization" },
{ TS_BEFORE_INITRAM, "before RAM initialization" },
{ TS_AFTER_INITRAM, "after RAM initialization" },
{ TS_END_ROMSTAGE, "end of romstage" },
{ TS_START_VBOOT, "start of verified boot" },
{ TS_END_VBOOT, "end of verified boot" },
Expand Down
2 changes: 1 addition & 1 deletion src/commonlib/storage/sd.c
Expand Up @@ -220,7 +220,7 @@ int sd_change_freq(struct storage_media *media)
if (!((ctrlr->caps & DRVR_CAP_HS52) && (ctrlr->caps & DRVR_CAP_HS)))
goto out;

/* Give the card time to recover afer the switch operation. Wait for
/* Give the card time to recover after the switch operation. Wait for
* 9 (>= 8) clock cycles receiving the switch status.
*/
delay = (9000000 + ctrlr->bus_hz - 1) / ctrlr->bus_hz;
Expand Down
6 changes: 2 additions & 4 deletions src/cpu/Kconfig
Expand Up @@ -27,15 +27,13 @@ config MMX
bool
help
Select MMX in your socket or model Kconfig if your CPU has MMX
streaming SIMD instructions. ROMCC can build more efficient
code if it can spill to MMX registers.
streaming SIMD instructions.

config SSE
bool
help
Select SSE in your socket or model Kconfig if your CPU has SSE
streaming SIMD instructions. ROMCC can build more efficient
code if it can spill to SSE (aka XMM) registers.
streaming SIMD instructions.

config SSE2
bool
Expand Down
4 changes: 4 additions & 0 deletions src/cpu/Makefile.inc
Expand Up @@ -60,3 +60,7 @@ $(obj)/cpu_microcode_blob.bin: $$(wildcard $$(cpu_microcode_bins))
cpu_microcode_blob.bin-file ?= $(obj)/cpu_microcode_blob.bin
cpu_microcode_blob.bin-type := microcode
cpu_microcode_blob.bin-align := 16

ifneq ($(CONFIG_CPU_MICROCODE_CBFS_LOC),)
cpu_microcode_blob.bin-COREBOOT-position := $(CONFIG_CPU_MICROCODE_CBFS_LOC)
endif
2 changes: 1 addition & 1 deletion src/cpu/intel/microcode/Kconfig
Expand Up @@ -4,4 +4,4 @@ config MICROCODE_UPDATE_PRE_RAM
default y
help
Select this option if you want to update the microcode
during the cache as ram setup.
during the cache as RAM setup.
32 changes: 28 additions & 4 deletions src/cpu/x86/mp_init.c
Expand Up @@ -13,6 +13,7 @@
*/

#include <console/console.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <rmodule.h>
Expand All @@ -37,6 +38,8 @@
#include <timer.h>
#include <thread.h>

#include <security/intel/stm/SmmStm.h>

#define MAX_APIC_IDS 256

struct mp_callback {
Expand Down Expand Up @@ -518,11 +521,12 @@ static int bsp_do_flight_plan(struct mp_params *mp_params)
int i;
int ret = 0;
/*
* Set time-out to wait for APs to a huge value (=1 second) since it
* could take a longer time for APs to check-in as the number of APs
* increases (contention for resources like UART also increases).
* Set time out for flight plan to a huge minimum value (>=1 second).
* CPUs with many APs may take longer if there is contention for
* resources such as UART, so scale the time out up by increments of
* 100ms if needed.
*/
const int timeout_us = 1000000;
const int timeout_us = MAX(1000000, 100000 * mp_params->num_cpus);
const int step_us = 100;
int num_aps = mp_params->num_cpus - 1;
struct stopwatch sw;
Expand Down Expand Up @@ -741,6 +745,18 @@ static void asmlinkage smm_do_relocation(void *arg)

/* Setup code checks this callback for validity. */
mp_state.ops.relocation_handler(cpu, curr_smbase, perm_smbase);

if (CONFIG(STM)) {
uintptr_t mseg;

mseg = mp_state.perm_smbase +
(mp_state.perm_smsize - CONFIG_MSEG_SIZE);

stm_setup(mseg, p->cpu, runtime->num_cpus,
perm_smbase,
mp_state.perm_smbase,
runtime->start32_offset);
}
}

static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)
Expand Down Expand Up @@ -1020,6 +1036,14 @@ static void fill_mp_state(struct mp_state *state, const struct mp_ops *ops)
ops->get_smm_info(&state->perm_smbase, &state->perm_smsize,
&state->smm_save_state_size);

/*
* Make sure there is enough room for the SMM descriptor
*/
if (CONFIG(STM)) {
state->smm_save_state_size +=
ALIGN_UP(sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR), 0x100);
}

/*
* Default to smm_initiate_relocation() if trigger callback isn't
* provided.
Expand Down
1 change: 1 addition & 0 deletions src/cpu/x86/name/Makefile.inc
Expand Up @@ -12,4 +12,5 @@
##

bootblock-y += name.c
romstage-y += name.c
ramstage-y += name.c
20 changes: 19 additions & 1 deletion src/cpu/x86/smm/smm_module_loader.c
Expand Up @@ -17,6 +17,7 @@
#include <cpu/x86/cache.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <security/intel/stm/SmmStm.h>

#define FXSAVE_SIZE 512

Expand Down Expand Up @@ -201,6 +202,8 @@ static int smm_module_setup_stub(void *smbase, struct smm_loader_params *params,
/* Adjust remaining size to account for save state. */
total_save_state_size = params->per_cpu_save_state_size *
params->num_concurrent_save_states;
if (total_save_state_size > size)
return -1;
size -= total_save_state_size;

/* The save state size encroached over the first SMM entry point. */
Expand Down Expand Up @@ -267,6 +270,7 @@ static int smm_module_setup_stub(void *smbase, struct smm_loader_params *params,
stub_params->fxsave_area_size = FXSAVE_SIZE;
stub_params->runtime.smbase = (uintptr_t)smbase;
stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
stub_params->runtime.num_cpus = params->num_concurrent_stacks;

/* Initialize the APIC id to CPU number table to be 1:1 */
for (i = 0; i < params->num_concurrent_stacks; i++)
Expand Down Expand Up @@ -313,6 +317,11 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
* +-----------------+ <- smram + size
* | stacks |
* +-----------------+ <- smram + size - total_stack_size
* | fxsave area |
* +-----------------+ <- smram + size - total_stack_size - fxsave_size
* | BIOS resource |
* | list (STM) |
* +-----------------+ <- .. - CONFIG_BIOS_RESOURCE_LIST_SIZE
* | ... |
* +-----------------+ <- smram + handler_size + SMM_DEFAULT_SIZE
* | handler |
Expand Down Expand Up @@ -353,7 +362,12 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)

/* Stacks start at the top of the region. */
base = smram;
base += size;

if (CONFIG(STM))
base += size - CONFIG_MSEG_SIZE; // take out the mseg
else
base += size;

params->stack_top = base;

/* SMM module starts at offset SMM_DEFAULT_SIZE with the load alignment
Expand Down Expand Up @@ -382,6 +396,10 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
/* Does the required amount of memory exceed the SMRAM region size? */
total_size = total_stack_size + handler_size;
total_size += fxsave_size + SMM_DEFAULT_SIZE;
/* Account for the BIOS resource list */
if (CONFIG(STM))
total_size += CONFIG_BIOS_RESOURCE_LIST_SIZE;

if (total_size > size)
return -1;

Expand Down
13 changes: 13 additions & 0 deletions src/cpu/x86/smm/smm_stub.S
Expand Up @@ -44,6 +44,11 @@ smbase:
.long 0
save_state_size:
.long 0
num_cpus:
.long 0
/* allows the STM to bring up SMM in 32-bit mode */
start32_offset:
.long smm_trampoline32 - _start
/* apic_to_cpu_num is a table mapping the default APIC id to CPU num. If the
* APIC id is found at the given index, the contiguous CPU number is index
* into the table. */
Expand Down Expand Up @@ -90,6 +95,14 @@ smm_relocate_gdt:
/* gdt selector 0x10, flat data segment */
.word 0xffff, 0x0000
.byte 0x00, 0x93, 0xcf, 0x00

/* gdt selector 0x18, flat code segment (64-bit) */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xcf, 0x00

/* gdt selector 0x20 tss segment */
.word 0xffff, 0x0000
.byte 0x00, 0x8b, 0x80, 0x00
smm_relocate_gdt_end:

.align 4
Expand Down