103 changes: 103 additions & 0 deletions Documentation/mainboard/asus/p8h61-m_pro.md
@@ -0,0 +1,103 @@
# ASUS P8H61-M Pro

This page describes how to run coreboot on the [ASUS P8H61-M Pro].

## Flashing coreboot

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

The flash IC is located right next to one of the SATA ports:
![](p8h61-m_pro.jpg)

### Internal programming

The main SPI flash can be accessed using [flashrom]. By default, only
the BIOS region of the flash is writable. If you wish to change any
other region (Management Engine or flash descriptor), then an external
programmer is required.

The following command may be used to flash coreboot:

```
$ sudo flashrom --noverify-all --ifd -i bios -p internal -w coreboot.rom
```

The use of `--noverify-all` is required since the Management Engine
region is not readable even by the host.

## Known issues

- There is no automatic, OS-independent fan control. This is because
the super I/O hardware monitor can only obtain valid CPU temperature
readings from the PECI agent, whose complete initialisation is not
publicly documented. The `coretemp` driver can still be used for
accurate CPU temperature readings.

- me_cleaner breaks LPC bus and attached components!
- PS/2 mouse doesn't work

## Untested

- parallel port
- EHCI debug
- S/PDIF audio

## Working

- PS/2 keyboard
- PCIe graphics
- USB
- Gigabit Ethernet
- Integrated graphics
- SATA
- Serial port
- hardware monitor (see [Known issues](#known-issues) for caveats)
- front panel audio
- Native raminit (2 x 2GB, DDR3-1333)
- Native graphics init (libgfxinit)
- Wake-on-LAN
- TPM on TPM-header

## Technology

```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
+------------------+--------------------------------------------------+
| Southbridge | bd82x6x |
+------------------+--------------------------------------------------+
| CPU | model_206ax |
+------------------+--------------------------------------------------+
| Super I/O | Nuvoton NCT6776 |
+------------------+--------------------------------------------------+
| EC | None |
+------------------+--------------------------------------------------+
| Coprocessor | Intel Management Engine |
+------------------+--------------------------------------------------+
```

## Extra resources

- [Flash chip datasheet][W25Q32BV]

[ASUS P8H61-M Pro]: https://www.asus.com/Motherboards/P8H61M_Pro/
[W25Q32BV]: https://www.winbond.com/resource-files/w25q32bv_revi_100413_wo_automotive.pdf
[flashrom]: https://flashrom.org/Flashrom
82 changes: 82 additions & 0 deletions Documentation/mainboard/hp/8760w.md
@@ -0,0 +1,82 @@
# HP EliteBook 8760w

This page describes how to run coreboot on the [HP EliteBook 8760w].

## Flashing coreboot

```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
| Socketed flash | no |
+---------------------+------------+
| Model | W25Q64.V |
+---------------------+------------+
| Size | 8 MiB |
+---------------------+------------+
| Package | SOIC-8 |
+---------------------+------------+
| Write protection | no |
+---------------------+------------+
| Dual BIOS feature | no |
+---------------------+------------+
| In circuit flashing | yes |
+---------------------+------------+
| Internal flashing | yes |
+---------------------+------------+
```

## Required proprietary blobs

- Intel Firmware Descriptor, ME and GbE firmware
- EC: please read [EliteBook Series](elitebook_series)

## Flashing instructions

HP EliteBook 8760w has an 8MB SOIC-8 flash chip on the bottom of the
mainboard. You just need to remove the service cover, and use an SOIC-8
clip to read and flash the chip.

![8760w_chip_location](8760w_flash.jpg)

## Untested

- dock: serial port, parallel port, ...
- TPM
- S3 suspend/resume
- Gigabit Ethernet

## Working

- i7-2630QM, 0+4G+8G+0
- i7-3720QM, 8G+8G+8G+8G
- Arch Linux boot from SeaBIOS payload
- EHCI debug: the port is at the right side, next to the charging port
- SATA
- eSATA
- USB2 and USB3
- keyboard, touchpad, trackpad
- WLAN
- WWAN
- EC ACPI
- Using `me_cleaner`

## Technology

```eval_rst
+------------------+--------------------------------------------------+
| Northbridge | :doc:`../../northbridge/intel/sandybridge/index` |
+------------------+--------------------------------------------------+
| Southbridge | bd82x6x |
+------------------+--------------------------------------------------+
| CPU | model_206ax |
+------------------+--------------------------------------------------+
| Super I/O | SMSC LPC47n217 |
+------------------+--------------------------------------------------+
| EC | SMSC KBC1126 |
+------------------+--------------------------------------------------+
| Coprocessor | Intel Management Engine |
+------------------+--------------------------------------------------+
```

[HP EliteBook 8760w]: https://support.hp.com/us-en/product/hp-elitebook-8760w-mobile-workstation/5071180
Binary file added Documentation/mainboard/hp/8760w_flash.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
111 changes: 111 additions & 0 deletions Documentation/mainboard/hp/elitebook_series.md
@@ -0,0 +1,111 @@
# HP EliteBook series

This document is about HP EliteBook series laptops up to Ivy Bridge era
which use SMSC KBC1126 as embedded controller.

## EC

SMSC KBC1098/KBC1126 has been used in HP EliteBooks for many generations.
They use similar EC firmware that will load other code and data from the
SPI flash chip, so we need to put some firmware blobs to the coreboot image.

The following document takes EliteBook 2760p as an example.

First, you need to extract the blobs needed by EC firmware using util/kbc1126.
You can extract them from your backup firmware image, or firmware update
provided by HP with [unar] as follows:

```bash
wget https://ftp.hp.com/pub/softpaq/sp79501-80000/sp79710.exe
unar sp79710.exe
${COREBOOT_DIR}/util/kbc1126/kbc1126_ec_dump sp79710/Rompaq/68SOU.BIN
mv 68SOU.BIN.fw1 ${COREBOOT_DIR}/2760p-fw1.bin
mv 68SOU.BIN.fw2 ${COREBOOT_DIR}/2760p-fw2.bin
```

When you config coreboot, select:

```text
Chipset --->
[*] Add firmware images for KBC1126 EC
(2760p-fw1.bin) KBC1126 firmware #1 path and filename
(2760p-fw2.bin) KBC1126 filename #2 path and filename
```

## Super I/O

EliteBook 8000 series laptops have SMSC LPC47n217 Super I/O to provide
a serial port and a parallel port, you can debug the laptop via this
serial port.

## porting

To port coreboot to an HP EliteBook laptop, you need to do the following:

- select Kconfig option `EC_HP_KBC1126`
- select Kconfig option `SUPERIO_SMSC_LPC47N217` if there is LPC47n217 Super I/O
- initialize EC and Super I/O in romstage
- add EC and Super I/O support to devicetree.cb

To get the related values for EC in devicetree.cb, you need to extract the EFI
module EcThermalInit from the vendor UEFI firmware with [UEFITool]. Usually,
`ec_data_port`, `ec_cmd_port` and `ec_ctrl_reg` has the following values:

- For xx60 series: 0x60, 0x64, 0xca
- For xx70 series: 0x62, 0x66, 0x81

You can use [radare2] and the following [r2pipe] Python script to find
these values from the EcThermalInit EFI module:

```python
#!/usr/bin/env python

# install radare2 and use `pip3 install --user r2pipe` to install r2pipe

import r2pipe
import sys

if len(sys.argv) < 2:
fn = "ecthermalinit.efi"
else:
fn = sys.argv[1]

r2 = r2pipe.open(fn)
r2.cmd("aa")
entryf = r2.cmdj("pdfj")

for insn in entryf["ops"]:
if "lea r8" in insn["opcode"]:
_callback = insn["ptr"]
break

r2.cmd("af @ {}".format(_callback))
callbackf_insns = r2.cmdj("pdfj @ {}".format(_callback))["ops"]

def find_port(addr):
ops = r2.cmdj("pdfj @ {}".format(addr))["ops"]
for insn in ops:
if "lea r8d" in insn["opcode"]:
return insn["ptr"]

ctrl_reg_found = False

for i in range(0, len(callbackf_insns)):
if not ctrl_reg_found and "mov cl" in callbackf_insns[i]["opcode"]:
ctrl_reg_found = True
ctrl_reg = callbackf_insns[i]["ptr"]
print("ec_ctrl_reg = 0x%02x" % ctrl_reg)
cmd_port = find_port(callbackf_insns[i+1]["jump"])
data_port = find_port(callbackf_insns[i+3]["jump"])
print("ec_cmd_port = 0x%02x\nec_data_port = 0x%02x" % (cmd_port, data_port))

if "mov bl" in callbackf_insns[i]["opcode"]:
ctrl_value = callbackf_insns[i]["ptr"]
print("ec_fan_ctrl_value = 0x%02x" % ctrl_value)
```


[unar]: https://theunarchiver.com/command-line
[UEFITool]: https://github.com/LongSoft/UEFITool
[radare2]: https://radare.org/
[r2pipe]: https://github.com/radare/radare2-r2pipe
11 changes: 11 additions & 0 deletions Documentation/mainboard/index.md
Expand Up @@ -6,6 +6,7 @@ This section contains documentation about coreboot on specific mainboards.

- [F2A85-M](asus/f2a85-m.md)
- [P8H61-M LX](asus/p8h61-m_lx.md)
- [P8H61-M Pro](asus/p8h61-m_pro.md)

## ASRock

Expand Down Expand Up @@ -44,11 +45,17 @@ The boards in this section are not real mainboards, but emulators.
## Open Cellular

- [Elgon](opencellular/elgon.md)
- [Rotundu](opencellular/rotundu.md)

## HP

- [Compaq 8200 Elite SFF](hp/compaq_8200_sff.md)

### EliteBook series

- [EliteBook common](hp/elitebook_series.md)
- [EliteBook 8760w](hp/8760w.md)

## Lenovo

- [Mainboard codenames](lenovo/codenames.md)
Expand Down Expand Up @@ -81,3 +88,7 @@ The boards in this section are not real mainboards, but emulators.
## Supermicro

- [X10SLM+-F](supermicro/x10slm-f.md)

## UP

- [Squared](up/squared/index.md)
76 changes: 76 additions & 0 deletions Documentation/mainboard/opencellular/rotundu.md
@@ -0,0 +1,76 @@
# Rutundu

This page describes how to run coreboot on the [Rotundu] compute board
from [OpenCellular].

## TODO

* Configure UART
* EC interface

## Flashing coreboot

```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
| Socketed flash | no |
+---------------------+------------+
| Model | W25Q128 |
+---------------------+------------+
| Size | 16 MiB |
+---------------------+------------+
| In circuit flashing | yes |
+---------------------+------------+
| Package | SOIC-8 |
+---------------------+------------+
| Write protection | No |
+---------------------+------------+
| Dual BIOS feature | No |
+---------------------+------------+
| Internal flashing | yes |
+---------------------+------------+
```

### Internal programming

The SPI flash can be accessed using [flashrom].

### External programming

The GBCv1 board does have a pinheader to flash the SOIC-8 in circuit.
Directly connecting a Pomona test-clip on the flash is also possible.

**Closeup view of SOIC-8 flash IC**

![][rotundu_flash]

[rotundu_flash]: rotundu_flash.jpg

**SPI header**

![][rotundu_header2]

[rotundu_header2]: rotundu_header2.jpg

**SPI header pinout**

Dediprog compatible pinout.

![][rotundu_j16]

[rotundu_j16]: rotundu_j16.png

## Technology

```eval_rst
+------------------+--------------------------------------------------+
| SoC | Intel Baytrail |
+------------------+--------------------------------------------------+
| Coprocessor | Intel ME |
+------------------+--------------------------------------------------+
```

[Rotundu]: https://github.com/Telecominfraproject/OpenCellular
[OpenCellular]: https://code.fb.com/connectivity/introducing-opencellular-an-open-source-wireless-access-platform/
[flashrom]: https://flashrom.org/Flashrom
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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.
Binary file added Documentation/mainboard/up/squared/bottom.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 99 additions & 0 deletions Documentation/mainboard/up/squared/index.md
@@ -0,0 +1,99 @@
# Squared

## Overview
### Top
![][overview_top]

### Bottom
![][overview_bottom]

## Mainboard components
### Platform
```eval_rst
+------------------+----------------------------------+
| CPU | Intel Atom, Celeron, Pentium |
+------------------+----------------------------------+
| PCH | Intel Apollo Lake |
+------------------+----------------------------------+
| EC / Super IO | N/A |
+------------------+----------------------------------+
| Coprocessor | Intel TXE 3.0 |
+------------------+----------------------------------+
```

### Flash chip
```eval_rst
+---------------------+------------+
| Type | Value |
+=====================+============+
| Socketed flash | no |
+---------------------+------------+
| Vendor | Winbond |
+---------------------+------------+
| Model | W25Q128FW |
+---------------------+------------+
| Voltage | 1.8V |
+---------------------+------------+
| Size | 16 MiB |
+---------------------+------------+
| Package | SOIC-8 |
+---------------------+------------+
| Write protection | No |
+---------------------+------------+
| Internal flashing | No |
+---------------------+------------+
| In curcuit flashing | Yes |
+---------------------+------------+
```

## Board status
### Working
- bootblock, romstage, ramstage
- Serial console UART0, UART1
- SPI flash console
- iGPU init with libgfxinit
- LAN1, LAN2
- USB2, USB3
- HDMI, DisplayPort
- eMMC
- flashing with flashrom externally

### Work in progress
- Documentation
- ACPI

### Not working / Known issues
- Generally SeaBIOS works, but it can't find the CBFS region and therefore it can't load seavgabios. This is because of changes at the Apollolake platform.

### Untested
- GPIO pin header
- 60 pin EXHAT
- Camera interface
- MIPI-CSI2 2-lane (2MP)
- MIPI-CSI2 4-lane (8MP)
- SATA3
- USB3 OTG
- embedded DisplayPort
- M.2 slot
- mini PCIe
- flashing with flashrom internally using Linux

## Building and flashing coreboot
### Building

```bash
make distclean
touch .config
./util/scripts/config --enable VENDOR_UP
./util/scripts/config --enable BOARD_UP_SQUARED
./util/scripts/config --enable NEED_IFWI
./util/scripts/config --enable HAVE_IFD_BIN
./util/scripts/config --set-str IFWI_FILE_NAME "<path_to_your_bios_region>"
./util/scripts/config --set-str IFD_BIN_PATH "<path_to_your_ifd_region>"
make olddefconfig
```

### Flashing

[overview_top]: top.jpg
[overview_bottom]: bottom.jpg
Binary file added Documentation/mainboard/up/squared/top.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Makefile.inc
Expand Up @@ -401,7 +401,7 @@ endif
CFLAGS_common += -pipe -g -nostdinc -std=gnu11
CFLAGS_common += -nostdlib -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
CFLAGS_common += -Wwrite-strings -Wredundant-decls -Wno-trigraphs
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time
CFLAGS_common += -Wstrict-aliasing -Wshadow -Wdate-time -Wtype-limits
CFLAGS_common += -fno-common -ffreestanding -fno-builtin -fomit-frame-pointer
CFLAGS_common += -ffunction-sections -fdata-sections -fno-pie
ifeq ($(CONFIG_COMPILER_GCC),y)
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu1
@@ -1,11 +1,11 @@
CONFIG_LOCALVERSION="v4.9.0.5"
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.9.0.5"
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU2=y
Expand All @@ -7,7 +7,7 @@ CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/variants/$(CONFIG_VARIANT_DIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
Expand Down
25 changes: 25 additions & 0 deletions configs/config.pcengines_apu2_vboot
@@ -0,0 +1,25 @@
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_CBFS_SIZE=0x20C000
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_VBOOT=y
CONFIG_BOARD_PCENGINES_APU2=y
CONFIG_PXE_ROM_ID="8086,157b"
CONFIG_CPU_MICROCODE_CBFS_NONE=y
CONFIG_NO_GFX_INIT=y
CONFIG_VBOOT_MEASURED_BOOT=y
CONFIG_VBOOT_SLOTS_RW_AB=y
CONFIG_USER_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/variants/$(CONFIG_VARIANT_DIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
CONFIG_BUILD_IPXE=y
# CONFIG_PXE_SERIAL_CONSOLE is not set
CONFIG_PXE_CUSTOM_BUILD_ID="12345678"
CONFIG_MEMTEST_SECONDARY_PAYLOAD=y
CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y
CONFIG_MEMTEST_REVISION=y
CONFIG_MEMTEST_REVISION_ID="0bd34c22604660e4283316331f3e7bf8a3863753"
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu3
@@ -1,12 +1,12 @@
CONFIG_LOCALVERSION="v4.9.0.5"
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU3=y
CONFIG_CPU_MICROCODE_CBFS_NONE=y
CONFIG_NO_GFX_INIT=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/variants/$(CONFIG_VARIANT_DIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu4
@@ -1,12 +1,12 @@
CONFIG_LOCALVERSION="v4.9.0.5"
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU4=y
CONFIG_CPU_MICROCODE_CBFS_NONE=y
CONFIG_NO_GFX_INIT=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/variants/$(CONFIG_VARIANT_DIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
Expand Down
4 changes: 2 additions & 2 deletions configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.9.0.5"
CONFIG_LOCALVERSION="v4.9.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
Expand All @@ -7,7 +7,7 @@ CONFIG_NO_GFX_INIT=y
CONFIG_USER_TPM2=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y
CONFIG_SEABIOS_REVISION=y
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.1"
CONFIG_SEABIOS_REVISION_ID="rel-1.12.1.2"
CONFIG_SEABIOS_BOOTORDER_FILE="$(top)/src/mainboard/$(MAINBOARDDIR)/variants/$(CONFIG_VARIANT_DIR)/bootorder"
CONFIG_SEABIOS_DEBUG_LEVEL=0
CONFIG_PXE=y
Expand Down
7 changes: 1 addition & 6 deletions payloads/coreinfo/pci_module.c
Expand Up @@ -103,15 +103,10 @@ static void show_config_space(WINDOW *win, int row, int col, int index)
static int pci_module_redraw(WINDOW *win)
{
unsigned int bus, slot, func;
int i, last;
int i;

print_module_title(win, "PCI Device List");

last = menu_first + MENU_VISIBLE;

if (last > devices_index)
last = devices_index;

for (i = 0; i < MENU_VISIBLE; i++) {
int item = menu_first + i;

Expand Down
2 changes: 1 addition & 1 deletion payloads/external/sortbootorder/Makefile
@@ -1,4 +1,4 @@
version=4.6.13
version=4.6.14
branch_name=v$(version)
project_url=https://github.com/pcengines/sortbootorder/archive/$(branch_name).tar.gz
archive_name=$(branch_name).tar.gz
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/i8042/i8042.h
Expand Up @@ -63,6 +63,7 @@
#define I8042_KBCMD_EN 0xf4
#define I8042_KBCMD_DEFAULT_DIS 0xf5
#define I8042_KBCMD_SET_DEFAULT 0xf6
#define I8042_KBCMD_ACK 0xfa
#define I8042_KBCMD_RESEND 0xfe
#define I8042_KBCMD_RESET 0xff

Expand Down
11 changes: 10 additions & 1 deletion payloads/libpayload/drivers/i8042/keyboard.c
Expand Up @@ -258,6 +258,7 @@ int keyboard_getchar(void)
/* vulcan nerve pinch */
if ((modifier & KB_MOD_ALT) && reset_handler)
reset_handler();
/* fallthrough */
default:
ret = 0;
}
Expand Down Expand Up @@ -296,7 +297,8 @@ int keyboard_set_layout(char *country)

static struct console_input_driver cons = {
.havekey = keyboard_havechar,
.getchar = keyboard_getchar
.getchar = keyboard_getchar,
.input_type = CONSOLE_INPUT_TYPE_EC,
};

void keyboard_init(void)
Expand All @@ -315,6 +317,13 @@ void keyboard_init(void)
/* Enable first PS/2 port */
i8042_cmd(I8042_CMD_EN_KB);

/* Reset keyboard and self test (keyboard side) */
ret = keyboard_cmd(I8042_KBCMD_RESET);
if (ret != I8042_KBCMD_ACK) {
printf("ERROR: Keyboard reset failed ACK: 0x%x\n", ret);
return;
}

/* Set scancode set 1 */
ret = keyboard_cmd(I8042_KBCMD_SET_SCANCODE);
if (!ret && !CONFIG(LP_PC_KEYBOARD_IGNORE_INIT_FAILURE))
Expand Down
3 changes: 2 additions & 1 deletion payloads/libpayload/drivers/serial/8250.c
Expand Up @@ -98,7 +98,8 @@ static void serial_hardware_init(int speed, int word_bits,

static struct console_input_driver consin = {
.havekey = &serial_havechar,
.getchar = &serial_getchar
.getchar = &serial_getchar,
.input_type = CONSOLE_INPUT_TYPE_UART,
};

static struct console_output_driver consout = {
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/serial/ipq40xx.c
Expand Up @@ -560,6 +560,7 @@ void serial_console_init(void)

consin.havekey = serial_havechar;
consin.getchar = serial_getchar;
consin.input_type = CONSOLE_INPUT_TYPE_UART;

consout.putchar = serial_putchar;

Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/serial/ipq806x.c
Expand Up @@ -352,6 +352,7 @@ void serial_console_init(void)

consin.havekey = serial_havechar;
consin.getchar = serial_getchar;
consin.input_type = CONSOLE_INPUT_TYPE_UART;

consout.putchar = serial_putchar;

Expand Down
3 changes: 2 additions & 1 deletion payloads/libpayload/drivers/serial/s5p.c
Expand Up @@ -84,7 +84,8 @@ static struct console_output_driver s5p_serial_output =
static struct console_input_driver s5p_serial_input =
{
.havekey = &serial_havechar,
.getchar = &serial_getchar
.getchar = &serial_getchar,
.input_type = CONSOLE_INPUT_TYPE_UART,
};

void serial_init(void)
Expand Down
9 changes: 6 additions & 3 deletions payloads/libpayload/drivers/storage/ahci.c
Expand Up @@ -108,6 +108,9 @@ static int ahci_dev_init(hba_ctrl_t *const ctrl,

const int ncs = HBA_CAPS_DECODE_NCS(ctrl->caps);

if (ahci_cmdengine_stop(port))
return 1;

/* Allocate command list, one command table and received FIS. */
cmd_t *const cmdlist = memalign(1024, ncs * sizeof(cmd_t));
cmdtable_t *const cmdtable = memalign(128, sizeof(cmdtable_t));
Expand All @@ -121,12 +124,10 @@ static int ahci_dev_init(hba_ctrl_t *const ctrl,
memset((void *)rcvd_fis, '\0', sizeof(*rcvd_fis));

/* Set command list base and received FIS base. */
if (ahci_cmdengine_stop(port))
return 1;
port->cmdlist_base = virt_to_phys(cmdlist);
port->frameinfo_base = virt_to_phys(rcvd_fis);
if (ahci_cmdengine_start(port))
return 1;
goto _cleanup_ret;
/* Put port into active state. */
port->cmd_stat |= HBA_PxCMD_ICC_ACTIVE;

Expand Down Expand Up @@ -178,6 +179,8 @@ static int ahci_dev_init(hba_ctrl_t *const ctrl,
/* Clean up (not reached for initialized devices). */
if (dev)
free(dev);
/* Only free if stopping succeeds, since otherwise the controller may
still use the resources for DMA. */
if (!ahci_cmdengine_stop(port)) {
port->cmdlist_base = 0;
port->frameinfo_base = 0;
Expand Down
15 changes: 15 additions & 0 deletions payloads/libpayload/include/coreboot_tables.h
Expand Up @@ -287,6 +287,21 @@ struct cb_macs {
struct mac_address mac_addrs[0];
};

#define CB_TAG_MMC_INFO 0x0035
struct cb_mmc_info {
uint32_t tag;
uint32_t size;
/*
* Passes the early mmc status to payload to indicate if firmware
* successfully sent CMD0, CMD1 to the card or not. In case of
* success, the payload can skip the first step of the initialization
* sequence which is to send CMD0, and instead start by sending CMD1
* as described in Jedec Standard JESD83-B1 section 6.4.3.
* passes 1 on success
*/
int32_t early_cmd1_status;
};

#define CB_TAG_SERIALNO 0x002a
#define CB_MAX_SERIALNO_LENGTH 32

Expand Down
10 changes: 8 additions & 2 deletions payloads/libpayload/include/libpayload.h
Expand Up @@ -350,6 +350,9 @@ int set_option_from_string(const struct nvram_accessor *nvram, struct cb_cmos_op
typedef enum {
CONSOLE_INPUT_TYPE_UNKNOWN = 0,
CONSOLE_INPUT_TYPE_USB,
CONSOLE_INPUT_TYPE_EC,
CONSOLE_INPUT_TYPE_UART,
CONSOLE_INPUT_TYPE_GPIO,
} console_input_type;

void console_init(void);
Expand Down Expand Up @@ -431,9 +434,12 @@ void hexdump(const void *memory, size_t length);
void fatal(const char *msg) __attribute__((noreturn));

/* Count Leading Zeroes: clz(0) == 32, clz(0xf) == 28, clz(1 << 31) == 0 */
static inline int clz(u32 x) { return x ? __builtin_clz(x) : sizeof(x) * 8; }
static inline int clz(u32 x)
{
return x ? __builtin_clz(x) : (int)sizeof(x) * 8;
}
/* Integer binary logarithm (rounding down): log2(0) == -1, log2(5) == 2 */
static inline int log2(u32 x) { return sizeof(x) * 8 - clz(x) - 1; }
static inline int log2(u32 x) { return (int)sizeof(x) * 8 - clz(x) - 1; }
/* Find First Set: __ffs(0xf) == 0, __ffs(0) == -1, __ffs(1 << 31) == 31 */
static inline int __ffs(u32 x) { return log2(x & (u32)(-(s32)x)); }
/** @} */
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/include/sysinfo.h
Expand Up @@ -129,6 +129,7 @@ struct sysinfo_t {
uint64_t mtc_start;
uint32_t mtc_size;
void *chromeos_vpd;
int mmc_early_wake_status;
};

extern struct sysinfo_t lib_sysinfo;
Expand Down
10 changes: 10 additions & 0 deletions payloads/libpayload/libc/coreboot.c
Expand Up @@ -102,6 +102,13 @@ static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
info->vbnv_size = vbnv->range_size;
}

static void cb_parse_mmc_info(unsigned char *ptr, struct sysinfo_t *info)
{
struct cb_mmc_info *mmc_info = (struct cb_mmc_info *)ptr;

info->mmc_early_wake_status = mmc_info->early_cmd1_status;
}

static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
{
int i;
Expand Down Expand Up @@ -399,6 +406,9 @@ int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
case CB_TAG_SPI_FLASH:
cb_parse_spi_flash(ptr, info);
break;
case CB_TAG_MMC_INFO:
cb_parse_mmc_info(ptr, info);
break;
case CB_TAG_MTC:
cb_parse_mtc(ptr, info);
break;
Expand Down
40 changes: 15 additions & 25 deletions src/Kconfig
Expand Up @@ -277,6 +277,21 @@ config BOOTSPLASH_FILE
The path and filename of the file to use as graphical bootsplash
screen. The file format has to be jpg.

config RAMPAYLOAD
bool "Enable coreboot flow without executing ramstage"
default n
depends on ARCH_X86
help
If this option is enabled, coreboot flow will skip ramstage
loading and execution of ramstage to load payload.

Instead it is expected to load payload from postcar stage itself.

In this flow coreboot will perform basic x86 initialization
(DRAM resource allocation), MTRR programming,
Skip PCI enumeration logic and only allocate BAR for fixed devices
(bootable devices, TPM over GSPI).

endmenu

menu "Mainboard"
Expand Down Expand Up @@ -1143,31 +1158,6 @@ config GENERIC_GPIO_LIB
implies configurability usually found on SoCs, particularly the
ability to control internal pull resistors.

config GENERIC_SPD_BIN
bool
help
If enabled, add support for adding spd.hex files in cbfs as spd.bin
and locating it runtime to load SPD. Additionally provide provision to
fetch SPD over SMBus.

config DIMM_MAX
int
default 4
help
Total number of memory DIMM slots available on motherboard.
It is multiplication of number of channel to number of DIMMs per
channel

config DIMM_SPD_SIZE
int
default 256
help
Total SPD size that will be used for DIMM.
Ex: DDR3 256, DDR4 512.

config SPD_READ_BY_WORD
bool

config BOOTBLOCK_CUSTOM
# To be selected by arch, SoC or mainboard if it does not want use the normal
# src/lib/bootblock.c#main() C entry point.
Expand Down
2 changes: 0 additions & 2 deletions src/arch/arm64/boot.c
Expand Up @@ -38,15 +38,13 @@ static void run_payload(struct prog *prog)
void arch_prog_run(struct prog *prog)
{
void (*doit)(void *);
void *arg;

if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
run_payload(prog);
return;
}

doit = prog_entry(prog);
arg = prog_entry_arg(prog);

doit(prog_entry_arg(prog));
}
Expand Down
4 changes: 1 addition & 3 deletions src/arch/x86/car.ld
Expand Up @@ -91,9 +91,7 @@
_car_global_end = .;
_car_relocatable_data_end = .;

#if (CONFIG(NORTHBRIDGE_INTEL_SANDYBRIDGE) || \
CONFIG(NORTHBRIDGE_INTEL_IVYBRIDGE)) && \
!CONFIG(USE_NATIVE_RAMINIT)
#if CONFIG(NORTHBRIDGE_INTEL_SANDYBRIDGE) && !CONFIG(USE_NATIVE_RAMINIT)
. = ABSOLUTE(0xff7e1000);
_mrc_pool = .;
. += 0x5000;
Expand Down
53 changes: 53 additions & 0 deletions src/arch/x86/cpu.c
Expand Up @@ -219,6 +219,35 @@ static void set_cpu_ops(struct device *cpu)
cpu->ops = driver ? driver->ops : NULL;
}

/* Keep track of default apic ids for SMM. */
static int cpus_default_apic_id[CONFIG_MAX_CPUS];

/*
* When CPUID executes with EAX set to 1, additional processor identification
* information is returned to EBX register:
* Default APIC ID: EBX[31-24] - this number is the 8 bit ID that is assigned
* to the local APIC on the processor during power on.
*/
static int initial_lapicid(void)
{
return cpuid_ebx(1) >> 24;
}

/* Function to keep track of cpu default apic_id */
void cpu_add_map_entry(unsigned int index)
{
cpus_default_apic_id[index] = initial_lapicid();
}

/* Returns default APIC id based on logical_cpu number or < 0 on failure. */
int cpu_get_apic_id(int logical_cpu)
{
if (logical_cpu >= CONFIG_MAX_CPUS || logical_cpu < 0)
return -1;

return cpus_default_apic_id[logical_cpu];
}

void cpu_initialize(unsigned int index)
{
/* Because we busy wait at the printk spinlock.
Expand Down Expand Up @@ -308,3 +337,27 @@ void arch_bootstate_coreboot_exit(void)
/* APs are waiting for work. Last thing to do is park them. */
mp_park_aps();
}

/*
* Previously cpu_index() implementation assumes that cpu_index()
* function will always getting called from coreboot context
* (ESP stack pointer will always refer to coreboot).
*
* But with FSP_USES_MP_SERVICES_PPI implementation in coreboot this
* assumption might not be true, where FSP context (stack pointer refers
* to FSP) will request to get cpu_index().
*
* Hence new logic to use cpuid to fetch lapic id and matches with
* cpus_default_apic_id[] variable to return correct cpu_index().
*/
int cpu_index(void)
{
int i;
int lapic_id = initial_lapicid();

for (i = 0; i < CONFIG_MAX_CPUS; i++) {
if (cpu_get_apic_id(i) == lapic_id)
return i;
}
return -1;
}
2 changes: 1 addition & 1 deletion src/arch/x86/exception.c
Expand Up @@ -502,7 +502,7 @@ void x86_exception(struct eregs *info)
}
#else /* !CONFIG_GDB_STUB */
#define MDUMP_SIZE 0x80
unsigned int logical_processor = 0;
int logical_processor = 0;

#if ENV_RAMSTAGE
logical_processor = cpu_index();
Expand Down
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/acpi.h
Expand Up @@ -838,14 +838,12 @@ void acpi_create_ivrs(acpi_ivrs_t *ivrs,
unsigned long (*acpi_fill_ivrs)(acpi_ivrs_t *ivrs_struct,
unsigned long current));

#if ENV_RAMSTAGE && !defined(__SIMPLE_DEVICE__)
void acpi_create_hpet(acpi_hpet_t *hpet);
unsigned long acpi_write_hpet(struct device *device, unsigned long start,
acpi_rsdp_t *rsdp);

/* cpu/intel/speedstep/acpi.c */
void generate_cpu_entries(struct device *device);
#endif

void acpi_create_mcfg(acpi_mcfg_t *mcfg);

Expand Down
21 changes: 14 additions & 7 deletions src/arch/x86/include/arch/cpu.h
Expand Up @@ -261,13 +261,6 @@ static inline struct cpu_info *cpu_info(void)
);
return ci;
}

static inline unsigned long cpu_index(void)
{
struct cpu_info *ci;
ci = cpu_info();
return ci->index;
}
#endif

#ifndef __ROMCC__ // romcc is segfaulting in some cases
Expand Down Expand Up @@ -374,4 +367,18 @@ uint32_t cpu_get_feature_flags_ecx(void);
*/
uint32_t cpu_get_feature_flags_edx(void);

/*
* Previously cpu_index() implementation assumes that cpu_index()
* function will always getting called from coreboot context
* (ESP stack pointer will always refer to coreboot).
*
* But with FSP_USES_MP_SERVICES_PPI implementation in coreboot this
* assumption might not be true, where FSP context (stack pointer refers
* to FSP) will request to get cpu_index().
*
* Hence new logic to use cpuid to fetch lapic id and matches with
* cpus_default_apic_id[] variable to return correct cpu_index().
*/
int cpu_index(void);

#endif /* ARCH_CPU_H */
9 changes: 6 additions & 3 deletions src/arch/x86/postcar_loader.c
Expand Up @@ -141,13 +141,16 @@ static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
};

if (prog_locate(prog))
die("Failed to locate after CAR program.\n");
die_with_post_code(POST_INVALID_ROM,
"Failed to locate after CAR program.\n");
if (rmodule_stage_load(&rsl))
die("Failed to load after CAR program.\n");
die_with_post_code(POST_INVALID_ROM,
"Failed to load after CAR program.\n");

/* Set the stack pointer within parameters of the program loaded. */
if (rsl.params == NULL)
die("No parameters found in after CAR program.\n");
die_with_post_code(POST_INVALID_ROM,
"No parameters found in after CAR program.\n");

finalize_load(rsl.params, pcf->stack);

Expand Down
12 changes: 6 additions & 6 deletions src/arch/x86/smbios.c
Expand Up @@ -140,7 +140,7 @@ void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id,
struct smbios_type17 *t)
{
switch (mod_id) {
case 0x2c80:
case 0x9b85:
t->manufacturer = smbios_add_string(t->eos,
"Crucial");
break;
Expand Down Expand Up @@ -172,9 +172,9 @@ void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id,
t->manufacturer = smbios_add_string(t->eos,
"Hynix/Hyundai");
break;
case 0xb502:
case 0x3486:
t->manufacturer = smbios_add_string(t->eos,
"SuperTalent");
"Super Talent");
break;
case 0xcd04:
t->manufacturer = smbios_add_string(t->eos,
Expand All @@ -188,7 +188,7 @@ void smbios_fill_dimm_manufacturer_from_id(uint16_t mod_id,
t->manufacturer = smbios_add_string(t->eos,
"Elpida");
break;
case 0xff2c:
case 0x2c80:
t->manufacturer = smbios_add_string(t->eos,
"Micron");
break;
Expand Down Expand Up @@ -977,7 +977,7 @@ int smbios_write_type38(unsigned long *current, int *handle,

int smbios_write_type41(unsigned long *current, int *handle,
const char *name, u8 instance, u16 segment,
u8 bus, u8 device, u8 function)
u8 bus, u8 device, u8 function, u8 device_type)
{
struct smbios_type41 *t = (struct smbios_type41 *)*current;
int len = sizeof(struct smbios_type41);
Expand All @@ -987,7 +987,7 @@ int smbios_write_type41(unsigned long *current, int *handle,
t->handle = *handle;
t->length = len - 2;
t->reference_designation = smbios_add_string(t->eos, name);
t->device_type = SMBIOS_DEVICE_TYPE_OTHER;
t->device_type = device_type;
t->device_status = 1;
t->device_type_instance = instance;
t->segment_group_number = segment;
Expand Down
1 change: 1 addition & 0 deletions src/commonlib/cbfs.c
Expand Up @@ -18,6 +18,7 @@
#include <commonlib/endian.h>
#include <commonlib/helpers.h>
#include <string.h>
#include <vb2_sha.h>

#if !defined(ERROR)
#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
Expand Down
2 changes: 2 additions & 0 deletions src/commonlib/include/commonlib/cbmem_id.h
Expand Up @@ -39,6 +39,7 @@
#define CBMEM_ID_IMD_SMALL 0x53a11439
#define CBMEM_ID_MEMINFO 0x494D454D
#define CBMEM_ID_MMA_DATA 0x4D4D4144
#define CBMEM_ID_MMC_STATUS 0x4d4d4353
#define CBMEM_ID_MPTABLE 0x534d5054
#define CBMEM_ID_MRCDATA 0x4d524344
#define CBMEM_ID_VAR_MRCDATA 0x4d524345
Expand Down Expand Up @@ -100,6 +101,7 @@
{ CBMEM_ID_IMD_SMALL, "IMD SMALL " }, \
{ CBMEM_ID_MEMINFO, "MEM INFO " }, \
{ CBMEM_ID_MMA_DATA, "MMA DATA " }, \
{ CBMEM_ID_MMC_STATUS, "MMC STATUS " }, \
{ CBMEM_ID_MPTABLE, "SMP TABLE " }, \
{ CBMEM_ID_MRCDATA, "MRC DATA " }, \
{ CBMEM_ID_VAR_MRCDATA, "VARMRC DATA" }, \
Expand Down
15 changes: 15 additions & 0 deletions src/commonlib/include/commonlib/coreboot_tables.h
Expand Up @@ -385,6 +385,21 @@ struct mac_address {
uint8_t pad[2]; /* Pad it to 8 bytes to keep it simple. */
};

#define LB_TAG_MMC_INFO 0x0035
struct lb_mmc_info {
uint32_t tag;
uint32_t size;
/*
* Passes the early mmc status to payload to indicate if firmware
* successfully sent CMD0, CMD1 to the card or not. In case of
* success, the payload can skip the first step of the initialization
* sequence which is to send CMD0, and instead start by sending CMD1
* as described in Jedec Standard JESD83-B1 section 6.4.3.
* passes 1 on success
*/
int32_t early_cmd1_status;
};

struct lb_macs {
uint32_t tag;
uint32_t size;
Expand Down
6 changes: 3 additions & 3 deletions src/commonlib/include/commonlib/stdlib.h
Expand Up @@ -38,19 +38,19 @@
#if CONFIG(COREBOOT_BUILD)
#include <console/console.h>
#include <halt.h>
#define printf(...) printk(BIOS_ERR, __VA_ARGS__)
#define HALT(x) halt()
#else
#include <stdio.h>
#define HALT(x)
#define printk(level, ...) printf(__VA_ARGS__)
#define HALT(x) abort()
#endif

static inline void *xmalloc_work(size_t size, const char *file,
const char *func, int line)
{
void *ret = malloc(size);
if (!ret && size) {
printf("%s/%s/line %d: Failed to malloc %zu bytes\n",
printk(BIOS_ERR, "%s/%s/line %d: Failed to malloc %zu bytes\n",
file, func, line, size);
while (1)
HALT(1);
Expand Down
1 change: 1 addition & 0 deletions src/console/Makefile.inc
Expand Up @@ -9,6 +9,7 @@ endif

smm-$(CONFIG_DEBUG_SMI) += init.c console.c vtxprintf.c printk.c
smm-$(CONFIG_SMM_TSEG) += die.c
smm-$(CONFIG_SMM_TSEG) += post.c

verstage-y += init.c
verstage-y += printk.c
Expand Down
7 changes: 7 additions & 0 deletions src/console/die.c
Expand Up @@ -36,4 +36,11 @@ void __noreturn die(const char *msg)
die_notify();
halt();
}

/* Report a fatal error with a post code */
void __noreturn die_with_post_code(uint8_t value, const char *msg)
{
post_code(value);
die(msg);
}
#endif
4 changes: 1 addition & 3 deletions src/console/post.c
Expand Up @@ -44,7 +44,6 @@ void __weak mainboard_post(uint8_t value)

DECLARE_SPIN_LOCK(cmos_post_lock)

#if ENV_RAMSTAGE
void cmos_post_log(void)
{
u8 code = 0;
Expand Down Expand Up @@ -82,7 +81,7 @@ void cmos_post_log(void)
default:
printk(BIOS_WARNING, "POST: Unexpected post code "
"in previous boot: 0x%02x\n", code);
#if CONFIG(ELOG)
#if CONFIG(ELOG) && (ENV_RAMSTAGE || CONFIG(ELOG_PRERAM))
elog_add_event_word(ELOG_TYPE_LAST_POST_CODE, code);
#if CONFIG(CMOS_POST_EXTRA)
if (extra)
Expand Down Expand Up @@ -125,7 +124,6 @@ void post_log_clear(void)
post_log_extra(0);
}
#endif /* CONFIG_CMOS_POST_EXTRA */
#endif /* ENV_RAMSTAGE */

static void cmos_post_code(u8 value)
{
Expand Down
22 changes: 4 additions & 18 deletions src/console/vtxprintf.c
Expand Up @@ -24,20 +24,6 @@
#define SUPPORT_64BIT_INTS
#endif

/* haha, don't need ctype.c */
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define is_digit isdigit
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))

static int skip_atoi(const char **s)
{
int i = 0;

while (is_digit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}

#define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */
Expand Down Expand Up @@ -175,8 +161,8 @@ int vtxprintf(void (*tx_byte)(unsigned char byte, void *data),

/* get field width */
field_width = -1;
if (is_digit(*fmt)) {
field_width = skip_atoi(&fmt);
if (isdigit(*fmt)) {
field_width = skip_atoi((char **)&fmt);
} else if (*fmt == '*') {
++fmt;
/* it's the next argument */
Expand All @@ -191,8 +177,8 @@ int vtxprintf(void (*tx_byte)(unsigned char byte, void *data),
precision = -1;
if (*fmt == '.') {
++fmt;
if (is_digit(*fmt)) {
precision = skip_atoi(&fmt);
if (isdigit(*fmt)) {
precision = skip_atoi((char **)&fmt);
} else if (*fmt == '*') {
++fmt;
/* it's the next argument */
Expand Down
6 changes: 3 additions & 3 deletions src/cpu/amd/quadcore/quadcore.c
Expand Up @@ -95,13 +95,13 @@ void real_start_other_core(uint32_t nodeid, uint32_t cores)
*/

/* Wait for the first core of each compute unit to start... */
uint32_t timeout;
for (i = 1; i < cores + 1; i++) {
if (!(i & 0x1)) {
uint32_t ap_apicid =
get_boot_apic_id(nodeid, i);
timeout = wait_cpu_state(ap_apicid,
F10_APSTATE_ASLEEP, F10_APSTATE_ASLEEP);
/* Timeout */
wait_cpu_state(ap_apicid, F10_APSTATE_ASLEEP,
F10_APSTATE_ASLEEP);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/cpu/intel/Makefile.inc
Expand Up @@ -12,7 +12,6 @@ subdirs-$(CONFIG_CPU_INTEL_SOCKET_P) += socket_p
subdirs-$(CONFIG_CPU_INTEL_SOCKET_MPGA604) += socket_mPGA604
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_NEHALEM) += model_2065x
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += model_206ax
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += model_206ax
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_HASWELL) += haswell
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_FSP_RANGELEY) += fsp_model_406dx
subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1
Expand Down
6 changes: 6 additions & 0 deletions src/cpu/intel/model_2065x/Kconfig
Expand Up @@ -20,6 +20,8 @@ config CPU_SPECIFIC_OPTIONS
select TSC_SYNC_MFENCE
select CPU_INTEL_COMMON
select NO_FIXED_XIP_ROM_SIZE
select PARALLEL_MP
select CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM

config BOOTBLOCK_CPU_INIT
string
Expand All @@ -29,4 +31,8 @@ config SMM_TSEG_SIZE
hex
default 0x800000

config SMM_RESERVED_SIZE
hex
default 0x100000

endif
4 changes: 4 additions & 0 deletions src/cpu/intel/model_2065x/Makefile.inc
Expand Up @@ -19,6 +19,10 @@ ramstage-y += acpi.c

smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c

romstage-y += stage_cache.c
ramstage-y += stage_cache.c
postcar-y += stage_cache.c

cpu_microcode_bins += 3rdparty/blobs/cpu/intel/model_2065x/microcode.bin

cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S
Expand Down
19 changes: 19 additions & 0 deletions src/cpu/intel/model_2065x/model_2065x.h
Expand Up @@ -20,6 +20,7 @@
/* Nehalem bus clock is fixed at 133MHz */
#define NEHALEM_BCLK 133

#define CORE_THREAD_COUNT_MSR 0x35
#define MSR_FEATURE_CONFIG 0x13c
#define MSR_FLEX_RATIO 0x194
#define FLEX_RATIO_LOCK (1 << 20)
Expand Down Expand Up @@ -79,4 +80,22 @@ void set_power_limits(u8 power_limit_1_time);
int cpu_config_tdp_levels(void);
#endif

/*
* Region of SMM space is reserved for multipurpose use. It falls below
* the IED region and above the SMM handler.
*/
#define RESERVED_SMM_SIZE CONFIG_SMM_RESERVED_SIZE
#define RESERVED_SMM_OFFSET (CONFIG_SMM_TSEG_SIZE - RESERVED_SMM_SIZE)

/* Sanity check config options. */
#if (CONFIG_SMM_TSEG_SIZE <= RESERVED_SMM_SIZE)
# error "CONFIG_SMM_TSEG_SIZE <= RESERVED_SMM_SIZE"
#endif
#if (CONFIG_SMM_TSEG_SIZE < 0x800000)
# error "CONFIG_SMM_TSEG_SIZE must at least be 8MiB"
#endif
#if ((CONFIG_SMM_TSEG_SIZE & (CONFIG_SMM_TSEG_SIZE - 1)) != 0)
# error "CONFIG_SMM_TSEG_SIZE is not a power of 2"
#endif

#endif
153 changes: 70 additions & 83 deletions src/cpu/intel/model_2065x/model_2065x_init.c
Expand Up @@ -15,13 +15,15 @@
* GNU General Public License for more details.
*/

#include <assert.h>
#include <console/console.h>
#include <device/device.h>
#include <arch/acpi.h>
#include <cpu/cpu.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/intel/microcode.h>
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
Expand Down Expand Up @@ -109,29 +111,6 @@ static acpi_cstate_t cstate_map[] = {
{ 0 }
};

int cpu_get_apic_id_map(int *apic_id_map)
{
int i;
struct cpuid_result result;
unsigned int threads_per_package, threads_per_core;

/* Logical processors (threads) per core */
result = cpuid_ext(0xb, 0);
threads_per_core = result.ebx & 0xffff;

/* Logical processors (threads) per package */
result = cpuid_ext(0xb, 1);
threads_per_package = result.ebx & 0xffff;

for (i = 0; i < threads_per_package && i < CONFIG_MAX_CPUS; ++i) {
apic_id_map[i] = (i % threads_per_core)
+ ((i / threads_per_core) << 2);
}

return threads_per_package;
}


int cpu_config_tdp_levels(void)
{
msr_t platform_info;
Expand Down Expand Up @@ -250,67 +229,13 @@ static void configure_mca(void)
wrmsr(IA32_MC0_STATUS + (i * 4), msr);
}

/*
* Initialize any extra cores/threads in this package.
*/
static void intel_cores_init(struct device *cpu)
{
struct cpuid_result result;
unsigned int threads_per_package, threads_per_core, i;

/* Logical processors (threads) per core */
result = cpuid_ext(0xb, 0);
threads_per_core = result.ebx & 0xffff;

/* Logical processors (threads) per package */
result = cpuid_ext(0xb, 1);
threads_per_package = result.ebx & 0xffff;

/* Only initialize extra cores from BSP */
if (cpu->path.apic.apic_id)
return;

printk(BIOS_DEBUG, "CPU: %u has %u cores, %u threads per core\n",
cpu->path.apic.apic_id, threads_per_package/threads_per_core,
threads_per_core);

for (i = 1; i < threads_per_package; ++i) {
struct device_path cpu_path;
struct device *new;

/* Build the CPU device path */
cpu_path.type = DEVICE_PATH_APIC;
cpu_path.apic.apic_id =
cpu->path.apic.apic_id + (i % threads_per_core)
+ ((i / threads_per_core) << 2);

/* Allocate the new CPU device structure */
new = alloc_dev(cpu->bus, &cpu_path);
if (!new)
continue;

printk(BIOS_DEBUG, "CPU: %u has core %u\n",
cpu->path.apic.apic_id,
new->path.apic.apic_id);

/* Start the new CPU */
if (is_smp_boot() && !start_cpu(new)) {
/* Record the error in cpu? */
printk(BIOS_ERR, "CPU %u would not start!\n",
new->path.apic.apic_id);
}
}
}

static void model_2065x_init(struct device *cpu)
{
char processor_name[49];

/* Turn on caching if we haven't already */
x86_enable_cache();

intel_update_microcode_from_cbfs();

/* Clear out pending MCEs */
configure_mca();

Expand All @@ -320,10 +245,6 @@ static void model_2065x_init(struct device *cpu)
printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid(),
boot_cpu());

/* Setup MTRRs based on physical address size */
x86_setup_mtrrs_with_detect();
x86_mtrr_check();

/* Setup Page Attribute Tables (PAT) */
// TODO set up PAT

Expand All @@ -348,9 +269,75 @@ static void model_2065x_init(struct device *cpu)

/* Enable Turbo */
enable_turbo();
}

/* Start up extra cores */
intel_cores_init(cpu);
/* MP initialization support. */
static const void *microcode_patch;

static void pre_mp_init(void)
{
/* Setup MTRRs based on physical address size. */
x86_setup_mtrrs_with_detect();
x86_mtrr_check();
}

static int get_cpu_count(void)
{
msr_t msr;
int num_threads;
int num_cores;

msr = rdmsr(CORE_THREAD_COUNT_MSR);
num_threads = (msr.lo >> 0) & 0xffff;
num_cores = (msr.lo >> 16) & 0xffff;
printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n",
num_cores, num_threads);

return num_threads;
}

static void get_microcode_info(const void **microcode, int *parallel)
{
microcode_patch = intel_microcode_find();
*microcode = microcode_patch;
*parallel = 1;
}

static void per_cpu_smm_trigger(void)
{
/* Relocate the SMM handler. */
smm_relocate();

/* After SMM relocation a 2nd microcode load is required. */
intel_microcode_load_unlocked(microcode_patch);
}

static void post_mp_init(void)
{
/* Now that all APs have been relocated as well as the BSP let SMIs
* start flowing. */
southbridge_smm_init();

/* Lock down the SMRAM space. */
smm_lock();
}


static const struct mp_ops mp_ops = {
.pre_mp_init = pre_mp_init,
.get_cpu_count = get_cpu_count,
.get_smm_info = smm_info,
.get_microcode_info = get_microcode_info,
.pre_mp_smm_init = smm_initialize,
.per_cpu_smm_trigger = per_cpu_smm_trigger,
.relocation_handler = smm_relocation_handler,
.post_mp_init = post_mp_init,
};

void bsp_init_and_start_aps(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
}

static struct device_operations cpu_dev_ops = {
Expand Down
30 changes: 30 additions & 0 deletions src/cpu/intel/model_2065x/stage_cache.c
@@ -0,0 +1,30 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2015 Google, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#include <cbmem.h>
#include <stage_cache.h>
#include <cpu/intel/smm/gen1/smi.h>
#include "model_2065x.h"

void stage_cache_external_region(void **base, size_t *size)
{
/*
* The ramstage cache lives in the TSEG region at RESERVED_SMM_OFFSET.
* The top of RAM is defined to be the TSEG base address.
*/
*size = RESERVED_SMM_SIZE;
*base = (void *)((uintptr_t)northbridge_get_tseg_base()
+ RESERVED_SMM_OFFSET);
}
5 changes: 1 addition & 4 deletions src/cpu/intel/model_206ax/Kconfig
@@ -1,10 +1,7 @@
config CPU_INTEL_MODEL_206AX
bool

config CPU_INTEL_MODEL_306AX
bool

if CPU_INTEL_MODEL_206AX || CPU_INTEL_MODEL_306AX
if CPU_INTEL_MODEL_206AX

config CPU_SPECIFIC_OPTIONS
def_bool y
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/smm/gen1/smi.h
Expand Up @@ -17,11 +17,8 @@ void bsp_init_and_start_aps(struct bus *cpu_bus);

/* These helpers are for performing SMM relocation. */
void southbridge_smm_init(void);
void southbridge_trigger_smi(void);
void southbridge_clear_smi_status(void);
u32 northbridge_get_tseg_base(void);
u32 northbridge_get_tseg_size(void);
int cpu_get_apic_id_map(int *apic_id_map);
void northbridge_write_smram(u8 smram);

bool cpu_has_alternative_smrr(void);
Expand Down
169 changes: 0 additions & 169 deletions src/cpu/intel/smm/gen1/smmrelocate.c
Expand Up @@ -100,60 +100,6 @@ static void write_smrr(struct smm_relocation_params *relo_params)
}
}

/* The relocation work is actually performed in SMM context, but the code
* resides in the ramstage module. This occurs by trampolining from the default
* SMRAM entry point to here. */
static void asmlinkage cpu_smm_do_relocation(void *arg)
{
em64t101_smm_state_save_area_t *save_state;
msr_t mtrr_cap;
struct smm_relocation_params *relo_params;
const struct smm_module_params *p;
const struct smm_runtime *runtime;
int cpu;

p = arg;
runtime = p->runtime;
relo_params = p->arg;
cpu = p->cpu;

if (cpu >= CONFIG_MAX_CPUS) {
printk(BIOS_CRIT,
"Invalid CPU number assigned in SMM stub: %d\n", cpu);
return;
}

printk(BIOS_DEBUG, "In relocation handler: cpu %d\n", cpu);

/* All threads need to set IEDBASE and SMBASE in the save state area.
* Since one thread runs at a time during the relocation the save state
* is the same for all cpus. */
save_state = (void *)(runtime->smbase + SMM_DEFAULT_SIZE -
runtime->save_state_size);

/* The relocated handler runs with all CPUs concurrently. Therefore
* stagger the entry points adjusting SMBASE downwards by save state
* size * CPU num. */
save_state->smbase = relo_params->smram_base -
cpu * runtime->save_state_size;
if (CONFIG_IED_REGION_SIZE != 0) {
save_state->iedbase = relo_params->ied_base;

printk(BIOS_DEBUG, "New SMBASE=0x%08x IEDBASE=0x%08x @ %p\n",
save_state->smbase, save_state->iedbase, save_state);
} else {
printk(BIOS_DEBUG, "New SMBASE=0x%08x @ %p\n",
save_state->smbase, save_state);
}

/* Write SMRR MSRs based on indicated support. */
mtrr_cap = rdmsr(MTRR_CAP_MSR);
if (mtrr_cap.lo & SMRR_SUPPORTED && relo_params->smrr_mask.lo != 0)
write_smrr(relo_params);

southbridge_clear_smi_status();
}

static void fill_in_relocation_params(struct smm_relocation_params *params)
{
/* All range registers are aligned to 4KiB */
Expand Down Expand Up @@ -202,33 +148,6 @@ static void fill_in_relocation_params(struct smm_relocation_params *params)
}
}

static int install_relocation_handler(int *apic_id_map, int num_cpus,
struct smm_relocation_params *relo_params)
{
/* The default SMM entry happens serially at the default location.
* Therefore, there is only 1 concurrent save state area. Set the
* stack size to the save state size, and call into the
* do_relocation handler. */
int save_state_size = sizeof(em64t101_smm_state_save_area_t);
struct smm_loader_params smm_params = {
.per_cpu_stack_size = save_state_size,
.num_concurrent_stacks = num_cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
.handler = &cpu_smm_do_relocation,
.handler_arg = (void *)relo_params,
};

default_smm_area = backup_default_smm_area();

if (smm_setup_relocation_handler(&smm_params))
return -1;
int i;
for (i = 0; i < num_cpus; i++)
smm_params.runtime->apic_id_to_cpu[i] = apic_id_map[i];
return 0;
}

static void setup_ied_area(struct smm_relocation_params *params)
{
char *ied_base;
Expand All @@ -248,94 +167,6 @@ static void setup_ied_area(struct smm_relocation_params *params)
memset(ied_base + (1 << 20), 0, (32 << 10));
}

static int install_permanent_handler(int *apic_id_map, int num_cpus,
struct smm_relocation_params *relo_params)
{
/* There are num_cpus concurrent stacks and num_cpus concurrent save
* state areas. Lastly, set the stack size to the save state size. */
int save_state_size = sizeof(em64t101_smm_state_save_area_t);
struct smm_loader_params smm_params = {
.per_cpu_stack_size = save_state_size,
.num_concurrent_stacks = num_cpus,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = num_cpus,
};

printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n",
relo_params->smram_base);
if (smm_load_module((void *)relo_params->smram_base,
relo_params->smram_size, &smm_params))
return -1;
int i;
for (i = 0; i < num_cpus; i++)
smm_params.runtime->apic_id_to_cpu[i] = apic_id_map[i];
return 0;
}

static int cpu_smm_setup(void)
{
int num_cpus;
int apic_id_map[CONFIG_MAX_CPUS];

printk(BIOS_DEBUG, "Setting up SMI for CPU\n");

fill_in_relocation_params(&smm_reloc_params);

/* enable the SMM memory window */
northbridge_write_smram(D_OPEN | G_SMRAME | C_BASE_SEG);

if (CONFIG_IED_REGION_SIZE != 0)
setup_ied_area(&smm_reloc_params);

num_cpus = cpu_get_apic_id_map(apic_id_map);
if (num_cpus > CONFIG_MAX_CPUS) {
printk(BIOS_CRIT,
"Error: Hardware CPUs (%d) > MAX_CPUS (%d)\n",
num_cpus, CONFIG_MAX_CPUS);
}

if (install_relocation_handler(apic_id_map, num_cpus,
&smm_reloc_params)) {
printk(BIOS_CRIT, "SMM Relocation handler install failed.\n");
return -1;
}

if (install_permanent_handler(apic_id_map, num_cpus,
&smm_reloc_params)) {
printk(BIOS_CRIT, "SMM Permanent handler install failed.\n");
return -1;
}

/* Ensure the SMM handlers hit DRAM before performing first SMI. */
/* TODO(adurbin): Is this really needed? */
wbinvd();

/* close the SMM memory window and enable normal SMM */
northbridge_write_smram(G_SMRAME | C_BASE_SEG);

return 0;
}

void smm_init(void)
{
/* Return early if CPU SMM setup failed. */
if (cpu_smm_setup())
return;

southbridge_smm_init();

/* Initiate first SMI to kick off SMM-context relocation. Note: this
* SMI being triggered here queues up an SMI in the APs which are in
* wait-for-SIPI state. Once an AP gets an SIPI it will service the SMI
* at the SMM_DEFAULT_BASE before jumping to startup vector. */
southbridge_trigger_smi();

printk(BIOS_DEBUG, "Relocation complete.\n");

/* Lock down the SMRAM space. */
smm_lock();
}

void smm_init_completion(void)
{
restore_default_smm_area(default_smm_area);
Expand Down
7 changes: 7 additions & 0 deletions src/cpu/intel/socket_FCBGA559/Kconfig
Expand Up @@ -21,4 +21,11 @@ config DCACHE_RAM_SIZE
hex
default 0x4000

config DCACHE_BSP_STACK_SIZE
hex
default 0x2000
help
The amount of anticipated stack usage in CAR by bootblock and
other stages.

endif
4 changes: 3 additions & 1 deletion src/cpu/intel/socket_FCBGA559/Makefile.inc
Expand Up @@ -8,7 +8,9 @@ subdirs-y += ../microcode
subdirs-y += ../hyperthreading
subdirs-y += ../speedstep

cpu_incs-y += $(src)/cpu/intel/car/non-evict/cache_as_ram.S
bootblock-y += ../car/bootblock.c
bootblock-y += ../car/non-evict/cache_as_ram.S

postcar-y += ../car/non-evict/exit_car.S

romstage-y += ../car/romstage.c
7 changes: 0 additions & 7 deletions src/cpu/x86/Kconfig
Expand Up @@ -151,13 +151,6 @@ config X86_AMD_FIXED_MTRRS
This option informs the MTRR code to use the RdMem and WrMem fields
in the fixed MTRR MSRs.

config PLATFORM_USES_FSP1_0
bool
default n
help
Selected for Intel processors/platform combinations that use the
Intel Firmware Support Package (FSP) 1.0 for initialization.

config MIRROR_PAYLOAD_TO_RAM_BEFORE_LOADING
def_bool n
help
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/lapic/lapic.c
Expand Up @@ -24,7 +24,7 @@ void do_lapic_init(void)
* see the Intel mp1.4 spec, page A-3
*/

printk(BIOS_INFO, "Setting up local APIC...");
printk(BIOS_INFO, "Setting up local APIC...\n");

/* Enable the local APIC */
enable_lapic();
Expand Down
2 changes: 2 additions & 0 deletions src/cpu/x86/lapic/lapic_cpu_init.c
Expand Up @@ -291,6 +291,7 @@ int start_cpu(struct device *cpu)
info = (struct cpu_info *)stack_top;
info->index = index;
info->cpu = cpu;
cpu_add_map_entry(info->index);
thread_init_cpu_info_non_bsp(info);

/* Advertise the new stack and index to start_cpu */
Expand Down Expand Up @@ -549,6 +550,7 @@ void initialize_cpus(struct bus *cpu_bus)

/* Find the device structure for the boot CPU */
info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
cpu_add_map_entry(info->index);

// why here? In case some day we can start core1 in amd_sibling_init
if (is_smp_boot())
Expand Down
50 changes: 21 additions & 29 deletions src/cpu/x86/mp_init.c
Expand Up @@ -135,20 +135,8 @@ struct mp_flight_plan {
static int global_num_aps;
static struct mp_flight_plan mp_info;

struct cpu_map {
struct device *dev;
/* Keep track of default apic ids for SMM. */
int default_apic_id;
};

/* Keep track of APIC and device structure for each CPU. */
static struct cpu_map cpus[CONFIG_MAX_CPUS];

static inline void add_cpu_map_entry(const struct cpu_info *info)
{
cpus[info->index].dev = info->cpu;
cpus[info->index].default_apic_id = cpuid_ebx(1) >> 24;
}
/* Keep track of device structure for each CPU. */
static struct device *cpus_dev[CONFIG_MAX_CPUS];

static inline void barrier_wait(atomic_t *b)
{
Expand Down Expand Up @@ -212,9 +200,9 @@ static void asmlinkage ap_init(unsigned int cpu)

info = cpu_info();
info->index = cpu;
info->cpu = cpus[cpu].dev;
info->cpu = cpus_dev[cpu];

add_cpu_map_entry(info);
cpu_add_map_entry(info->index);
thread_init_cpu_info_non_bsp(info);

/* Fix up APIC id with reality. */
Expand Down Expand Up @@ -411,7 +399,7 @@ static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p)
continue;
}
new->name = processor_name;
cpus[i].dev = new;
cpus_dev[i] = new;
}

return max_cpus;
Expand Down Expand Up @@ -589,7 +577,7 @@ static void init_bsp(struct bus *cpu_bus)
printk(BIOS_CRIT, "BSP index(%d) != 0!\n", info->index);

/* Track BSP in cpu_map structures. */
add_cpu_map_entry(info);
cpu_add_map_entry(info->index);
}

/*
Expand Down Expand Up @@ -667,15 +655,6 @@ static void mp_initialize_cpu(void)
cpu_initialize(info->index);
}

/* Returns APIC id for coreboot CPU number or < 0 on failure. */
int mp_get_apic_id(int logical_cpu)
{
if (logical_cpu >= CONFIG_MAX_CPUS || logical_cpu < 0)
return -1;

return cpus[logical_cpu].default_apic_id;
}

void smm_initiate_relocation_parallel(void)
{
if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
Expand Down Expand Up @@ -769,7 +748,7 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)
struct smm_runtime *runtime = smm_params->runtime;

for (i = 0; i < CONFIG_MAX_CPUS; i++)
runtime->apic_id_to_cpu[i] = mp_get_apic_id(i);
runtime->apic_id_to_cpu[i] = cpu_get_apic_id(i);
}

static int install_relocation_handler(int num_cpus, size_t save_state_size)
Expand Down Expand Up @@ -891,13 +870,20 @@ static int run_ap_work(struct mp_callback *val, long expire_us)
int i;
int cpus_accepted;
struct stopwatch sw;
int cur_cpu = cpu_index();
int cur_cpu;

if (!CONFIG(PARALLEL_MP_AP_WORK)) {
printk(BIOS_ERR, "APs already parked. PARALLEL_MP_AP_WORK not selected.\n");
return -1;
}

cur_cpu = cpu_index();

if (cur_cpu < 0) {
printk(BIOS_ERR, "Invalid CPU index.\n");
return -1;
}

/* Signal to all the APs to run the func. */
for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
if (cur_cpu == i)
Expand Down Expand Up @@ -939,6 +925,12 @@ static void ap_wait_for_instruction(void)
return;

cur_cpu = cpu_index();

if (cur_cpu < 0) {
printk(BIOS_ERR, "Invalid CPU index.\n");
return;
}

per_cpu_slot = &ap_callbacks[cur_cpu];

while (1) {
Expand Down
4 changes: 2 additions & 2 deletions src/cpu/x86/pae/pgtbl.c
Expand Up @@ -116,12 +116,12 @@ void *map_2M_page(unsigned long page)
static struct pg_table pgtbl[CONFIG_MAX_CPUS]
__attribute__((aligned(4096)));
static unsigned long mapped_window[CONFIG_MAX_CPUS];
unsigned long index;
int index;
unsigned long window;
void *result;
int i;
index = cpu_index();
if (index >= CONFIG_MAX_CPUS)
if (index < 0)
return MAPPING_ERROR;
window = page >> 10;
if (window != mapped_window[index]) {
Expand Down
3 changes: 0 additions & 3 deletions src/device/pci_device.c
Expand Up @@ -780,9 +780,6 @@ static int should_run_oprom(struct device *dev)
*/
should_run = display_init_required();

if (!should_run && CONFIG(VBOOT))
should_run = vboot_wants_oprom();

if (!should_run)
printk(BIOS_DEBUG, "Not running VGA Option ROM\n");
return should_run;
Expand Down
140 changes: 103 additions & 37 deletions src/drivers/amd/agesa/eventlog.c
@@ -1,6 +1,8 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2016-2019 Kyösti Mälkki
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
Expand All @@ -14,62 +16,126 @@
#include <console/console.h>
#include <stdint.h>
#include <string.h>
#include <timestamp.h>

#include <northbridge/amd/agesa/state_machine.h>
#include <northbridge/amd/agesa/BiosCallOuts.h>
#include <amdlib.h>
#include <debug_util.h>
#include <AGESA.h>
#include <AMD.h>

#include <heapManager.h>

static const char undefined[] = "undefined";

/* Match order of enum AGESA_STRUCT_NAME. */
static const char *AgesaFunctionNameStr[] = {
"AmdInitRecovery", "AmdCreateStruct", "AmdInitEarly", "AmdInitEnv", "AmdInitLate",
"AmdInitMid", "AmdInitPost", "AmdInitReset", "AmdInitResume", "AmdReleaseStruct",
"AmdS3LateRestore","AmdS3Save", "AmdGetApicId", "AmdGetPciAddress", "AmdIdentifyCore",
"AmdReadEventLog", "AmdGetAvailableExeCacheSize", "AmdLateRunApTask", "AmdIdentifyDimm",
struct agesa_mapping
{
AGESA_STRUCT_NAME func;
const char *name;
uint32_t entry_id;
uint32_t exit_id;
};

/* heapManager.h */
static const char *HeapStatusStr[] = {
"DoNotExistYet", "LocalCache", "TempMem", "SystemMem", "DoNotExistAnymore","S3Resume"
static const struct agesa_mapping entrypoint[] = {
{
.func = AMD_INIT_RESET,
.name = "AmdInitReset",
.entry_id = TS_AGESA_INIT_RESET_START,
.exit_id = TS_AGESA_INIT_RESET_DONE,
},
{
.func = AMD_INIT_EARLY,
.name = "AmdInitEarly",
.entry_id = TS_AGESA_INIT_EARLY_START,
.exit_id = TS_AGESA_INIT_EARLY_DONE,
},
{
.func = AMD_INIT_POST,
.name = "AmdInitPost",
.entry_id = TS_AGESA_INIT_POST_START,
.exit_id = TS_AGESA_INIT_POST_DONE,
},
{
.func = AMD_INIT_RESUME,
.name = "AmdInitResume",
.entry_id = TS_AGESA_INIT_RESUME_START,
.exit_id = TS_AGESA_INIT_RESUME_DONE,
},
{
.func = AMD_INIT_ENV,
.name = "AmdInitEnv",
.entry_id = TS_AGESA_INIT_ENV_START,
.exit_id = TS_AGESA_INIT_ENV_DONE,
},
{
.func = AMD_INIT_MID,
.name = "AmdInitMid",
.entry_id = TS_AGESA_INIT_MID_START,
.exit_id = TS_AGESA_INIT_MID_DONE,
},
{
.func = AMD_INIT_LATE,
.name = "AmdInitLate",
.entry_id = TS_AGESA_INIT_LATE_START,
.exit_id = TS_AGESA_INIT_LATE_DONE,
},
{
.func = AMD_S3LATE_RESTORE,
.name = "AmdS3LateRestore",
.entry_id = TS_AGESA_S3_LATE_START,
.exit_id = TS_AGESA_S3_LATE_DONE,
},
#if !defined(AMD_S3_SAVE_REMOVED)
{
.func = AMD_S3_SAVE,
.name = "AmdS3Save",
.entry_id = TS_AGESA_INIT_RTB_START,
.exit_id = TS_AGESA_INIT_RTB_DONE,
},
#endif
{
.func = AMD_S3FINAL_RESTORE,
.name = "AmdS3FinalRestore",
.entry_id = TS_AGESA_S3_FINAL_START,
.exit_id = TS_AGESA_S3_FINAL_DONE,
},
{
.func = AMD_INIT_RTB,
.name = "AmdInitRtb",
.entry_id = TS_AGESA_INIT_RTB_START,
.exit_id = TS_AGESA_INIT_RTB_DONE,
},
};

/* This function has to match with enumeration of AGESA_STRUCT_NAME defined
* inside AMD.h header file. Unfortunately those are different across
* different vendorcode subtrees.
*
* TBD: Fix said header or move this function together with the strings above
* under vendorcode/ tree.
*/

const char *agesa_struct_name(int state)
void agesa_state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func)
{
#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
if ((state < AMD_INIT_RECOVERY) || (state > AMD_IDENTIFY_DIMMS))
return undefined;

int index = state - AMD_INIT_RECOVERY;
#else
state >>= 12;
if ((state < AMD_INIT_RECOVERY >> 12) || (state > AMD_IDENTIFY_DIMMS >> 12))
return undefined;
int i;

task->apic_id = (u8) (cpuid_ebx(1) >> 24);
task->func = func;
task->function_name = undefined;

for (i = 0; i < ARRAY_SIZE(entrypoint); i++) {
if (task->func == entrypoint[i].func) {
task->function_name = entrypoint[i].name;
task->ts_entry_id = entrypoint[i].entry_id;
task->ts_exit_id = entrypoint[i].exit_id;
break;
}
}

int index = state - (AMD_INIT_RECOVERY >> 12);
#endif
return AgesaFunctionNameStr[index];
printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}

const char *heap_status_name(int status)
void agesa_state_on_exit(struct agesa_state *task,
AMD_CONFIG_PARAMS *StdHeader)
{
if ((status < HEAP_DO_NOT_EXIST_YET) || (status > HEAP_S3_RESUME))
return undefined;
printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
task->apic_id, heap_status_name(StdHeader->HeapStatus),
StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);

int index = status - HEAP_DO_NOT_EXIST_YET;
return HeapStatusStr[index];
printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}

/*
Expand Down
2 changes: 0 additions & 2 deletions src/drivers/amd/agesa/romstage.c
Expand Up @@ -89,8 +89,6 @@ void *asmlinkage romstage_main(unsigned long bist)
else
agesa_execute_state(cb, AMD_INIT_RESUME);

/* FIXME: Detect if TSC frequency changed during raminit? */
timestamp_rescale_table(1, 4);
timestamp_add_now(TS_AFTER_INITRAM);

/* Work around AGESA setting all memory as WB on normal
Expand Down
60 changes: 23 additions & 37 deletions src/drivers/amd/agesa/state_machine.c
Expand Up @@ -20,11 +20,14 @@
#include <arch/cpu.h>
#include <bootstate.h>
#include <cbfs.h>
#include <console/console.h>
#include <cbmem.h>
#include <timestamp.h>

#include <northbridge/amd/agesa/state_machine.h>
#include <northbridge/amd/agesa/agesa_helper.h>
#include <northbridge/amd/agesa/BiosCallOuts.h>
#include <amdlib.h>

#include <AMD.h>

#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Expand Down Expand Up @@ -146,6 +149,11 @@ static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
platform_BeforeInitPost(cb, param);
board_BeforeInitPost(cb, param);
status = module_dispatch(func, StdHeader);

/* FIXME: Detect if TSC frequency really
* changed during raminit? */
timestamp_rescale_table(1, 4);

platform_AfterInitPost(cb, param);
break;
}
Expand All @@ -155,6 +163,11 @@ static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
AMD_RESUME_PARAMS *param = (void *)StdHeader;
platform_BeforeInitResume(cb, param);
status = module_dispatch(func, StdHeader);

/* FIXME: Detect if TSC frequency really
* changed during raminit? */
timestamp_rescale_table(1, 4);

platform_AfterInitResume(cb, param);
break;
}
Expand Down Expand Up @@ -229,38 +242,6 @@ static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
return status;
}

/* DEBUG trace helper */

struct agesa_state
{
u8 apic_id;

AGESA_STRUCT_NAME func;
const char *function_name;
};

static void state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func,
const char *struct_name)
{
task->apic_id = (u8) (cpuid_ebx(1) >> 24);
task->func = func;
task->function_name = struct_name;

printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}

static void state_on_exit(struct agesa_state *task,
AMD_CONFIG_PARAMS *StdHeader)
{
printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
task->apic_id, heap_status_name(StdHeader->HeapStatus),
StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);

printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
task->apic_id, task->function_name, task->func);
}

int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
{
AMD_INTERFACE_PARAMS aip;
Expand All @@ -270,13 +251,12 @@ int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
} agesa_params;
void *buf = NULL;
size_t len = 0;
const char *state_name = agesa_struct_name(func);

AGESA_STATUS status, final;

struct agesa_state task;
memset(&task, 0, sizeof(task));
state_on_entry(&task, func, state_name);
agesa_state_on_entry(&task, func);

aip.StdHeader = cb->StdHeader;

Expand All @@ -294,19 +274,25 @@ int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
ASSERT(StdHeader->Func == func);

if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id)
timestamp_add_now(task.ts_entry_id);

if (ENV_ROMSTAGE)
final = romstage_dispatch(cb, func, StdHeader);

if (ENV_RAMSTAGE)
final = ramstage_dispatch(cb, func, StdHeader);

agesawrapper_trace(final, StdHeader, state_name);
if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_exit_id)
timestamp_add_now(task.ts_exit_id);

agesawrapper_trace(final, StdHeader, task.function_name);
ASSERT(final < AGESA_FATAL);

status = amd_release_struct(&aip);
ASSERT(status == AGESA_SUCCESS);

state_on_exit(&task, &aip.StdHeader);
agesa_state_on_exit(&task, &aip.StdHeader);

return (final < AGESA_FATAL) ? 0 : -1;
}
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/elog/elog.c
Expand Up @@ -797,7 +797,7 @@ static bool elog_do_add_boot_count(void)
#endif
}

static void ramstage_elog_add_boot_count(void)
static void elog_add_boot_count(void)
{
if (elog_do_add_boot_count()) {
elog_add_event_dword(ELOG_TYPE_BOOT, boot_count_read());
Expand Down Expand Up @@ -860,7 +860,7 @@ int elog_init(void)
es->full_threshold, es->shrink_size);

if (ENV_RAMSTAGE)
ramstage_elog_add_boot_count();
elog_add_boot_count();
return 0;
}

Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/fsp1_0/Kconfig
Expand Up @@ -13,6 +13,13 @@
## GNU General Public License for more details.
##

config PLATFORM_USES_FSP1_0
bool
default n
help
Selected for Intel processors/platform combinations that use the
Intel Firmware Support Package (FSP) 1.0 for initialization.

if PLATFORM_USES_FSP1_0

comment "Intel FSP"
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/intel/fsp1_1/Kconfig
Expand Up @@ -18,6 +18,8 @@ config PLATFORM_USES_FSP1_1
bool
select UEFI_2_4_BINDING
select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
select POSTCAR_STAGE
select POSTCAR_CONSOLE
help
Does the code require the Intel Firmware Support Package?

Expand Down
8 changes: 7 additions & 1 deletion src/drivers/intel/fsp1_1/Makefile.inc
Expand Up @@ -28,7 +28,6 @@ romstage-y += fsp_util.c
romstage-y += hob.c
romstage-y += raminit.c
romstage-y += romstage.c
romstage-y += stack.c
romstage-y += stage_cache.c
romstage-$(CONFIG_MMA) += mma_core.c

Expand All @@ -45,6 +44,13 @@ CPPFLAGS_common += -Isrc/drivers/intel/fsp1_1/include

cpu_incs-$(CONFIG_USE_GENERIC_FSP_CAR_INC) += $(src)/drivers/intel/fsp1_1/cache_as_ram.inc

postcar-y += stage_cache.c
ifneq ($(CONFIG_SKIP_FSP_CAR),y)
postcar-y += temp_ram_exit.c
postcar-y += exit_car.S
endif
postcar-y += fsp_util.c

# Add the FSP binary to the cbfs image
ifeq ($(CONFIG_HAVE_FSP_BIN),y)
cbfs-files-y += fsp.bin
Expand Down
170 changes: 0 additions & 170 deletions src/drivers/intel/fsp1_1/after_raminit.S

This file was deleted.

6 changes: 0 additions & 6 deletions src/drivers/intel/fsp1_1/cache_as_ram.inc
Expand Up @@ -147,12 +147,6 @@ before_romstage:
/* Call cache_as_ram_main(struct cache_as_ram_params *) */
call cache_as_ram_main

/* One will never return from cache_as_ram_main() in verstage so there's
* no such thing as after RAM init. */
#if !ENV_VERSTAGE
#include "after_raminit.S"
#endif

movb $0x69, %ah
jmp .Lhlt

Expand Down
128 changes: 90 additions & 38 deletions src/drivers/intel/fsp1_1/car.c
Expand Up @@ -18,35 +18,96 @@
#include <cpu/x86/mtrr.h>
#include <fsp/car.h>
#include <fsp/util.h>
#include <fsp/memmap.h>
#include <program_loading.h>
#include <timestamp.h>

FSP_INFO_HEADER *fih_car CAR_GLOBAL;
#define ROMSTAGE_RAM_STACK_SIZE 0x5000

/* Save FSP_INFO_HEADER for TempRamExit() call in assembly. */
static inline void set_fih_car(FSP_INFO_HEADER *fih)
/* platform_enter_postcar() determines the stack to use after
* cache-as-ram is torn down as well as the MTRR settings to use,
* and continues execution in postcar stage. */
static void platform_enter_postcar(void)
{
/* This variable is written in the raw form because it's only
* ever accessed in code that that has the cache-as-ram enabled. The
* assembly routine which tears down cache-as-ram utilizes this
* variable for determining where to find FSP. */
fih_car = fih;
struct postcar_frame pcf;
size_t alignment;
uint32_t aligned_ram;

if (postcar_frame_init(&pcf, ROMSTAGE_RAM_STACK_SIZE))
die("Unable to initialize postcar frame.\n");
/* Cache the ROM as WP just below 4GiB. */
postcar_frame_add_mtrr(&pcf, CACHE_ROM_BASE, CACHE_ROM_SIZE,
MTRR_TYPE_WRPROT);

/* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
postcar_frame_add_mtrr(&pcf, 0, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);

/*
* +-------------------------+ Top of RAM (aligned)
* | System Management Mode |
* | code and data | Length: CONFIG_TSEG_SIZE
* | (TSEG) |
* +-------------------------+ SMM base (aligned)
* | |
* | Chipset Reserved Memory | Length: Multiple of CONFIG_TSEG_SIZE
* | |
* +-------------------------+ top_of_ram (aligned)
* | |
* | CBMEM Root |
* | |
* +-------------------------+
* | |
* | FSP Reserved Memory |
* | |
* +-------------------------+
* | |
* | Various CBMEM Entries |
* | |
* +-------------------------+ top_of_stack (8 byte aligned)
* | |
* | stack (CBMEM Entry) |
* | |
* +-------------------------+
*/

alignment = mmap_region_granularity();
aligned_ram = ALIGN_DOWN(romstage_ram_stack_bottom(), alignment);
postcar_frame_add_mtrr(&pcf, aligned_ram, alignment, MTRR_TYPE_WRBACK);

if (CONFIG(HAVE_SMI_HANDLER)) {
void *smm_base;
size_t smm_size;

/*
* Cache the TSEG region at the top of ram. This region is not
* restricted to SMM mode until SMM has been relocated. By
* setting the region to cacheable it provides faster access
* when relocating the SMM handler as well as using the TSEG
* region for other purposes.
*/
smm_region(&smm_base, &smm_size);
postcar_frame_add_mtrr(&pcf, (uintptr_t)smm_base, alignment,
MTRR_TYPE_WRBACK);
}

run_postcar_phase(&pcf);
}

asmlinkage void *cache_as_ram_main(struct cache_as_ram_params *car_params)
/* This is the romstage C entry for platforms without
CONFIG_C_ENVIRONMENT_BOOTBLOCK */
asmlinkage void cache_as_ram_main(struct cache_as_ram_params *car_params)
{
int i;
const int num_guards = 4;
const u32 stack_guard = 0xdeadbeef;
u32 *stack_base;
void *ram_stack;
u32 size;

/* Size of unallocated CAR. */
size = _car_region_end - _car_relocatable_data_end;
size = ALIGN_DOWN(size, 16);

stack_base = (u32 *) (_car_region_end - size);
stack_base = (u32 *)(_car_region_end - size);

for (i = 0; i < num_guards; i++)
stack_base[i] = stack_guard;
Expand All @@ -66,23 +127,20 @@ asmlinkage void *cache_as_ram_main(struct cache_as_ram_params *car_params)

display_mtrrs();

if (car_params->bootloader_car_start != CONFIG_DCACHE_RAM_BASE ||
car_params->bootloader_car_end !=
(CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)) {
if (car_params->bootloader_car_start != CONFIG_DCACHE_RAM_BASE
|| car_params->bootloader_car_end != (CONFIG_DCACHE_RAM_BASE
+ CONFIG_DCACHE_RAM_SIZE)) {
printk(BIOS_INFO, "CAR mismatch: %08x--%08x vs %08lx--%08lx\n",
CONFIG_DCACHE_RAM_BASE,
CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE,
(long)car_params->bootloader_car_start,
(long)car_params->bootloader_car_end);
CONFIG_DCACHE_RAM_BASE,
CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE,
(long)car_params->bootloader_car_start,
(long)car_params->bootloader_car_end);
}

car_soc_post_console_init();
car_mainboard_post_console_init();

set_fih_car(car_params->fih);

/* Return new stack value in RAM back to assembly stub. */
ram_stack = cache_as_ram_stage_main(car_params->fih);
cache_as_ram_stage_main(car_params->fih);

/* Check the stack. */
for (i = 0; i < num_guards; i++) {
Expand All @@ -91,11 +149,13 @@ asmlinkage void *cache_as_ram_main(struct cache_as_ram_params *car_params)
printk(BIOS_DEBUG, "Smashed stack detected in romstage!\n");
}

return ram_stack;
/* we don't return here */
platform_enter_postcar();
}

/* Entry point taken when romstage is called after a separate verstage. */
asmlinkage void *romstage_c_entry(void)
/* This is the romstage C entry for platforms with
CONFIG_C_ENVIRONMENT_BOOTBLOCK */
asmlinkage void romstage_c_entry(void)
{
/* Need to locate the current FSP_INFO_HEADER. The cache-as-ram
* is still enabled. We can directly access work buffer here. */
Expand All @@ -107,24 +167,16 @@ asmlinkage void *romstage_c_entry(void)
if (prog_locate(&fsp)) {
fih = NULL;
printk(BIOS_ERR, "Unable to locate %s\n", prog_name(&fsp));
} else
} else {
/* This leaks a mapping which this code assumes is benign as
* the flash is memory mapped CPU's address space. */
fih = find_fsp((uintptr_t)rdev_mmap_full(prog_rdev(&fsp)));
}

set_fih_car(fih);

/* Return new stack value in RAM back to assembly stub. */
return cache_as_ram_stage_main(fih);
}

asmlinkage void after_cache_as_ram(void *chipset_context)
{
timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_END);
printk(BIOS_DEBUG, "FspTempRamExit returned successfully\n");
display_mtrrs();
cache_as_ram_stage_main(fih);

after_cache_as_ram_stage();
/* we don't return here */
platform_enter_postcar();
}

void __weak car_mainboard_pre_console_init(void)
Expand Down
27 changes: 27 additions & 0 deletions src/drivers/intel/fsp1_1/exit_car.S
@@ -0,0 +1,27 @@
/*
* This file is part of the coreboot project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/


.text
.global chipset_teardown_car
chipset_teardown_car:

pop %ebx
/* Move the stack pointer to real ram */
movl post_car_stack_top, %esp
/* Align the stack 16 bytes */
andl $0xfffffff0, %esp

call chipset_teardown_car_main

jmp *%ebx
8 changes: 3 additions & 5 deletions src/drivers/intel/fsp1_1/include/fsp/car.h
Expand Up @@ -30,14 +30,12 @@ struct cache_as_ram_params {
};

/* Entry points from the cache-as-ram assembly code. */
asmlinkage void *cache_as_ram_main(struct cache_as_ram_params *car_params);
asmlinkage void after_cache_as_ram(void *chipset_context);
asmlinkage void *romstage_c_entry(void);
asmlinkage void cache_as_ram_main(struct cache_as_ram_params *car_params);
asmlinkage void romstage_c_entry(void);
/* Per stage calls from the above two functions. The void * return from
* cache_as_ram_stage_main() is the stack pointer to use in RAM after
* exiting cache-as-ram mode. */
void *cache_as_ram_stage_main(FSP_INFO_HEADER *fih);
void after_cache_as_ram_stage(void);
void cache_as_ram_stage_main(FSP_INFO_HEADER *fih);

/* Mainboard and SoC initialization prior to console. */
void car_mainboard_pre_console_init(void);
Expand Down
38 changes: 1 addition & 37 deletions src/drivers/intel/fsp1_1/include/fsp/romstage.h
Expand Up @@ -42,41 +42,6 @@ struct romstage_params {
const void *data_to_save;
};

/*
* FSP Boot Flow:
* 1. src/cpu/x86/16bit/reset.inc
* 2. src/cpu/x86/16bit/entry.inc
* 3. other modules
* 4. src/drivers/intel/fsp1_1/cache_as_ram.inc
* 5. src/drivers/intel/fsp1_1/fsp_util.c/find_fsp
* 6. FSP binary/TempRamInit
* 7. src/drivers/intel/fsp1_1/cache_as_ram.inc - return
* 8. src/soc/intel/common/romstage.c/romstage_main
* 9 src/soc/.../romstage/.../soc_pre_console_init
* 10 src/console/console.c/console_init
* 11 src/soc/.../romstage/.../soc_romstage_init
* 12. src/mainboard/.../romstage.c/mainboard_romstage_entry
* 13. src/soc/intel/common/romstage.c/romstage_common
* 14 src/soc/.../romstage/.../soc_pre_raminit
* 15. FSP binary/MemoryInit
* 16. src/soc/intel/common/romstage.c/romstage_common - return
* 17. src/mainboard/.../romstage.c/mainboard_romstage_entry - return
* 18. src/soc/intel/common/romstage.c/romstage_main - return
* 19. src/soc/intel/common/stack.c/setup_stack_and_mtrrs
* 20. src/drivers/intel/fsp1_1/cache_as_ram.inc - return, cleanup
* after call to romstage_main
* 21. FSP binary/TempRamExit
* 22. src/soc/intel/common/romstage.c/romstage_after_car
* 23. FSP binary/SiliconInit
* 24. src/soc/intel/common/romstage.c/romstage_after_car - return
* 25. src/drivers/intel/fsp1_1/fsp_util.c/fsp_notify_boot_state_callback
* 26. src/drivers/intel/fsp1_1/fsp_util.c/fsp_notify
* 27. FSP binary/FspNotify
* 28. src/drivers/intel/fsp1_1/fsp_util.c/fsp_notify_boot_state_callback
* 29. src/drivers/intel/fsp1_1/fsp_util.c/fsp_notify
* 30. FSP binary/FspNotify
*/

void mainboard_memory_init_params(struct romstage_params *params,
MEMORY_INIT_UPD *memory_params);
void mainboard_romstage_entry(struct romstage_params *params);
Expand All @@ -87,10 +52,9 @@ void mainboard_add_dimm_info(struct romstage_params *params,
void raminit(struct romstage_params *params);
void report_memory_config(void);
void romstage_common(struct romstage_params *params);
asmlinkage void *romstage_main(FSP_INFO_HEADER *fih);
asmlinkage void romstage_main(FSP_INFO_HEADER *fih);
/* Initialize memory margin analysis settings. */
void setup_mma(MEMORY_INIT_UPD *memory_upd);
void *setup_stack_and_mtrrs(void);
void soc_after_ram_init(struct romstage_params *params);
void soc_display_memory_init_params(const MEMORY_INIT_UPD *old,
MEMORY_INIT_UPD *new);
Expand Down
4 changes: 4 additions & 0 deletions src/drivers/intel/fsp1_1/include/fsp/util.h
Expand Up @@ -17,6 +17,8 @@
#ifndef FSP1_1_UTIL_H
#define FSP1_1_UTIL_H

#include <rules.h>
#include <arch/cpu.h>
#include <fsp/api.h>
/* Current users expect to get the SoC's FSP definitions by including util.h. */
#include <fsp/soc_binding.h>
Expand Down Expand Up @@ -107,4 +109,6 @@ void *get_first_guid_hob(const EFI_GUID *guid);
__attribute__((cdecl)) size_t fsp_write_line(uint8_t *buffer,
size_t number_of_bytes);

asmlinkage void chipset_teardown_car_main(void);

#endif /* FSP1_1_UTIL_H */
17 changes: 10 additions & 7 deletions src/drivers/intel/fsp1_1/raminit.c
Expand Up @@ -130,7 +130,8 @@ void raminit(struct romstage_params *params)

printk(BIOS_DEBUG, "FspMemoryInit returned 0x%08x\n", status);
if (status != EFI_SUCCESS)
die("ERROR - FspMemoryInit failed to initialize memory!\n");
die_with_post_code(POST_RAM_FAILURE,
"ERROR - FspMemoryInit failed to initialize memory!\n");

/* Locate the FSP reserved memory area */
fsp_reserved_bytes = 0;
Expand Down Expand Up @@ -195,9 +196,6 @@ void raminit(struct romstage_params *params)
}

#if CONFIG(DISPLAY_HOBS)
if (hob_list_ptr == NULL)
die("ERROR - HOB pointer is NULL!\n");

/*
* Verify that FSP is generating the required HOBs:
* 7.1: FSP_BOOTLOADER_TEMP_MEMORY_HOB only produced for FSP 1.0
Expand Down Expand Up @@ -244,7 +242,10 @@ void raminit(struct romstage_params *params)
"ERROR - Missing one or more required FSP HOBs!\n");

/* Display the HOBs */
print_hob_type_structure(0, hob_list_ptr);
if (hob_list_ptr != NULL)
print_hob_type_structure(0, hob_list_ptr);
else
printk(BIOS_ERR, "ERROR - HOB pointer is NULL!\n");
#endif

/* Get the address of the CBMEM region for the FSP reserved memory */
Expand Down Expand Up @@ -274,14 +275,16 @@ void raminit(struct romstage_params *params)
printk(BIOS_DEBUG,
"0x%08x: Chipset reserved bytes reported by FSP\n",
(unsigned int)delta_bytes);
die("Please verify the chipset reserved size\n");
die_with_post_code(POST_INVALID_VENDOR_BINARY,
"Please verify the chipset reserved size\n");
}
#endif
}

/* Verify the FSP 1.1 HOB interface */
if (fsp_verification_failure)
die("ERROR - coreboot's requirements not met by FSP binary!\n");
die_with_post_code(POST_INVALID_VENDOR_BINARY,
"ERROR - coreboot's requirements not met by FSP binary!\n");

/* Display the memory configuration */
report_memory_config();
Expand Down
27 changes: 3 additions & 24 deletions src/drivers/intel/fsp1_1/romstage.c
Expand Up @@ -38,9 +38,8 @@
#include <timestamp.h>
#include <vendorcode/google/chromeos/chromeos.h>

asmlinkage void *romstage_main(FSP_INFO_HEADER *fih)
asmlinkage void romstage_main(FSP_INFO_HEADER *fih)
{
void *top_of_stack;
struct romstage_params params = {
.chipset_context = fih,
};
Expand Down Expand Up @@ -72,17 +71,11 @@ asmlinkage void *romstage_main(FSP_INFO_HEADER *fih)
mainboard_romstage_entry(&params);
soc_after_ram_init(&params);
post_code(0x38);

top_of_stack = setup_stack_and_mtrrs();

printk(BIOS_DEBUG, "Calling FspTempRamExit API\n");
timestamp_add_now(TS_FSP_TEMP_RAM_EXIT_START);
return top_of_stack;
}

void *cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
void cache_as_ram_stage_main(FSP_INFO_HEADER *fih)
{
return romstage_main(fih);
romstage_main(fih);
}

/* Entry from the mainboard. */
Expand Down Expand Up @@ -161,13 +154,6 @@ void romstage_common(struct romstage_params *params)
full_reset();
}

void after_cache_as_ram_stage(void)
{
/* Load the ramstage. */
run_ramstage();
die("ERROR - Failed to load ramstage!");
}

/* Initialize the power state */
__weak struct chipset_power_state *fill_power_state(void)
{
Expand Down Expand Up @@ -340,13 +326,6 @@ __weak void report_memory_config(void)
{
}

/* Choose top of stack and setup MTRRs */
__weak void *setup_stack_and_mtrrs(void)
{
die("ERROR - Must specify top of stack!\n");
return NULL;
}

/* SOC initialization after RAM is enabled */
__weak void soc_after_ram_init(struct romstage_params *params)
{
Expand Down