@@ -1,6 +1,6 @@
# Supermicro X11SSH-F
# Supermicro X11SSH-F/X11SSH-LN4F

This section details how to run coreboot on the [Supermicro X11SSH-F].
This section details how to run coreboot on the [Supermicro X11SSH-F] or [Supermicro X11SSH-LN4F].

## Flashing coreboot

Expand Down Expand Up @@ -43,6 +43,11 @@ tasks, or for offloading graphics rendering via "muxless" [vga_witcheroo].
- S3 resume not working (vendor and coreboot)
- SeaBIOS cannot make use of VGA on Aspeed (even if IGD is disabled)

## Difference between X11SSH-F and X11SSH-LN4F

The PCB is identical. The X11SSH-F has 2 NICs, the X11SSH-LN4F has 4 NICs.
So the X11SSH-F just doesn't have 2 NICs populated.

## ToDo

- Fix known issues
Expand All @@ -60,7 +65,8 @@ tasks, or for offloading graphics rendering via "muxless" [vga_witcheroo].
+------------------+--------------------------------------------------+
| Super I/O | ASPEED AST2400 |
+------------------+--------------------------------------------------+
| Ethernet | 2x Intel I210-AT 1 GbE |
| Ethernet | 2x Intel I210-AT 1 GbE (for X11SSH-F) |
| | 4x Intel I210-AT 1 GbE (for X11SSH-LN4F) |
| | 1x dedicated BMC |
+------------------+--------------------------------------------------+
| PCIe slots | 1x 3.0 x8 |
Expand Down Expand Up @@ -95,6 +101,7 @@ tasks, or for offloading graphics rendering via "muxless" [vga_witcheroo].
- [Board manual]

[Supermicro X11SSH-F]: https://www.supermicro.com/en/products/motherboard/X11SSH-F
[Supermicro X11SSH-LN4F]: https://www.supermicro.com/en/products/motherboard/X11SSH-LN4F
[Board manual]: https://www.supermicro.com/manuals/motherboard/C236/MNL-1778.pdf
[AST2400]: https://www.aspeedtech.com/products.php?fPath=20&rId=376
[IPMI]: ../../../../drivers/ipmi_kcs.md
Expand Down
72 changes: 72 additions & 0 deletions Documentation/mainboard/system76/gaze15.md
@@ -0,0 +1,72 @@
# System76 Gazelle 15 (gaze15)

## Specs

- CPU
- Intel Core i7 10750H
- EC
- ITE5570E running https://github.com/system76/ec
- Graphics
- Intel UHD Graphics
- NVIDIA GeForce GTX 1650/1650 Ti/1660 Ti
- eDP 15.6" or 17.3" 1920x1080 @ 120 Hz LCD
- HDMI, Mini DisplayPort 1.4, and DisplayPort 1.4 over USB-C
- Memory
- Channel 0: 8-GB/16-GB/32-GB DDR4 SO-DIMM
- Channel 1: 8-GB/16-GB/32-GB DDR4 SO-DIMM
- Networking
- Gigabit Ethernet
- M.2 PCIe/CNVi Wifi/Bluetooth
- Intel Wireless-AC 9560, or
- Intel Wi-Fi 6 AX200/AX201
- Power
- 120W AC adapter (GTX 1650 and 1650 Ti)
- 180W AC adapter (GTX 1660 Ti)
- 48.96Wh battery
- Sound
- Realtek ALC293 codec
- TAS5825MRHBR smart AMP
- Internal speakers and microphone
- Combined headphone and microphone 3.5mm jack
- HDMI, Mini DisplayPort, USB-C DP audio
- Storage
- M.2 PCIe/SATA SSD-1
- M.2 PCIe SSD-2
- 2.5" 7mm drive bay
- SD card reader
- Realtek RTL8411B card reader
- USB
- 1x USB 2.0
- 1x USB 3.0
- 1x USB 3.1
- 1x USB 3.2 Type-C

## Building coreboot

```bash
make distclean
make defconfig KBUILD_DEFCONFIG=configs/config.system76_gaze15
make
```

## Flashing coreboot

```eval_rst
+---------------------+---------------------+
| Type | Value |
+=====================+=====================+
| Socketed flash | no |
+---------------------+---------------------+
| Vendor | GigaDevice |
+---------------------+---------------------+
| Model | GD25Q127C/GD25Q128C |
+---------------------+---------------------+
| Size | 16 MiB |
+---------------------+---------------------+
| Package | SOIC-8 |
+---------------------+---------------------+
| Internal flashing | yes |
+---------------------+---------------------+
| External flashing | yes |
+---------------------+---------------------+
```
5 changes: 3 additions & 2 deletions Documentation/releases/checklist.md
Expand Up @@ -177,8 +177,9 @@ commit db508565d2483394b709654c57533e55eebace51 (HEAD, tag: 4.6, origin/master,
...
````

When you used the script to generate the release, a tag was generated in the tree that was downloaded.
From the coreboot-X.Y tree, just run: `git push -f origin <TAG (X.Y)>`
When you used the script to generate the release, a signed tag was generated in the
tree that was downloaded. From the coreboot-X.Y tree, just run: `git push origin X.Y`.
In case you pushed the wrong tag already, you have to force push the new one.

You will need write access for tags to the coreboot git repo to do this.

Expand Down
39 changes: 39 additions & 0 deletions Documentation/releases/coreboot-4.14-relnotes.md
Expand Up @@ -10,6 +10,45 @@ Update this document with changes that should be in the release notes.
* The chip and board additions and removals will be updated right
before the release, so those do not need to be added.

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

### SAR support in VPD for Chrome OS

SAR support in VPD has been deprecated for Chrome OS platforms for > 1
year now. All new Chrome OS platforms have switched to using SAR
tables from CBFS. For the next release, coreboot is updated to align
with the Chrome OS factory changes and hence SAR support in VPD is
deprecated in [CB:51483](https://review.coreboot.org/51483). Starting
with this release, anyone building coreboot for an already released
Chrome OS platform with SAR table in VPD will have to extract the
"wifi_sar" key from VPD and add it as a file to CBFS using following
steps:
* On DUT, read SAR value using `vpd -i RO_VPD -g wifi_sar`
* In coreboot repo, generate CBFS SAR file using:
`echo ${SAR_STRING} > site-local/${BOARD}-sar.hex`
* Add to site-local/Kconfig:
```
config WIFI_SAR_CBFS_FILEPATH
string
default "site-local/${BOARD}-sar.hex"
```
### CBFS stage file format change
[CB:46484](https://review.coreboot.org/46484) changed the in-flash
file format of coreboot stages to prepare for per-file signature
verification. As described in the commit message in more details,
when manipulating stages in a CBFS, the cbfstool build must match the
coreboot image so that they're using the same format: coreboot.rom
and cbfstool must be built from coreboot sources that either both
contain this change or both do not contain this change.
Since stages are usually only handled by the coreboot build system
which builds its own cbfstool (and therefore it always matches
coreboot.rom) this shouldn't be a concern in the vast majority of
scenarios.
Significant changes
-------------------
Expand Down
4 changes: 3 additions & 1 deletion Documentation/security/vboot/list_vboot.md
Expand Up @@ -154,7 +154,9 @@
- Stout (Lenovo Thinkpad X131e Chromebook)
- Bubs
- Coachz
- Homestar
- Lazor
- Marzipan
- Pompom
- Trogdor
- Veyron_Jaq (Haier Chromebook 11)
Expand Down Expand Up @@ -253,7 +255,7 @@
## Supermicro
- X11SSH-TF
- X11SSM-F
- X11SSH-F
- X11SSH-F/X11SSH-LN4F

## UP
- Squared
1 change: 1 addition & 0 deletions Documentation/tutorial/index.md
Expand Up @@ -3,3 +3,4 @@
* [Part 1: Starting from scratch](part1.md)
* [Part 2: Submitting a patch to coreboot.org](part2.md)
* [Part 3: Writing unit tests](part3.md)
* [Managing local additions](managing_local_additions.md)
43 changes: 43 additions & 0 deletions Documentation/tutorial/managing_local_additions.md
@@ -0,0 +1,43 @@
Managing local additions
========================

This section describes the site-local mechanism, what it is good for and
how it can be used.

What is site-local?
-------------------
site-local is the name of a directory that won't ever appear in the
upstream coreboot repository but is referred to in several key places of its
configuration and build system. The intent is provide a single location to
store local modifications.

By keeping local additions to builds in this place, it can be versioned
independently from upstream (e.g. controlled by git in another repository)
and any changes made there won't ever conflict with upstream changes.

This optional directory is searched for in the top-level of the coreboot
repo and is called `site-local`.

Integration into the configuration system
-----------------------------------------
Kconfig includes `site-local/Kconfig` relatively early, so it can be used
to pre-define some configuration before coreboot's regular ruleset sets
up defaults.

Integration into the build system
---------------------------------
The build system includes, if present, `site-local/Makefile.inc`. The main
purpose so far has been to add additional files to a CBFS image. A single
Makefile.inc can serve multiple boards, for example:

cbfs-files-$(CONFIG_BOARD_INTEL_D945GCLF) += pci8086,2772.rom
pci8086,2772.rom-file := intel_d945gclf/pci8086,2772.rom
pci8086,2772.rom-type := optionrom

cbfs-files-$(CONFIG_BOARD_KONTRON_986LCD_M) += pci8086,27a2.rom
pci8086,27a2.rom-file := kontron_986lcd-m/pci8086,27a2.rom
pci8086,27a2.rom-type := optionrom

This adds the correct Option ROM binary (which are non-redistributable and
therefore can't become part of the coreboot.org repos) to coreboot.rom when
built for intel/d945gclf or kontron/986lcd-m.
11 changes: 11 additions & 0 deletions MAINTAINERS
Expand Up @@ -614,6 +614,12 @@ M: Hung-Te Lin <hungte@chromium.org>
S: Supported
F: src/soc/mediatek/

MEDIATEK MT8192
M: Xi Chen <xixi.chen@mediatek.com>
S: Maintained
F: src/soc/mediatek/mt8192/
F: src/vendorcode/mediatek/mt8192/

ORPHANED ARM SOCS
S: Orphaned
F: src/cpu/armltd/
Expand Down Expand Up @@ -798,6 +804,11 @@ M: Wim Vervoorn <wvervoorn@eltan.com>
S: Maintained
F: src/vendorcode/eltan/

TESTS
M: Jakub Czapiga <jacz@semihalf.com>
S: Maintained
F: tests/

MISSING: TIMERS / DELAYS

MISSING: TIMESTAMPS
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Expand Up @@ -13,6 +13,8 @@ objutil ?= $(obj)/util
objk := $(objutil)/kconfig
absobj := $(abspath $(obj))

additional-dirs :=

VBOOT_HOST_BUILD ?= $(abspath $(objutil)/vboot_lib)

COREBOOT_EXPORTS := COREBOOT_EXPORTS
Expand Down
15 changes: 7 additions & 8 deletions Makefile.inc
Expand Up @@ -42,13 +42,15 @@ COREBOOT_EXPORTS += MAINBOARDDIR VARIANT_DIR CARRIER_DIR
## rom image file, are placed under $(objcbfs).
## These typically have suffixes .debug .elf .bin and .map
objcbfs := $(obj)/cbfs/$(CONFIG_CBFS_PREFIX)
additional-dirs += $(objcbfs)
COREBOOT_EXPORTS += objcbfs

## Based on the active configuration, Makefile conditionally collects
## the required assembly includes and saves them in a file.
## Such files that do not have a clear one-to-one relation to a source
## file under src/ are placed and built under $(objgenerated)
objgenerated := $(obj)/generated
additional-dirs += $(objgenerated)
COREBOOT_EXPORTS += objgenerated

## CCACHE_EXTRAFILES can be set by individual rules to help CCACHE
Expand All @@ -58,7 +60,7 @@ COREBOOT_EXPORTS += CCACHE_EXTRAFILES
#######################################################################
# root rule to resolve if in build mode (ie. configuration exists)
real-target: $(obj)/config.h coreboot files_added
coreboot: build-dirs $(obj)/coreboot.rom $(obj)/cbfstool $(obj)/rmodtool $(obj)/ifwitool
coreboot: $(obj)/coreboot.rom $(obj)/cbfstool $(obj)/rmodtool $(obj)/ifwitool

# This target can be used in site local to run scripts or additional
# targets after the build completes by creating a Makefile.inc in the
Expand All @@ -73,7 +75,7 @@ files_added:: build_complete

#######################################################################
# our phony targets
PHONY+= clean-abuild coreboot check-style build-dirs build_complete
PHONY+= clean-abuild coreboot check-style build_complete

#######################################################################
# root source directories of coreboot
Expand Down Expand Up @@ -335,7 +337,7 @@ endef
cbfs-files-processor-struct= \
$(eval $(2): $(1) $(obj)/build.h $(KCONFIG_AUTOHEADER); \
printf " CC+STRIP $(1)\n"; \
$(CC_ramstage) -MMD $(CPPFLAGS_ramstage) $(CFLAGS_ramstage) $$(ramstage-c-ccopts) -include $(KCONFIG_AUTOHEADER) -MT $(2) -o $(2).tmp -c $(1) && \
$(CC_ramstage) -MMD $(CPPFLAGS_ramstage) $(CFLAGS_ramstage) --param asan-globals=0 $$(ramstage-c-ccopts) -include $(KCONFIG_AUTOHEADER) -MT $(2) -o $(2).tmp -c $(1) && \
$(OBJCOPY_ramstage) -O binary --set-section-flags .bss*=alloc,contents,load $(2).tmp $(2); \
rm -f $(2).tmp) \
$(eval DEPENDENCIES += $(2).d)
Expand Down Expand Up @@ -508,7 +510,7 @@ ifeq ($(CONFIG_DEBUG_ADA_CODE),y)
ADAFLAGS_common += -gnata
endif

additional-dirs := $(objutil)/cbfstool $(objutil)/ifdtool \
additional-dirs += $(objutil)/cbfstool $(objutil)/ifdtool \
$(objutil)/options $(objutil)/amdfwtool \
$(objutil)/cbootimage

Expand Down Expand Up @@ -536,9 +538,6 @@ $(build_h): $$(shell $$(build_h_check))
@printf " GEN build.h\n"
mv $< $@

build-dirs $(objcbfs) $(objgenerated):
mkdir -p $(objcbfs) $(objgenerated)

$(obj)/build_info:
@echo 'COREBOOT_VERSION: $(call strip_quotes,$(KERNELVERSION))' > $@.tmp
@echo 'MAINBOARD_VENDOR: $(call strip_quotes,$(CONFIG_MAINBOARD_VENDOR))' >> $@.tmp
Expand Down Expand Up @@ -770,7 +769,7 @@ $(objcbfs)/bootblock.raw.bin: $(objcbfs)/bootblock.raw.elf
$(OBJCOPY_bootblock) -O binary $< $@

ifneq ($(CONFIG_HAVE_BOOTBLOCK),y)
$(objcbfs)/bootblock.bin: $(objcbfs)
$(objcbfs)/bootblock.bin:
dd if=/dev/zero of=$@ bs=64 count=1
endif

Expand Down
1 change: 1 addition & 0 deletions configs/config.emulation_qemu_x86_i440fx_asan
@@ -0,0 +1 @@
CONFIG_ASAN=y
4 changes: 4 additions & 0 deletions configs/config.emulation_qemu_x86_q35_smm_tseg
@@ -0,0 +1,4 @@
CONFIG_BOARD_EMULATION_QEMU_X86_Q35=y
CONFIG_CPU_QEMU_X86_PARALLEL_MP=y
CONFIG_CPU_QEMU_X86_TSEG_SMM=y
CONFIG_CPU_QEMU_X86_SMMLOADERV2=y
32 changes: 32 additions & 0 deletions configs/config.google_volteer.build_test_purposes
@@ -0,0 +1,32 @@
# Not meant for actual use, but rather to build-test individual options.
# If keeping this combination of options buildable becomes too hard in
# the future, then this config can be split into several smaller chunks.
# Exercises, among other things:
# + Debug options
# + Crashlog
# + Flashconsole
CONFIG_VENDOR_GOOGLE=y
CONFIG_CONSOLE_POST=y
CONFIG_BOARD_GOOGLE_VOLTEER=y
CONFIG_USE_LEGACY_8254_TIMER=y
CONFIG_INTEL_TME=y
CONFIG_SOC_INTEL_CRASHLOG=y
CONFIG_NO_GFX_INIT=y
CONFIG_DISPLAY_HOBS=y
CONFIG_DISPLAY_UPD_DATA=y
CONFIG_CONSOLE_SPI_FLASH=y
CONFIG_DEFAULT_CONSOLE_LOGLEVEL_8=y
CONFIG_DISPLAY_MTRRS=y
CONFIG_DISPLAY_FSP_CALLS_AND_STATUS=y
CONFIG_DISPLAY_FSP_HEADER=y
CONFIG_VERIFY_HOBS=y
CONFIG_FATAL_ASSERTS=y
CONFIG_DEBUG_GPIO=y
CONFIG_DEBUG_CBFS=y
CONFIG_DEBUG_SMBUS=y
CONFIG_DEBUG_SMI=y
CONFIG_DEBUG_PERIODIC_SMI=y
CONFIG_DEBUG_MALLOC=y
CONFIG_DEBUG_CONSOLE_INIT=y
CONFIG_DEBUG_SPI_FLASH=y
CONFIG_DEBUG_BOOT_STATE=y
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
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.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
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_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
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.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
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.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu6
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.4"
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU6=y
Expand Down
5 changes: 5 additions & 0 deletions configs/config.system76_gaze15
@@ -0,0 +1,5 @@
CONFIG_VENDOR_SYSTEM76=y
CONFIG_BOARD_SYSTEM76_GAZE15=y
CONFIG_PAYLOAD_TIANOCORE=y
CONFIG_RUN_FSP_GOP=y
CONFIG_SMMSTORE=y
4 changes: 2 additions & 2 deletions payloads/external/LinuxBoot/Kconfig
Expand Up @@ -253,10 +253,10 @@ config LINUXBOOT_UROOT_SHELL

config LINUXBOOT_UROOT_COMMANDS
string "U-root commands"
default "coreboot-app"
default "boot coreboot-app"
help
List of additional modules to include,
separated by space. (default "coreboot-app")
separated by space. (default "boot coreboot-app")

endif #LINUXBOOT_UROOT

Expand Down
1 change: 1 addition & 0 deletions src/acpi/Makefile.inc
Expand Up @@ -6,6 +6,7 @@ ramstage-y += acpi.c
ramstage-y += acpigen.c
ramstage-y += acpigen_dptf.c
ramstage-y += acpigen_dsm.c
ramstage-$(CONFIG_PCI) += acpigen_pci.c
ramstage-y += acpigen_ps2_keybd.c
ramstage-y += acpigen_usb.c
ramstage-y += device.c
Expand Down
21 changes: 21 additions & 0 deletions src/acpi/acpi.c
Expand Up @@ -638,6 +638,21 @@ unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
return andd->length;
}

unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags,
u16 segment, const char *device_scope)
{
dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
int satc_len = sizeof(dmar_satc_entry_t) + strlen(device_scope) + 1;
memset(satc, 0, satc_len);
satc->type = DMAR_SATC;
satc->length = satc_len;
satc->flags = flags;
satc->segment_number = segment;
memcpy(&satc->device_scope, device_scope, strlen(device_scope));

return satc->length;
}

void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
{
dmar_entry_t *drhd = (dmar_entry_t *)base;
Expand All @@ -656,6 +671,12 @@ void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
atsr->length = current - base;
}

void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
{
dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
satc->length = current - base;
}

static unsigned long acpi_create_dmar_ds(unsigned long current,
enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
{
Expand Down
21 changes: 2 additions & 19 deletions src/acpi/acpigen.c
Expand Up @@ -18,8 +18,6 @@
#include <assert.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <device/pci_type.h>
#include <device/soundwire.h>
#include <types.h>

Expand Down Expand Up @@ -1424,8 +1422,10 @@ void acpigen_write_if_lequal_namestr_int(const char *namestr, uint64_t val)
acpigen_write_integer(val);
}

/* Closes previously opened if statement and generates ACPI code for else statement. */
void acpigen_write_else(void)
{
acpigen_pop_len();
acpigen_emit_byte(ELSE_OP);
acpigen_write_len_f();
}
Expand Down Expand Up @@ -2033,23 +2033,6 @@ void acpigen_write_ADR(uint64_t adr)
acpigen_write_name_qword("_ADR", adr);
}

void acpigen_write_ADR_pci_devfn(pci_devfn_t devfn)
{
/*
* _ADR for PCI Bus is encoded as follows:
* [63:32] - unused
* [31:16] - device #
* [15:0] - function #
*/
acpigen_write_ADR(PCI_SLOT(devfn) << 16 | PCI_FUNC(devfn));
}

void acpigen_write_ADR_pci_device(const struct device *dev)
{
assert(dev->path.type == DEVICE_PATH_PCI);
acpigen_write_ADR_pci_devfn(dev->path.pci.devfn);
}

/**
* acpigen_write_ADR_soundwire_device() - SoundWire ACPI Device Address Encoding.
* @address: SoundWire device address properties.
Expand Down
1 change: 0 additions & 1 deletion src/acpi/acpigen_dsm.c
Expand Up @@ -22,7 +22,6 @@ static void i2c_hid_func0_cb(void *arg)
acpigen_write_if_lequal_op_int(LOCAL2_OP, 0x1);
/* Return (Buffer (One) { 0x3 }) */
acpigen_write_return_singleton_buffer(0x3);
acpigen_pop_len(); /* Pop : If */
/* Else */
acpigen_write_else();
/* Return (Buffer (One) { 0x0 }) */
Expand Down
57 changes: 57 additions & 0 deletions src/acpi/acpigen_pci.c
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpigen.h>
#include <acpi/acpigen_pci.h>
#include <assert.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <device/pci_type.h>
#include <types.h>

void acpigen_write_ADR_pci_devfn(pci_devfn_t devfn)
{
/*
* _ADR for PCI Bus is encoded as follows:
* [63:32] - unused
* [31:16] - device #
* [15:0] - function #
*/
acpigen_write_ADR(PCI_SLOT(devfn) << 16 | PCI_FUNC(devfn));
}

void acpigen_write_ADR_pci_device(const struct device *dev)
{
assert(dev->path.type == DEVICE_PATH_PCI);
acpigen_write_ADR_pci_devfn(dev->path.pci.devfn);
}

void acpigen_write_PRT_GSI_entry(unsigned int pci_dev, unsigned int acpi_pin, unsigned int gsi)
{
acpigen_write_package(4);
acpigen_write_dword((pci_dev << 16) | 0xffff);
acpigen_write_byte(acpi_pin);

/* Source */
acpigen_write_byte(0);

/* Source Index */
acpigen_write_dword(gsi);

acpigen_pop_len(); /* Package */
}

void acpigen_write_PRT_source_entry(unsigned int pci_dev, unsigned int acpi_pin,
const char *source_path, unsigned int index)
{
acpigen_write_package(4);
acpigen_write_dword((pci_dev << 16) | 0xffff);
acpigen_write_byte(acpi_pin);

/* Source */
acpigen_emit_namestring(source_path);

/* Source Index */
acpigen_write_dword(index);

acpigen_pop_len(); /* Package */
}
1 change: 1 addition & 0 deletions src/acpi/device.c
Expand Up @@ -5,6 +5,7 @@
#include <acpi/acpi.h>
#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <acpi/acpigen_pci.h>
#include <device/device.h>
#include <device/path.h>
#include <stdlib.h>
Expand Down
6 changes: 0 additions & 6 deletions src/arch/arm64/bl31.c
Expand Up @@ -76,9 +76,6 @@ void run_bl31(u64 payload_entry, u64 payload_arg0, u64 payload_spsr)
struct prog bl31 = PROG_INIT(PROG_BL31, CONFIG_CBFS_PREFIX"/bl31");
void (*bl31_entry)(bl_params_t *params, void *plat_params) = NULL;

if (prog_locate(&bl31))
die("BL31 not found");

if (!selfload_check(&bl31, BM_MEM_BL31))
die("BL31 load failed");
bl31_entry = prog_entry(&bl31);
Expand All @@ -87,9 +84,6 @@ void run_bl31(u64 payload_entry, u64 payload_arg0, u64 payload_spsr)
struct prog bl32 = PROG_INIT(PROG_BL32,
CONFIG_CBFS_PREFIX"/secure_os");

if (prog_locate(&bl32))
die("BL32 not found");

if (cbfs_prog_stage_load(&bl32))
die("BL32 load failed");

Expand Down
3 changes: 0 additions & 3 deletions src/arch/riscv/boot.c
Expand Up @@ -53,9 +53,6 @@ void arch_prog_run(struct prog *prog)
if (ENV_RAMSTAGE && CONFIG(RISCV_OPENSBI)) {
struct prog sbi = PROG_INIT(PROG_OPENSBI, CONFIG_CBFS_PREFIX"/opensbi");

if (prog_locate(&sbi))
die("OpenSBI not found");

if (!selfload_check(&sbi, BM_MEM_OPENSBI))
die("OpenSBI load failed");

Expand Down
6 changes: 3 additions & 3 deletions src/arch/x86/bootblock_normal.c
Expand Up @@ -12,7 +12,7 @@ static const char *get_fallback(const char *stagelist)
return ++stagelist;
}

int legacy_romstage_selector(struct prog *romstage)
int legacy_romstage_select_and_load(struct prog *romstage)
{
static const char *default_filenames = "normal/romstage\0fallback/romstage";
const char *boot_candidate;
Expand All @@ -24,10 +24,10 @@ int legacy_romstage_selector(struct prog *romstage)

if (do_normal_boot()) {
romstage->name = boot_candidate;
if (!prog_locate(romstage))
if (!cbfs_prog_stage_load(romstage))
return 0;
}

romstage->name = get_fallback(boot_candidate);
return prog_locate(romstage);
return cbfs_prog_stage_load(romstage);
}
3 changes: 0 additions & 3 deletions src/arch/x86/postcar_loader.c
Expand Up @@ -135,9 +135,6 @@ static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)

vboot_run_logic();

if (prog_locate(prog))
die_with_post_code(POST_INVALID_ROM,
"Failed to locate after CAR program.\n");
if (rmodule_stage_load(&rsl))
die_with_post_code(POST_INVALID_ROM,
"Failed to load after CAR program.\n");
Expand Down
9 changes: 2 additions & 7 deletions src/arch/x86/smbios.c
Expand Up @@ -283,6 +283,7 @@ static int create_smbios_type17_for_dimm(struct dimm_info *dimm,

smbios_fill_dimm_manufacturer_from_id(dimm->mod_id, t);
smbios_fill_dimm_serial_number(dimm, t);
smbios_fill_dimm_asset_tag(dimm, t);
smbios_fill_dimm_locator(dimm, t);

/* put '\0' in the end of data */
Expand Down Expand Up @@ -442,12 +443,6 @@ static int get_socket_type(void)
return 0x02; /* Unknown */
}

unsigned int __weak smbios_memory_error_correction_type(struct memory_info *meminfo)
{
return meminfo->ecc_capable ?
MEMORY_ARRAY_ECC_SINGLE_BIT : MEMORY_ARRAY_ECC_NONE;
}

unsigned int __weak smbios_processor_external_clock(void)
{
return 0; /* Unknown */
Expand Down Expand Up @@ -1023,7 +1018,7 @@ static int smbios_write_type16(unsigned long *current, int *handle)

t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
t->use = MEMORY_ARRAY_USE_SYSTEM;
t->memory_error_correction = smbios_memory_error_correction_type(meminfo);
t->memory_error_correction = meminfo->ecc_type;

/* no error information handle available */
t->memory_error_information_handle = 0xFFFE;
Expand Down
11 changes: 10 additions & 1 deletion src/arch/x86/smbios_defaults.c
Expand Up @@ -18,6 +18,15 @@ __weak void smbios_fill_dimm_locator(const struct dimm_info *dimm, struct smbios
t->bank_locator = smbios_add_string(t->eos, locator);
}

__weak void smbios_fill_dimm_asset_tag(const struct dimm_info *dimm, struct smbios_type17 *t)
{
char buf[40];

snprintf(buf, sizeof(buf), "Channel-%d-DIMM-%d-AssetTag",
dimm->channel_num, dimm->dimm_num);
t->asset_tag = smbios_add_string(t->eos, buf);
}

__weak const char *smbios_mainboard_bios_version(void)
{
return NULL;
Expand Down Expand Up @@ -60,7 +69,7 @@ __weak const char *smbios_mainboard_location_in_chassis(void)

__weak smbios_board_type smbios_mainboard_board_type(void)
{
return SMBIOS_BOARD_TYPE_UNKNOWN;
return SMBIOS_BOARD_TYPE_MOTHERBOARD;
}

__weak void smbios_ec_revision(uint8_t *ec_major_revision, uint8_t *ec_minor_revision)
Expand Down
1 change: 1 addition & 0 deletions src/commonlib/Makefile.inc
Expand Up @@ -5,6 +5,7 @@ verstage-y += mem_pool.c
romstage-y += mem_pool.c
ramstage-y += mem_pool.c
postcar-y += mem_pool.c
smm-y += mem_pool.c

bootblock-y += iobuf.c
verstage-y += iobuf.c
Expand Down
27 changes: 27 additions & 0 deletions src/commonlib/bsd/include/commonlib/bsd/cbfs_mdata.h
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */

#ifndef _COMMONLIB_BSD_CBFS_MDATA_H_
#define _COMMONLIB_BSD_CBFS_MDATA_H_

#include <commonlib/bsd/cbfs_serialized.h>
#include <stddef.h>
#include <stdint.h>

/*
* Helper structure to allocate space for a blob of metadata on the stack.
* NOTE: The fields in any union cbfs_mdata or any of its substructures from cbfs_serialized.h
* should always remain in the same byte order as they are stored on flash (= big endian). To
* avoid byte-order confusion, fields should always and only be converted to host byte order at
* exactly the time they are read from one of these structures into their own separate variable.
*/
union cbfs_mdata {
struct cbfs_file h;
uint8_t raw[CBFS_METADATA_MAX_SIZE];
};

/* Finds a CBFS attribute in a metadata block. Attribute returned as-is (still big-endian).
If |size| is not 0, will check that it matches the length of the attribute (if found)...
else caller is responsible for checking the |len| field to avoid reading out-of-bounds. */
const void *cbfs_find_attr(const union cbfs_mdata *mdata, uint32_t attr_tag, size_t size_check);

#endif /* _COMMONLIB_BSD_CBFS_MDATA_H_ */
19 changes: 1 addition & 18 deletions src/commonlib/bsd/include/commonlib/bsd/cbfs_private.h
Expand Up @@ -5,7 +5,7 @@


#include <commonlib/bsd/cb_err.h>
#include <commonlib/bsd/cbfs_serialized.h>
#include <commonlib/bsd/cbfs_mdata.h>
#include <commonlib/bsd/sysincludes.h>
#include <stdbool.h>
#include <stdint.h>
Expand Down Expand Up @@ -41,18 +41,6 @@
*/
#include <cbfs_glue.h>

/*
* Helper structure to allocate space for a blob of metadata on the stack.
* NOTE: The fields in any union cbfs_mdata or any of its substructures from cbfs_serialized.h
* should always remain in the same byte order as they are stored on flash (= big endian). To
* avoid byte-order confusion, fields should always and only be converted to host byte order at
* exactly the time they are read from one of these structures into their own separate variable.
*/
union cbfs_mdata {
struct cbfs_file h;
uint8_t raw[CBFS_METADATA_MAX_SIZE];
};

/* Flags that modify behavior of cbfs_walk(). */
enum cbfs_walk_flags {
/* Write the calculated hash back out to |metadata_hash->hash| rather than comparing it.
Expand Down Expand Up @@ -130,9 +118,4 @@ cb_err_t cbfs_mcache_lookup(const void *mcache, size_t mcache_size, const char *
/* Returns the amount of bytes actually used by the CBFS metadata cache in |mcache|. */
size_t cbfs_mcache_real_size(const void *mcache, size_t mcache_size);

/* Finds a CBFS attribute in a metadata block. Attribute returned as-is (still big-endian).
If |size| is not 0, will check that it matches the length of the attribute (if found)...
else caller is responsible for checking the |len| field to avoid reading out-of-bounds. */
const void *cbfs_find_attr(const union cbfs_mdata *mdata, uint32_t attr_tag, size_t size_check);

#endif /* _COMMONLIB_BSD_CBFS_PRIVATE_H_ */
27 changes: 15 additions & 12 deletions src/commonlib/bsd/include/commonlib/bsd/cbfs_serialized.h
Expand Up @@ -13,11 +13,15 @@ enum cbfs_compression {
};

enum cbfs_type {
/* QUERY is an alias for DELETED that can be passed to CBFS APIs to
inquire about the type of a file, rather than constrain it. */
CBFS_TYPE_QUERY = 0,
CBFS_TYPE_DELETED = 0x00000000,
CBFS_TYPE_NULL = 0xffffffff,
CBFS_TYPE_BOOTBLOCK = 0x01,
CBFS_TYPE_CBFSHEADER = 0x02,
CBFS_TYPE_STAGE = 0x10,
CBFS_TYPE_LEGACY_STAGE = 0x10,
CBFS_TYPE_STAGE = 0x11,
CBFS_TYPE_SELF = 0x20,
CBFS_TYPE_FIT = 0x21,
CBFS_TYPE_OPTIONROM = 0x30,
Expand Down Expand Up @@ -128,6 +132,7 @@ enum cbfs_file_attr_tag {
CBFS_FILE_ATTR_TAG_ALIGNMENT = 0x42434c41, /* BE: 'BCLA' */
CBFS_FILE_ATTR_TAG_IBB = 0x32494242, /* BE: '2IBB' */
CBFS_FILE_ATTR_TAG_PADDING = 0x47444150, /* BE: 'GNDP' */
CBFS_FILE_ATTR_TAG_STAGEHEADER = 0x53746748, /* BE: 'StgH' */
};

struct cbfs_file_attr_compression {
Expand Down Expand Up @@ -157,22 +162,20 @@ struct cbfs_file_attr_align {
uint32_t alignment;
} __packed;

struct cbfs_file_attr_stageheader {
uint32_t tag;
uint32_t len;
uint64_t loadaddr; /* Memory address to load the code to. */
uint32_t entry_offset; /* Offset of entry point from loadaddr. */
uint32_t memlen; /* Total length (including BSS) in memory. */
} __packed;


/*** Component sub-headers ***/

/* Following are component sub-headers for the "standard"
component types */

/** This is the sub-header for stage components. Stages are
loaded by coreboot during the normal boot process */

struct cbfs_stage {
uint32_t compression; /** Compression type */
uint64_t entry; /** entry point */
uint64_t load; /** Where to load in memory */
uint32_t len; /** length of data to load */
uint32_t memlen; /** total length of object in memory */
} __packed;

/** this is the sub-header for payload components. Payloads
are loaded by coreboot at the end of the boot process */

Expand Down
8 changes: 3 additions & 5 deletions src/commonlib/include/commonlib/region.h
Expand Up @@ -196,18 +196,16 @@ extern const struct region_device_ops mem_rdev_rw_ops;
MEM_REGION_DEV_INIT(base_, size_, &mem_rdev_rw_ops) \

struct mmap_helper_region_device {
struct mem_pool pool;
struct mem_pool *pool;
struct region_device rdev;
};

#define MMAP_HELPER_REGION_INIT(ops_, offset_, size_) \
#define MMAP_HELPER_DEV_INIT(ops_, offset_, size_, mpool_) \
{ \
.rdev = REGION_DEV_INIT((ops_), (offset_), (size_)), \
.pool = (mpool_), \
}

void mmap_helper_device_init(struct mmap_helper_region_device *mdev,
void *cache, size_t cache_size);

void *mmap_helper_rdev_mmap(const struct region_device *, size_t, size_t);
int mmap_helper_rdev_munmap(const struct region_device *, void *);

Expand Down
12 changes: 3 additions & 9 deletions src/commonlib/region.c
Expand Up @@ -287,12 +287,6 @@ const struct region_device_ops mem_rdev_rw_ops = {
.eraseat = mdev_eraseat,
};

void mmap_helper_device_init(struct mmap_helper_region_device *mdev,
void *cache, size_t cache_size)
{
mem_pool_init(&mdev->pool, cache, cache_size);
}

void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset,
size_t size)
{
Expand All @@ -301,13 +295,13 @@ void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset,

mdev = container_of((void *)rd, __typeof__(*mdev), rdev);

mapping = mem_pool_alloc(&mdev->pool, size);
mapping = mem_pool_alloc(mdev->pool, size);

if (mapping == NULL)
return NULL;

if (rd->ops->readat(rd, mapping, offset, size) != size) {
mem_pool_free(&mdev->pool, mapping);
mem_pool_free(mdev->pool, mapping);
return NULL;
}

Expand All @@ -320,7 +314,7 @@ int mmap_helper_rdev_munmap(const struct region_device *rd, void *mapping)

mdev = container_of((void *)rd, __typeof__(*mdev), rdev);

mem_pool_free(&mdev->pool, mapping);
mem_pool_free(mdev->pool, mapping);

return 0;
}
Expand Down
29 changes: 27 additions & 2 deletions src/cpu/intel/fit/Makefile.inc
@@ -1,4 +1,19 @@
bootblock-y += fit.S
bootblock-y += fit.c

# The FIT table is generated as a separate CBFS file.
# The FIT pointer is reserved in fit.c and updated to point to the 'intel_fit'
# CBFS file using 'ifittool -F'.
# With a TOP_SWAP enabled bootblock the FIT pointer at the top swap offset
# will point to the 'intel_fit_ts' CBFS file.

cbfs-files-y += intel_fit
intel_fit-file := fit_table.c:struct
intel_fit-type := raw
intel_fit-align := 16

$(call add_intermediate, set_fit_ptr, $(IFITTOOL))
@printf " UPDATE-FIT set FIT pointer to table\n"
$(IFITTOOL) -f $< -F -n intel_fit -r COREBOOT

FIT_ENTRY=$(call strip_quotes, $(CONFIG_INTEL_TOP_SWAP_FIT_ENTRY_FMAP_REG))

Expand All @@ -13,13 +28,23 @@ $(call add_intermediate, add_mcu_fit, $(IFITTOOL))
# Second FIT in TOP_SWAP bootblock
ifeq ($(CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK),y)

$(call add_intermediate, add_ts_mcu_fit, $(IFITTOOL))
$(call add_intermediate, add_ts_mcu_fit, $(IFITTOOL) set_fit_ptr_ts)
@printf " UPDATE-FIT Top Swap: Microcode\n"
ifneq ($(FIT_ENTRY),)
$(IFITTOOL) -f $< -A -n $(FIT_ENTRY) -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r COREBOOT
endif # FIT_ENTRY
$(IFITTOOL) -f $< -a -n cpu_microcode_blob.bin -t 1 -s $(CONFIG_CPU_INTEL_NUM_FIT_ENTRIES) $(TS_OPTIONS) -r COREBOOT

cbfs-files-y += intel_fit_ts
intel_fit_ts-file := fit_table.c:struct
intel_fit_ts-type := raw
intel_fit_ts-align := 16

PHONY += set_ts_fit_ptr
set_ts_fit_ptr: $(obj)/coreboot.pre $(IFITTOOL)
@printf " UPDATE-FIT Top Swap: set FIT pointer to table\n"
$(IFITTOOL) -f $< -F -n intel_fit_ts -r COREBOOT -t $(TS_OPTIONS)

endif # CONFIG_INTEL_ADD_TOP_SWAP_BOOTBLOCK

endif # CONFIG_CPU_MICROCODE_CBFS_NONE
Expand Down
30 changes: 0 additions & 30 deletions src/cpu/intel/fit/fit.S

This file was deleted.

6 changes: 6 additions & 0 deletions src/cpu/intel/fit/fit.c
@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stdint.h>

/* This will get updated by ifittool later on to point to the cbfs 'intel_fit' file. */
__attribute__((used, __section__(".fit_pointer"))) const uint64_t fit_ptr = 0;
21 changes: 21 additions & 0 deletions src/cpu/intel/fit/fit_table.c
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stdint.h>

struct fit_entry {
uint8_t address[sizeof(uint64_t)];
uint32_t size_reserved;
uint16_t version;
uint8_t type_checksum_valid;
uint8_t checksum;
} __packed;

__attribute((used)) static struct fit_entry fit_table[CONFIG_CPU_INTEL_NUM_FIT_ENTRIES + 1] = {
[0] = {
.address = {'_', 'F', 'I', 'T', '_', ' ', ' ', ' '},
.size_reserved = 1,
.version = 0x100,
.type_checksum_valid = 0x80,
.checksum = 0x7d,
}
};
28 changes: 21 additions & 7 deletions src/cpu/intel/microcode/microcode.c
Expand Up @@ -117,18 +117,15 @@ uint32_t get_microcode_checksum(const void *microcode)
return ((struct microcode *)microcode)->cksum;
}

const void *intel_microcode_find(void)
static const void *find_cbfs_microcode(void)
{
static const struct microcode *ucode_updates;
const struct microcode *ucode_updates;
size_t microcode_len;
u32 eax;
u32 pf, rev, sig, update_size;
msr_t msr;
struct cpuinfo_x86 c;

if (ucode_updates)
return ucode_updates;

ucode_updates = cbfs_map(MICROCODE_CBFS_FILE, &microcode_len);
if (ucode_updates == NULL)
return NULL;
Expand Down Expand Up @@ -170,11 +167,28 @@ const void *intel_microcode_find(void)
microcode_len -= update_size;
}

ucode_updates = NULL;

return NULL;
}

const void *intel_microcode_find(void)
{
static bool microcode_checked;
static const void *ucode_update;

if (microcode_checked)
return ucode_update;

/*
* Since this function caches the found microcode (NULL or a valid
* microcode pointer), it is expected to be run from BSP before starting
* any other APs. This sequence is not multithread safe otherwise.
*/
ucode_update = find_cbfs_microcode();
microcode_checked = true;

return ucode_update;
}

void intel_update_microcode_from_cbfs(void)
{
const void *patch = intel_microcode_find();
Expand Down
21 changes: 18 additions & 3 deletions src/cpu/qemu-x86/Kconfig
Expand Up @@ -36,9 +36,24 @@ config CPU_QEMU_X86_ASEG_SMM
depends on !PARALLEL_MP
select SMM_ASEG

#config CPU_QEMU_X86_TSEG_SMM
# bool "SMM in TSEG"
# select SMM_TSEG
config CPU_QEMU_X86_TSEG_SMM
bool "SMM in TSEG"
select SMM_TSEG
depends on PARALLEL_MP

endchoice

choice
prompt "SMM loader"
default CPU_QEMU_X86_SMMLOADERV1
depends on SMM_TSEG

config CPU_QEMU_X86_SMMLOADERV1
bool "smmloader v1"

config CPU_QEMU_X86_SMMLOADERV2
bool "smmloader v2"
select X86_SMM_LOADER_VERSION2

endchoice

Expand Down
90 changes: 68 additions & 22 deletions src/cpu/x86/mp_init.c
Expand Up @@ -685,7 +685,11 @@ struct mp_state {
int cpu_count;
uintptr_t perm_smbase;
size_t perm_smsize;
/* Size of the real CPU save state */
size_t smm_real_save_state_size;
/* Size of allocated CPU save state, MAX(real save state size, stub size) */
size_t smm_save_state_size;
uintptr_t reloc_start32_offset;
int do_smm;
} mp_state;

Expand All @@ -708,15 +712,12 @@ static void smm_enable(void)
static void asmlinkage smm_do_relocation(void *arg)
{
const struct smm_module_params *p;
const struct smm_runtime *runtime;
int cpu;
uintptr_t curr_smbase;
const uintptr_t curr_smbase = SMM_DEFAULT_BASE;
uintptr_t perm_smbase;

p = arg;
runtime = p->runtime;
cpu = p->cpu;
curr_smbase = runtime->smbase;

if (cpu >= CONFIG_MAX_CPUS) {
printk(BIOS_CRIT,
Expand All @@ -729,17 +730,16 @@ static void asmlinkage smm_do_relocation(void *arg)
* the location of the new SMBASE. If using SMM modules then this
* calculation needs to match that of the module loader.
*/
#if CONFIG(X86_SMM_LOADER_VERSION2)
perm_smbase = smm_get_cpu_smbase(cpu);
mp_state.perm_smbase = perm_smbase;
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
if (CONFIG(X86_SMM_LOADER_VERSION2)) {
perm_smbase = smm_get_cpu_smbase(cpu);
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
}
} else {
perm_smbase = mp_state.perm_smbase;
perm_smbase -= cpu * mp_state.smm_save_state_size;
}
#else
perm_smbase = mp_state.perm_smbase;
perm_smbase -= cpu * runtime->save_state_size;
#endif

/* Setup code checks this callback for validity. */
printk(BIOS_INFO, "%s : curr_smbase 0x%x perm_smbase 0x%x, cpu = %d\n",
Expand All @@ -755,20 +755,21 @@ static void asmlinkage smm_do_relocation(void *arg)
stm_setup(mseg, p->cpu,
perm_smbase,
mp_state.perm_smbase,
runtime->start32_offset);
mp_state.reloc_start32_offset);
}
}

static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)
{
int i;
struct smm_runtime *runtime = smm_params->runtime;
struct smm_stub_params *stub_params = smm_params->stub_params;

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

static int install_relocation_handler(int num_cpus, size_t save_state_size)
static int install_relocation_handler(int num_cpus, size_t real_save_state_size,
size_t save_state_size)
{
int cpus = num_cpus;
#if CONFIG(X86_SMM_LOADER_VERSION2)
Expand All @@ -781,6 +782,7 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE,
.num_concurrent_stacks = cpus,
.real_cpu_save_state_size = real_save_state_size,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
.handler = smm_do_relocation,
Expand All @@ -796,11 +798,14 @@ static int install_relocation_handler(int num_cpus, size_t save_state_size)
}
adjust_smm_apic_id_map(&smm_params);

mp_state.reloc_start32_offset = smm_params.stub_params->start32_offset;

return 0;
}

static int install_permanent_handler(int num_cpus, uintptr_t smbase,
size_t smsize, size_t save_state_size)
size_t smsize, size_t real_save_state_size,
size_t save_state_size)
{
/*
* All the CPUs will relocate to permanaent handler now. Set parameters
Expand All @@ -812,6 +817,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase,
struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_MODULE_STACK_SIZE,
.num_concurrent_stacks = num_cpus,
.real_cpu_save_state_size = real_save_state_size,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = num_cpus,
};
Expand All @@ -833,6 +839,7 @@ static int install_permanent_handler(int num_cpus, uintptr_t smbase,
/* Load SMM handlers as part of MP flight record. */
static void load_smm_handlers(void)
{
size_t real_save_state_size = mp_state.smm_real_save_state_size;
size_t smm_save_state_size = mp_state.smm_save_state_size;

/* Do nothing if SMM is disabled.*/
Expand All @@ -841,13 +848,15 @@ static void load_smm_handlers(void)

/* Install handlers. */
if (install_relocation_handler(mp_state.cpu_count,
smm_save_state_size) < 0) {
real_save_state_size,
smm_save_state_size) < 0) {
printk(BIOS_ERR, "Unable to install SMM relocation handler.\n");
smm_disable();
}

if (install_permanent_handler(mp_state.cpu_count, mp_state.perm_smbase,
mp_state.perm_smsize, smm_save_state_size) < 0) {
mp_state.perm_smsize, real_save_state_size,
smm_save_state_size) < 0) {
printk(BIOS_ERR, "Unable to install SMM permanent handler.\n");
smm_disable();
}
Expand Down Expand Up @@ -992,6 +1001,28 @@ int mp_run_on_aps(void (*func)(void *), void *arg, int logical_cpu_num,
return run_ap_work(&lcb, expire_us);
}

int mp_run_on_all_aps(void (*func)(void *), void *arg, long expire_us, bool run_parallel)
{
int ap_index, bsp_index;

if (run_parallel)
return mp_run_on_aps(func, arg, 0, expire_us);

bsp_index = cpu_index();

const int total_threads = global_num_aps + 1; /* +1 for BSP */

for (ap_index = 0; ap_index < total_threads; ap_index++) {
/* skip if BSP */
if (ap_index == bsp_index)
continue;
if (mp_run_on_aps(func, arg, ap_index, expire_us))
return CB_ERR;
}

return CB_SUCCESS;
}

int mp_run_on_all_cpus(void (*func)(void *), void *arg)
{
/* Run on BSP first. */
Expand Down Expand Up @@ -1035,6 +1066,19 @@ static struct mp_flight_record mp_steps[] = {
MP_FR_BLOCK_APS(ap_wait_for_instruction, NULL),
};

static size_t smm_stub_size(void)
{
extern unsigned char _binary_smmstub_start[];
struct rmodule smm_stub;

if (rmodule_parse(&_binary_smmstub_start, &smm_stub)) {
printk(BIOS_ERR, "%s: unable to get SMM module size\n", __func__);
return 0;
}

return rmodule_memory_size(&smm_stub);
}

static void fill_mp_state(struct mp_state *state, const struct mp_ops *ops)
{
/*
Expand All @@ -1048,7 +1092,9 @@ static void fill_mp_state(struct mp_state *state, const struct mp_ops *ops)

if (ops->get_smm_info != NULL)
ops->get_smm_info(&state->perm_smbase, &state->perm_smsize,
&state->smm_save_state_size);
&state->smm_real_save_state_size);

state->smm_save_state_size = MAX(state->smm_real_save_state_size, smm_stub_size());

/*
* Make sure there is enough room for the SMM descriptor
Expand Down
4 changes: 2 additions & 2 deletions src/cpu/x86/mtrr/xip_cache.c
Expand Up @@ -29,8 +29,8 @@ static uint32_t max_cache_used(void)

void platform_prog_run(struct prog *prog)
{
const uint32_t base = region_device_offset(&prog->rdev);
const uint32_t size = region_device_sz(&prog->rdev);
const uint32_t base = (uintptr_t)prog_start(prog);
const uint32_t size = prog_size(prog);
const uint32_t end = base + size;
const uint32_t cache_used = max_cache_used();
/* This will accumulate MTRR's as XIP stages are run.
Expand Down
29 changes: 2 additions & 27 deletions src/cpu/x86/pae/pgtbl.c
Expand Up @@ -321,42 +321,17 @@ void paging_set_default_pat(void)
paging_set_pat(pat);
}

static int read_from_cbfs(const char *name, void *buf, size_t size)
{
struct cbfsf fh;
struct region_device rdev;
size_t rdev_sz;

if (cbfs_boot_locate(&fh, name, NULL))
return -1;

cbfs_file_data(&rdev, &fh);

rdev_sz = region_device_sz(&rdev);

if (size < rdev_sz) {
printk(BIOS_ERR, "%s region too small to load: %zx < %zx\n",
name, size, rdev_sz);
return -1;
}

if (rdev_readat(&rdev, buf, 0, rdev_sz) != rdev_sz)
return -1;

return 0;
}

int paging_enable_for_car(const char *pdpt_name, const char *pt_name)
{
if (!preram_symbols_available())
return -1;

if (read_from_cbfs(pdpt_name, _pdpt, REGION_SIZE(pdpt))) {
if (!cbfs_load(pdpt_name, _pdpt, REGION_SIZE(pdpt))) {
printk(BIOS_ERR, "Couldn't load pdpt\n");
return -1;
}

if (read_from_cbfs(pt_name, _pagetables, REGION_SIZE(pagetables))) {
if (!cbfs_load(pt_name, _pagetables, REGION_SIZE(pagetables))) {
printk(BIOS_ERR, "Couldn't load page tables\n");
return -1;
}
Expand Down
28 changes: 10 additions & 18 deletions src/cpu/x86/smm/smm_module_handler.c
Expand Up @@ -18,6 +18,9 @@ typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore;
static volatile
__attribute__((aligned(4))) smi_semaphore smi_handler_status = SMI_UNLOCKED;

static const volatile
__attribute((aligned(4), __section__(".module_parameters"))) struct smm_runtime smm_runtime;

static int smi_obtain_lock(void)
{
u8 ret = SMI_LOCKED;
Expand Down Expand Up @@ -87,33 +90,27 @@ static void smi_restore_pci_address(void)
outl(pci_orig, 0xcf8);
}

static const struct smm_runtime *smm_runtime;

struct global_nvs *gnvs;

void *smm_get_save_state(int cpu)
{
char *base;
if (cpu > smm_runtime.num_cpus)
return NULL;

/* This function assumes all save states start at top of default
* SMRAM size space and are staggered down by save state size. */
base = (void *)(uintptr_t)smm_runtime->smbase;
base += SMM_DEFAULT_SIZE;
base -= (cpu + 1) * smm_runtime->save_state_size;

return base;
return (void *)(smm_runtime.save_state_top[cpu] - smm_runtime.save_state_size);
}

uint32_t smm_revision(void)
{
const uintptr_t save_state = (uintptr_t)(smm_get_save_state(0));

return *(uint32_t *)(save_state + smm_runtime->save_state_size - SMM_REVISION_OFFSET_FROM_TOP);
return *(uint32_t *)(save_state + smm_runtime.save_state_size
- SMM_REVISION_OFFSET_FROM_TOP);
}

bool smm_region_overlaps_handler(const struct region *r)
{
const struct region r_smm = {smm_runtime->smbase, smm_runtime->smm_size};
const struct region r_smm = {smm_runtime.smbase, smm_runtime.smm_size};
const struct region r_aseg = {SMM_BASE, SMM_DEFAULT_SIZE};

return region_overlap(&r_smm, r) || region_overlap(&r_aseg, r);
Expand All @@ -122,22 +119,17 @@ bool smm_region_overlaps_handler(const struct region *r)
asmlinkage void smm_handler_start(void *arg)
{
const struct smm_module_params *p;
const struct smm_runtime *runtime;
int cpu;
uintptr_t actual_canary;
uintptr_t expected_canary;

p = arg;
runtime = p->runtime;
cpu = p->cpu;
expected_canary = (uintptr_t)p->canary;

/* Make sure to set the global runtime. It's OK to race as the value
* will be the same across CPUs as well as multiple SMIs. */
if (smm_runtime == NULL) {
smm_runtime = runtime;
gnvs = (void *)(uintptr_t)smm_runtime->gnvs_ptr;
}
gnvs = (void *)(uintptr_t)smm_runtime.gnvs_ptr;

if (cpu >= CONFIG_MAX_CPUS) {
console_init();
Expand Down
46 changes: 17 additions & 29 deletions src/cpu/x86/smm/smm_module_loader.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stdint.h>
#include <string.h>
#include <acpi/acpi_gnvs.h>
#include <rmodule.h>
Expand All @@ -26,18 +27,6 @@ __attribute__((aligned(16)));
* The components are assumed to consist of one consecutive region.
*/

/* These parameters are used by the SMM stub code. A pointer to the params
* is also passed to the C-base handler. */
struct smm_stub_params {
u32 stack_size;
u32 stack_top;
u32 c_handler;
u32 c_handler_arg;
u32 fxsave_area;
u32 fxsave_area_size;
struct smm_runtime runtime;
} __packed;

/*
* The stub is the entry point that sets up protected mode and stacks for each
* CPU. It then calls into the SMM handler module. It is encoded as an rmodule.
Expand Down Expand Up @@ -209,12 +198,6 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
smm_stub_size = rmodule_memory_size(&smm_stub);
stub_entry_offset = rmodule_entry_offset(&smm_stub);

if (smm_stub_size > params->per_cpu_save_state_size) {
printk(BIOS_ERR, "SMM Module: SMM stub size larger than save state size\n");
printk(BIOS_ERR, "SMM Module: Staggered entry points will overlap stub\n");
return -1;
}

/* Assume the stub is always small enough to live within upper half of
* SMRAM region after the save state space has been allocated. */
smm_stub_loc = &base[SMM_ENTRY_OFFSET];
Expand Down Expand Up @@ -261,24 +244,18 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
stub_params->stack_top = (uintptr_t)stacks_top;
stub_params->stack_size = params->per_cpu_stack_size;
stub_params->c_handler = (uintptr_t)params->handler;
stub_params->c_handler_arg = (uintptr_t)params->handler_arg;
stub_params->fxsave_area = (uintptr_t)fxsave_area;
stub_params->fxsave_area_size = FXSAVE_SIZE;
stub_params->runtime.smbase = (uintptr_t)smbase;
stub_params->runtime.smm_size = smm_size;
stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
stub_params->runtime.num_cpus = params->num_concurrent_stacks;
stub_params->runtime.gnvs_ptr = (uintptr_t)acpi_get_gnvs();

/* Initialize the APIC id to CPU number table to be 1:1 */
for (i = 0; i < params->num_concurrent_stacks; i++)
stub_params->runtime.apic_id_to_cpu[i] = i;
stub_params->apic_id_to_cpu[i] = i;

/* Allow the initiator to manipulate SMM stub parameters. */
params->runtime = &stub_params->runtime;
params->stub_params = stub_params;

printk(BIOS_DEBUG, "SMM Module: stub loaded at %p. Will call %p(%p)\n",
smm_stub_loc, params->handler, params->handler_arg);
printk(BIOS_DEBUG, "SMM Module: stub loaded at %p. Will call %p\n",
smm_stub_loc, params->handler);

return 0;
}
Expand Down Expand Up @@ -336,6 +313,7 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
{
struct rmodule smm_mod;
struct smm_runtime *handler_mod_params;
size_t total_stack_size;
size_t handler_size;
size_t module_alignment;
Expand Down Expand Up @@ -402,7 +380,17 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
return -1;

params->handler = rmodule_entry(&smm_mod);
params->handler_arg = rmodule_parameters(&smm_mod);
handler_mod_params = rmodule_parameters(&smm_mod);
handler_mod_params->smbase = (uintptr_t)smram;
handler_mod_params->smm_size = size;
handler_mod_params->save_state_size = params->real_cpu_save_state_size;
handler_mod_params->num_cpus = params->num_concurrent_stacks;
handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs();

for (int i = 0; i < CONFIG_MAX_CPUS; i++) {
handler_mod_params->save_state_top[i] = (uintptr_t)smram + SMM_DEFAULT_SIZE
- params->per_cpu_save_state_size * i;
}

return smm_module_setup_stub(smram, size, params, fxsave_area);
}
153 changes: 57 additions & 96 deletions src/cpu/x86/smm/smm_module_loaderv2.c
Expand Up @@ -27,18 +27,6 @@ __attribute__((aligned(16)));
* The components are assumed to consist of one consecutive region.
*/

/* These parameters are used by the SMM stub code. A pointer to the params
* is also passed to the C-base handler. */
struct smm_stub_params {
u32 stack_size;
u32 stack_top;
u32 c_handler;
u32 c_handler_arg;
u32 fxsave_area;
u32 fxsave_area_size;
struct smm_runtime runtime;
} __packed;

/*
* The stub is the entry point that sets up protected mode and stacks for each
* CPU. It then calls into the SMM handler module. It is encoded as an rmodule.
Expand Down Expand Up @@ -101,7 +89,7 @@ static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
unsigned int i;
struct rmodule smm_stub;
unsigned int ss_size = params->per_cpu_save_state_size, stub_size;
unsigned int smm_entry_offset = params->smm_main_entry_offset;
unsigned int smm_entry_offset = SMM_ENTRY_OFFSET;
unsigned int seg_count = 0, segments = 0, available;
unsigned int cpus_in_segment = 0;
unsigned int base = smbase;
Expand Down Expand Up @@ -135,12 +123,6 @@ static int smm_create_map(uintptr_t smbase, unsigned int num_cpus,
return 0;
}

if (stub_size > ss_size) {
printk(BIOS_ERR, "%s: Save state larger than SMM stub size\n", __func__);
printk(BIOS_ERR, " Decrease stub size or increase the size allocated for the save state\n");
return 0;
}

for (i = 0; i < num_cpus; i++) {
cpus[i].smbase = base;
cpus[i].entry = base + smm_entry_offset;
Expand Down Expand Up @@ -226,24 +208,19 @@ static int smm_place_entry_code(uintptr_t smbase, unsigned int num_cpus,
{
unsigned int i;
unsigned int size;
if (smm_create_map(smbase, num_cpus, params)) {
/*
* Ensure there was enough space and the last CPUs smbase
* did not encroach upon the stack. Stack top is smram start
* + size of stack.
*/
if (cpus[num_cpus].active) {
if (cpus[num_cpus - 1].smbase +
params->smm_main_entry_offset < stack_top) {
printk(BIOS_ERR, "%s: stack encroachment\n", __func__);

/*
* Ensure there was enough space and the last CPUs smbase
* did not encroach upon the stack. Stack top is smram start
* + size of stack.
*/
if (cpus[num_cpus].active) {
if (cpus[num_cpus - 1].smbase + SMM_ENTRY_OFFSET < stack_top) {
printk(BIOS_ERR, "%s: stack encroachment\n", __func__);
printk(BIOS_ERR, "%s: smbase %zx, stack_top %lx\n",
__func__, cpus[num_cpus].smbase, stack_top);
__func__, cpus[num_cpus].smbase, stack_top);
return 0;
}
}
} else {
printk(BIOS_ERR, "%s: unable to place smm entry code\n", __func__);
return 0;
}

printk(BIOS_INFO, "%s: smbase %zx, stack_top %lx\n",
Expand All @@ -266,8 +243,7 @@ static int smm_place_entry_code(uintptr_t smbase, unsigned int num_cpus,
* Place stacks in base -> base + size region, but ensure the stacks don't
* overlap the staggered entry points.
*/
static void *smm_stub_place_stacks(char *base, size_t size,
struct smm_loader_params *params)
static void *smm_stub_place_stacks(char *base, struct smm_loader_params *params)
{
size_t total_stack_size;
char *stacks_top;
Expand All @@ -279,17 +255,11 @@ static void *smm_stub_place_stacks(char *base, size_t size,
printk(BIOS_DEBUG, "%s: cpus: %zx : stack space: needed -> %zx\n",
__func__, params->num_concurrent_stacks,
total_stack_size);
printk(BIOS_DEBUG, " available -> %zx : per_cpu_stack_size : %zx\n",
size, params->per_cpu_stack_size);

/* There has to be at least one stack user. */
if (params->num_concurrent_stacks < 1)
return NULL;

/* Total stack size cannot fit. */
if (total_stack_size > size)
return NULL;

/* Stacks extend down to SMBASE */
stacks_top = &base[total_stack_size];
printk(BIOS_DEBUG, "%s: exit, stack_top %p\n", __func__, stacks_top);
Expand Down Expand Up @@ -340,21 +310,20 @@ static int smm_stub_place_staggered_entry_points(char *base,
* This module setup code works for the default (0x30000) SMM handler setup and the
* permanent SMM handler.
*/
static int smm_module_setup_stub(void *smbase, size_t smm_size,
static int smm_module_setup_stub(void *const smbase, const size_t smm_size,
struct smm_loader_params *params,
void *fxsave_area)
void *const fxsave_area,
void *const smram_start)
{
size_t total_save_state_size;
size_t smm_stub_size;
size_t stub_entry_offset;
char *smm_stub_loc;
void *stacks_top;
size_t size;
char *base;
size_t i;
struct smm_stub_params *stub_params;
struct rmodule smm_stub;
unsigned int total_size_all;
base = smbase;
size = smm_size;

Expand Down Expand Up @@ -383,10 +352,10 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
size -= total_save_state_size;

/* The save state size encroached over the first SMM entry point. */
if (size <= params->smm_main_entry_offset) {
if (size <= SMM_ENTRY_OFFSET) {
printk(BIOS_ERR, "%s: encroachment over SMM entry point\n", __func__);
printk(BIOS_ERR, "%s: state save size: %zx : smm_entry_offset -> %lx\n",
__func__, size, params->smm_main_entry_offset);
__func__, size, (size_t)SMM_ENTRY_OFFSET);
return -1;
}

Expand All @@ -399,13 +368,12 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,

smm_stub_loc = NULL;
smm_stub_size = rmodule_memory_size(&smm_stub);
stub_entry_offset = rmodule_entry_offset(&smm_stub);

/* Put the stub at the main entry point */
smm_stub_loc = &base[params->smm_main_entry_offset];
smm_stub_loc = &base[SMM_ENTRY_OFFSET];

/* Stub is too big to fit. */
if (smm_stub_size > (size - params->smm_main_entry_offset)) {
if (smm_stub_size > (size - SMM_ENTRY_OFFSET)) {
printk(BIOS_ERR, "%s: stub is too big to fit\n", __func__);
return -1;
}
Expand All @@ -414,14 +382,9 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
* for default handler, but for relocated handler it lives at the beginning
* of SMRAM which is TSEG base
*/
const size_t total_stack_size = params->num_concurrent_stacks *
params->per_cpu_stack_size;
stacks_top = smm_stub_place_stacks((char *)params->smram_start, total_stack_size,
params);
stacks_top = smm_stub_place_stacks(smram_start, params);
if (stacks_top == NULL) {
printk(BIOS_ERR, "%s: not enough space for stacks\n", __func__);
printk(BIOS_ERR, "%s: ....need -> %p : available -> %zx\n", __func__,
base, total_stack_size);
printk(BIOS_ERR, "%s: error assigning stacks\n", __func__);
return -1;
}
params->stack_top = stacks_top;
Expand All @@ -441,49 +404,31 @@ static int smm_module_setup_stub(void *smbase, size_t smm_size,
stub_params->stack_top = (uintptr_t)stacks_top;
stub_params->stack_size = params->per_cpu_stack_size;
stub_params->c_handler = (uintptr_t)params->handler;
stub_params->c_handler_arg = (uintptr_t)params->handler_arg;
stub_params->fxsave_area = (uintptr_t)fxsave_area;
stub_params->fxsave_area_size = FXSAVE_SIZE;
stub_params->runtime.smbase = (uintptr_t)smbase;
stub_params->runtime.smm_size = smm_size;
stub_params->runtime.save_state_size = params->per_cpu_save_state_size;
stub_params->runtime.num_cpus = params->num_concurrent_stacks;
stub_params->runtime.gnvs_ptr = (uintptr_t)acpi_get_gnvs();

const size_t total_stack_size =
params->num_concurrent_stacks * params->per_cpu_stack_size;
printk(BIOS_DEBUG, "%s: stack_end = 0x%lx\n",
__func__, stub_params->stack_top - total_stack_size);
printk(BIOS_DEBUG,
"%s: stack_top = 0x%x\n", __func__, stub_params->stack_top);
printk(BIOS_DEBUG, "%s: stack_size = 0x%x\n",
__func__, stub_params->stack_size);
printk(BIOS_DEBUG, "%s: runtime.smbase = 0x%x\n",
__func__, stub_params->runtime.smbase);
printk(BIOS_DEBUG, "%s: runtime.start32_offset = 0x%x\n", __func__,
stub_params->runtime.start32_offset);
stub_params->start32_offset);
printk(BIOS_DEBUG, "%s: runtime.smm_size = 0x%zx\n",
__func__, smm_size);
printk(BIOS_DEBUG, "%s: per_cpu_save_state_size = 0x%x\n",
__func__, stub_params->runtime.save_state_size);
printk(BIOS_DEBUG, "%s: num_cpus = 0x%x\n", __func__,
stub_params->runtime.num_cpus);
printk(BIOS_DEBUG, "%s: total_save_state_size = 0x%x\n",
__func__, (stub_params->runtime.save_state_size *
stub_params->runtime.num_cpus));
total_size_all = stub_params->stack_size +
(stub_params->runtime.save_state_size *
stub_params->runtime.num_cpus);
printk(BIOS_DEBUG, "%s: total_size_all = 0x%x\n", __func__,
total_size_all);

/* Initialize the APIC id to CPU number table to be 1:1 */
for (i = 0; i < params->num_concurrent_stacks; i++)
stub_params->runtime.apic_id_to_cpu[i] = i;
stub_params->apic_id_to_cpu[i] = i;

/* Allow the initiator to manipulate SMM stub parameters. */
params->runtime = &stub_params->runtime;
params->stub_params = stub_params;

printk(BIOS_DEBUG, "SMM Module: stub loaded at %p. Will call %p(%p)\n",
smm_stub_loc, params->handler, params->handler_arg);
printk(BIOS_DEBUG, "SMM Module: stub loaded at %p. Will call %p\n",
smm_stub_loc, params->handler);
return 0;
}

Expand Down Expand Up @@ -511,11 +456,8 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
if (params->num_concurrent_stacks == 0)
params->num_concurrent_stacks = CONFIG_MAX_CPUS;

params->smm_main_entry_offset = SMM_ENTRY_OFFSET;
params->smram_start = SMM_DEFAULT_BASE;
params->smram_end = SMM_DEFAULT_BASE + SMM_DEFAULT_SIZE;
return smm_module_setup_stub(smram, SMM_DEFAULT_SIZE,
params, fxsave_area_relocation);
params, fxsave_area_relocation, smram);
printk(BIOS_SPEW, "%s: exit\n", __func__);
}

Expand Down Expand Up @@ -548,6 +490,7 @@ int smm_setup_relocation_handler(struct smm_loader_params *params)
int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
{
struct rmodule smm_mod;
struct smm_runtime *handler_mod_params;
size_t total_stack_size;
size_t handler_size;
size_t module_alignment;
Expand All @@ -556,7 +499,7 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
void *fxsave_area;
size_t total_size = 0;
char *base;

void *smram_start = smram;
if (size <= SMM_DEFAULT_SIZE)
return -1;

Expand All @@ -565,9 +508,6 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
*/
base = smram;
base += size;
params->smram_start = (uintptr_t)smram;
params->smram_end = params->smram_start + size;
params->smm_main_entry_offset = SMM_ENTRY_OFFSET;

/* Fail if can't parse the smm rmodule. */
if (rmodule_parse(&_binary_smm_start, &smm_mod))
Expand Down Expand Up @@ -630,7 +570,12 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
return -1;

params->handler = rmodule_entry(&smm_mod);
params->handler_arg = rmodule_parameters(&smm_mod);
handler_mod_params = rmodule_parameters(&smm_mod);
handler_mod_params->smbase = (uintptr_t)smram;
handler_mod_params->smm_size = size;
handler_mod_params->save_state_size = params->real_cpu_save_state_size;
handler_mod_params->num_cpus = params->num_concurrent_stacks;
handler_mod_params->gnvs_ptr = (uintptr_t)acpi_get_gnvs();

printk(BIOS_DEBUG, "%s: smram_start: 0x%p\n",
__func__, smram);
Expand All @@ -642,8 +587,6 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
__func__, params->handler);
printk(BIOS_DEBUG, "%s: handler_size %zx\n",
__func__, handler_size);
printk(BIOS_DEBUG, "%s: handler_arg %p\n",
__func__, params->handler_arg);
printk(BIOS_DEBUG, "%s: fxsave_area %p\n",
__func__, fxsave_area);
printk(BIOS_DEBUG, "%s: fxsave_size %zx\n",
Expand All @@ -653,12 +596,30 @@ int smm_load_module(void *smram, size_t size, struct smm_loader_params *params)
printk(BIOS_DEBUG, "%s: CONFIG_BIOS_RESOURCE_LIST_SIZE 0x%x\n",
__func__, CONFIG_BIOS_RESOURCE_LIST_SIZE);

printk(BIOS_DEBUG, "%s: handler_mod_params.smbase = 0x%x\n", __func__,
handler_mod_params->smbase);
printk(BIOS_DEBUG, "%s: per_cpu_save_state_size = 0x%x\n", __func__,
handler_mod_params->save_state_size);
printk(BIOS_DEBUG, "%s: num_cpus = 0x%x\n", __func__, handler_mod_params->num_cpus);
printk(BIOS_DEBUG, "%s: total_save_state_size = 0x%x\n", __func__,
(handler_mod_params->save_state_size * handler_mod_params->num_cpus));

/* CPU 0 smbase goes first, all other CPUs
* will be staggered below
*/
base -= SMM_CODE_SEGMENT_SIZE;
printk(BIOS_DEBUG, "%s: cpu0 entry: %p\n",
__func__, base);
params->smm_entry = (uintptr_t)base + params->smm_main_entry_offset;
return smm_module_setup_stub(base, size, params, fxsave_area);

if (!smm_create_map((uintptr_t)base, params->num_concurrent_save_states, params)) {
printk(BIOS_ERR, "%s: Error creating CPU map\n", __func__);
return -1;
}

for (int i = 0; i < params->num_concurrent_stacks; i++) {
handler_mod_params->save_state_top[i] =
cpus[i].ss_start + params->per_cpu_save_state_size;
}

return smm_module_setup_stub(base, size, params, fxsave_area, smram_start);
}
27 changes: 3 additions & 24 deletions src/cpu/x86/smm/smm_stub.S
Expand Up @@ -21,33 +21,18 @@ stack_top:
.long 0
c_handler:
.long 0
c_handler_arg:
.long 0
fxsave_area:
.long 0
fxsave_area_size:
.long 0
/* struct smm_runtime begins here. */
smm_runtime:
smbase:
.long 0
smm_size:
.long 0
save_state_size:
.long 0
num_cpus:
.long 0
gnvs_ptr:
.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. */
apic_to_cpu_num:
.fill CONFIG_MAX_CPUS,1,0xff
/* end struct smm_runtime */
/* allows the STM to bring up SMM in 32-bit mode */
start32_offset:
.long smm_trampoline32 - _start

.data
/* Provide fallback stack to use when a valid CPU number cannot be found. */
Expand Down Expand Up @@ -202,9 +187,7 @@ smm_trampoline32:
*/
#ifdef __x86_64__
push %rbx /* uintptr_t *canary */
push $(smm_runtime)
push %rcx /* size_t cpu */
push c_handler_arg /* void *arg */

mov %rsp, %rdi /* *arg */

Expand All @@ -229,13 +212,9 @@ smm_trampoline32:
wrmsr

#else
push $0x0 /* Padding */
push $0x0 /* Padding */
push $0x0 /* Padding */
push %ebx /* uintptr_t *canary */
push $(smm_runtime)
push %ecx /* size_t cpu */
push c_handler_arg /* void *arg */
push %esp /* smm_module_params *arg (allocated on stack). */
mov c_handler, %eax
call *%eax
Expand Down
8 changes: 8 additions & 0 deletions src/device/Kconfig
Expand Up @@ -519,6 +519,14 @@ config AZALIA_PLUGIN_SUPPORT
bool
default n

config AZALIA_MAX_CODECS
int
depends on AZALIA_PLUGIN_SUPPORT
default 3
range 1 15
help
The maximum number of codecs supported on a single HD Audio controller.

config PCIEXP_PLUGIN_SUPPORT
bool
default y
Expand Down
74 changes: 42 additions & 32 deletions src/device/azalia_device.c
Expand Up @@ -6,11 +6,12 @@
#include <device/azalia_device.h>
#include <device/mmio.h>
#include <delay.h>
#include <timer.h>

int azalia_set_bits(void *port, u32 mask, u32 val)
{
struct stopwatch sw;
u32 reg32;
int count;

/* Write (val & mask) to port */
val &= mask;
Expand All @@ -20,16 +21,16 @@ int azalia_set_bits(void *port, u32 mask, u32 val)
write32(port, reg32);

/* Wait for readback of register to match what was just written to it */
count = 50;
stopwatch_init_msecs_expire(&sw, 50);
do {
/* Wait 1ms based on BKDG wait time */
mdelay(1);
reg32 = read32(port);
reg32 &= mask;
} while ((reg32 != val) && --count);
} while ((reg32 != val) && !stopwatch_expired(&sw));

/* Timeout occurred */
if (!count)
if (stopwatch_expired(&sw))
return -1;
return 0;
}
Expand All @@ -46,30 +47,32 @@ int azalia_exit_reset(u8 *base)
return azalia_set_bits(base + HDA_GCTL_REG, HDA_GCTL_CRST, HDA_GCTL_CRST);
}

static int codec_detect(u8 *base)
static u16 codec_detect(u8 *base)
{
u32 reg32;
int count;
struct stopwatch sw;
const u16 codec_mask = (1 << CONFIG_AZALIA_MAX_CODECS) - 1;
u16 reg16;

if (azalia_exit_reset(base) < 0)
goto no_codec;

/* clear STATESTS bits (BAR + 0xe)[2:0] */
reg32 = read32(base + HDA_STATESTS_REG);
reg32 |= 7;
write32(base + HDA_STATESTS_REG, reg32);
reg16 = read16(base + HDA_STATESTS_REG);
reg16 |= codec_mask;
write16(base + HDA_STATESTS_REG, reg16);

/* Wait for readback of register to
* match what was just written to it
*/
count = 50;
stopwatch_init_msecs_expire(&sw, 50);
do {
/* Wait 1ms based on BKDG wait time */
mdelay(1);
reg32 = read32(base + HDA_STATESTS_REG);
} while ((reg32 != 0) && --count);
reg16 = read16(base + HDA_STATESTS_REG);
} while ((reg16 != 0) && !stopwatch_expired(&sw));

/* Timeout occurred */
if (!count)
if (stopwatch_expired(&sw))
goto no_codec;

if (azalia_enter_reset(base) < 0)
Expand All @@ -79,12 +82,12 @@ static int codec_detect(u8 *base)
goto no_codec;

/* Read in Codec location (BAR + 0xe)[2..0] */
reg32 = read32(base + HDA_STATESTS_REG);
reg32 &= 0x0f;
if (!reg32)
reg16 = read16(base + HDA_STATESTS_REG);
reg16 &= codec_mask;
if (!reg16)
goto no_codec;

return reg32;
return reg16;

no_codec:
/* Codec Not found */
Expand Down Expand Up @@ -145,10 +148,11 @@ u32 azalia_find_verb(const u32 *verb_table, u32 verb_table_bytes, u32 viddid, co

static int wait_for_ready(u8 *base)
{
struct stopwatch sw;
/* Use a 50 usec timeout - the Linux kernel uses the same duration */
int timeout = 50;
stopwatch_init_usecs_expire(&sw, 50);

while (timeout--) {
while (!stopwatch_expired(&sw)) {
u32 reg32 = read32(base + HDA_ICII_REG);
if (!(reg32 & HDA_ICII_BUSY))
return 0;
Expand All @@ -159,26 +163,30 @@ static int wait_for_ready(u8 *base)
}

/*
* Wait 50usec for the codec to indicate that it accepted the previous command.
* No response would imply that the code is non-operative.
* Wait for the codec to indicate that it accepted the previous command.
* No response would imply that the codec is non-operative.
*/

static int wait_for_valid(u8 *base)
{
struct stopwatch sw;
u32 reg32;
/* Use a 50 usec timeout - the Linux kernel uses the same duration */
int timeout = 25;

/* Send the verb to the codec */
reg32 = read32(base + HDA_ICII_REG);
reg32 |= HDA_ICII_BUSY | HDA_ICII_VALID;
write32(base + HDA_ICII_REG, reg32);

while (timeout--)
udelay(1);

timeout = 50;
while (timeout--) {
/*
* The timeout is never reached when the codec is functioning properly.
* Using a small timeout value can result in spurious errors with some
* codecs, e.g. a codec that is slow to respond but operates correctly.
* When a codec is non-operative, the timeout is only reached once per
* verb table, thus the impact on booting time is relatively small. So,
* use a reasonably long enough timeout to cover all possible cases.
*/
stopwatch_init_msecs_expire(&sw, 1);
while (!stopwatch_expired(&sw)) {
reg32 = read32(base + HDA_ICII_REG);
if ((reg32 & (HDA_ICII_VALID | HDA_ICII_BUSY)) == HDA_ICII_VALID)
return 0;
Expand Down Expand Up @@ -254,21 +262,23 @@ static void codec_init(struct device *dev, u8 *base, int addr)
mainboard_azalia_program_runtime_verbs(base, reg32);
}

static void codecs_init(struct device *dev, u8 *base, u32 codec_mask)
static void codecs_init(struct device *dev, u8 *base, u16 codec_mask)
{
int i;

for (i = 2; i >= 0; i--) {
for (i = CONFIG_AZALIA_MAX_CODECS - 1; i >= 0; i--) {
if (codec_mask & (1 << i))
codec_init(dev, base, i);
}

azalia_program_verb_table(base, pc_beep_verbs, pc_beep_verbs_size);
}

void azalia_audio_init(struct device *dev)
{
u8 *base;
struct resource *res;
u32 codec_mask;
u16 codec_mask;

res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!res)
Expand Down
4 changes: 2 additions & 2 deletions src/device/device.c
Expand Up @@ -228,9 +228,9 @@ static void set_vga_bridge_bits(void)
/* If we prefer plugin VGA over chipset VGA, the chipset might
want to know. */
if (!CONFIG(ONBOARD_VGA_IS_PRIMARY) && (vga != vga_onboard) &&
vga_onboard && vga_onboard->ops && vga_onboard->ops->disable) {
vga_onboard && vga_onboard->ops && vga_onboard->ops->vga_disable) {
printk(BIOS_DEBUG, "Use plugin graphics over integrated.\n");
vga_onboard->ops->disable(vga_onboard);
vga_onboard->ops->vga_disable(vga_onboard);
}

if (vga) {
Expand Down
15 changes: 8 additions & 7 deletions src/device/pci_device.c
Expand Up @@ -882,14 +882,15 @@ static struct device_operations *get_pci_bridge_ops(struct device *dev)
case PCI_EXP_TYPE_DOWNSTREAM:
printk(BIOS_DEBUG, "%s subordinate bus PCI Express\n",
dev_path(dev));
#if CONFIG(PCIEXP_HOTPLUG)
u16 sltcap;
sltcap = pci_read_config16(dev, pciexpos + PCI_EXP_SLTCAP);
if (sltcap & PCI_EXP_SLTCAP_HPC) {
printk(BIOS_DEBUG, "%s hot-plug capable\n", dev_path(dev));
return &default_pciexp_hotplug_ops_bus;
if (CONFIG(PCIEXP_HOTPLUG)) {
u16 sltcap;
sltcap = pci_read_config16(dev, pciexpos + PCI_EXP_SLTCAP);
if (sltcap & PCI_EXP_SLTCAP_HPC) {
printk(BIOS_DEBUG, "%s hot-plug capable\n",
dev_path(dev));
return &default_pciexp_hotplug_ops_bus;
}
}
#endif /* CONFIG(PCIEXP_HOTPLUG) */
return &default_pciexp_ops_bus;
case PCI_EXP_TYPE_PCI_BRIDGE:
printk(BIOS_DEBUG, "%s subordinate PCI\n",
Expand Down
2 changes: 1 addition & 1 deletion src/device/pci_rom.c
Expand Up @@ -178,7 +178,7 @@ static struct rom_header *check_initialized(const struct device *dev)
struct rom_header *run_rom;
struct pci_data *rom_data;

if (!CONFIG(VGA_ROM_RUN))
if (!CONFIG(VGA_ROM_RUN) && !CONFIG(RUN_FSP_GOP))
return NULL;

run_rom = (struct rom_header *)(uintptr_t)PCI_VGA_RAM_IMAGE_START;
Expand Down
111 changes: 69 additions & 42 deletions src/device/pciexp_device.c
Expand Up @@ -129,66 +129,92 @@ static void pciexp_enable_clock_power_pm(struct device *endp, unsigned int endp_
pci_write_config16(endp, endp_cap + PCI_EXP_LNKCTL, lnkctl);
}

static void pciexp_config_max_latency(struct device *root, struct device *dev)
static bool _pciexp_ltr_supported(struct device *dev, unsigned int cap)
{
unsigned int cap;
cap = pciexp_find_extended_cap(dev, PCIE_EXT_CAP_LTR_ID);
if ((cap) && (root->ops->ops_pci != NULL) &&
(root->ops->ops_pci->set_L1_ss_latency != NULL))
root->ops->ops_pci->set_L1_ss_latency(dev, cap + 4);
return pci_read_config16(dev, cap + PCI_EXP_DEVCAP2) & PCI_EXP_DEVCAP2_LTR;
}

static bool pciexp_is_ltr_supported(struct device *dev, unsigned int cap)
static bool _pciexp_ltr_enabled(struct device *dev, unsigned int cap)
{
unsigned int val;
return pci_read_config16(dev, cap + PCI_EXP_DEVCTL2) & PCI_EXP_DEV2_LTR;
}

val = pci_read_config16(dev, cap + PCI_EXP_DEV_CAP2_OFFSET);
static bool _pciexp_enable_ltr(struct device *parent, unsigned int parent_cap,
struct device *dev, unsigned int cap)
{
if (!_pciexp_ltr_supported(dev, cap)) {
printk(BIOS_DEBUG, "%s: No LTR support\n", dev_path(dev));
return false;
}

if (val & LTR_MECHANISM_SUPPORT)
if (_pciexp_ltr_enabled(dev, cap))
return true;

return false;
if (parent &&
(parent->path.type != DEVICE_PATH_PCI ||
!_pciexp_ltr_supported(parent, parent_cap) ||
!_pciexp_ltr_enabled(parent, parent_cap)))
return false;

pci_or_config16(dev, cap + PCI_EXP_DEVCTL2, PCI_EXP_DEV2_LTR);
printk(BIOS_INFO, "%s: Enabled LTR\n", dev_path(dev));
return true;
}

static void pciexp_configure_ltr(struct device *dev)
static void pciexp_enable_ltr(struct device *dev)
{
unsigned int cap;

cap = pci_find_capability(dev, PCI_CAP_ID_PCIE);
const unsigned int cap = pci_find_capability(dev, PCI_CAP_ID_PCIE);
if (!cap)
return;

/*
* Check if capability pointer is valid and
* device supports LTR mechanism.
* If we have get_ltr_max_latencies(), treat `dev` as the root.
* If not, let _pciexp_enable_ltr() query the parent's state.
*/
if (!cap || !pciexp_is_ltr_supported(dev, cap)) {
printk(BIOS_INFO, "Failed to enable LTR for dev = %s\n",
dev_path(dev));
return;
struct device *parent = NULL;
unsigned int parent_cap = 0;
if (!dev->ops->ops_pci || !dev->ops->ops_pci->get_ltr_max_latencies) {
parent = dev->bus->dev;
parent_cap = pci_find_capability(dev, PCI_CAP_ID_PCIE);
if (!parent_cap)
return;
}

cap += PCI_EXP_DEV_CTL_STS2_CAP_OFFSET;
(void)_pciexp_enable_ltr(parent, parent_cap, dev, cap);
}

/* Enable LTR for device */
pci_update_config32(dev, cap, ~LTR_MECHANISM_EN, LTR_MECHANISM_EN);
static bool pciexp_get_ltr_max_latencies(struct device *dev, u16 *max_snoop, u16 *max_nosnoop)
{
/* Walk the hierarchy up to find get_ltr_max_latencies(). */
do {
if (dev->ops->ops_pci && dev->ops->ops_pci->get_ltr_max_latencies)
break;
if (dev->bus->dev == dev || dev->bus->dev->path.type != DEVICE_PATH_PCI)
return false;
dev = dev->bus->dev;
} while (true);

/* Configure Max Snoop Latency */
pciexp_config_max_latency(dev->bus->dev, dev);
dev->ops->ops_pci->get_ltr_max_latencies(max_snoop, max_nosnoop);
return true;
}

static void pciexp_enable_ltr(struct device *dev)
static void pciexp_configure_ltr(struct device *parent, unsigned int parent_cap,
struct device *dev, unsigned int cap)
{
struct bus *bus;
struct device *child;
if (!_pciexp_enable_ltr(parent, parent_cap, dev, cap))
return;

for (bus = dev->link_list ; bus ; bus = bus->next) {
for (child = bus->children; child; child = child->sibling) {
if (child->path.type != DEVICE_PATH_PCI)
continue;
pciexp_configure_ltr(child);
if (child->ops && child->ops->scan_bus)
pciexp_enable_ltr(child);
}
}
const unsigned int ltr_cap = pciexp_find_extended_cap(dev, PCIE_EXT_CAP_LTR_ID);
if (!ltr_cap)
return;

u16 max_snoop, max_nosnoop;
if (!pciexp_get_ltr_max_latencies(dev, &max_snoop, &max_nosnoop))
return;

pci_write_config16(dev, ltr_cap + PCI_LTR_MAX_SNOOP, max_snoop);
pci_write_config16(dev, ltr_cap + PCI_LTR_MAX_NOSNOOP, max_nosnoop);
printk(BIOS_INFO, "%s: Programmed LTR max latencies\n", dev_path(dev));
}

static unsigned char pciexp_L1_substate_cal(struct device *dev, unsigned int endp_cap,
Expand Down Expand Up @@ -475,12 +501,17 @@ static void pciexp_tune_dev(struct device *dev)

/* Adjust Max_Payload_Size of link ends. */
pciexp_set_max_payload_size(root, root_cap, dev, cap);

pciexp_configure_ltr(root, root_cap, dev, cap);
}

void pciexp_scan_bus(struct bus *bus, unsigned int min_devfn,
unsigned int max_devfn)
{
struct device *child;

pciexp_enable_ltr(bus->dev);

pci_scan_bus(bus, min_devfn, max_devfn);

for (child = bus->children; child; child = child->sibling) {
Expand All @@ -497,7 +528,6 @@ void pciexp_scan_bus(struct bus *bus, unsigned int min_devfn,
void pciexp_scan_bridge(struct device *dev)
{
do_pci_scan_bridge(dev, pciexp_scan_bus);
pciexp_enable_ltr(dev);
}

/** Default device operations for PCI Express bridges */
Expand All @@ -514,8 +544,6 @@ struct device_operations default_pciexp_ops_bus = {
.ops_pci = &pciexp_bus_ops_pci,
};

#if CONFIG(PCIEXP_HOTPLUG)

static void pciexp_hotplug_dummy_read_resources(struct device *dev)
{
struct resource *resource;
Expand Down Expand Up @@ -575,4 +603,3 @@ struct device_operations default_pciexp_hotplug_ops_bus = {
.reset_bus = pci_bus_reset,
.ops_pci = &pciexp_bus_ops_pci,
};
#endif /* CONFIG(PCIEXP_HOTPLUG) */
2 changes: 1 addition & 1 deletion src/drivers/analogix/anx7625/anx7625.c
Expand Up @@ -381,7 +381,7 @@ static int anx7625_dsi_video_config(uint8_t bus, struct display_timing *dt)
ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_PLL_N_NUM_7_0,
(n & 0xff));
/* diff */
ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_DIGITAL_ADJ_1, 0x37);
ret |= anx7625_reg_write(bus, RX_P1_ADDR, MIPI_DIGITAL_ADJ_1, 0x3d);

ret |= anx7625_odfc_config(bus, post_divider - 1);

Expand Down
3 changes: 3 additions & 0 deletions src/drivers/generic/alc1015/Kconfig
@@ -0,0 +1,3 @@
config DRIVERS_GENERIC_ALC1015
bool
depends on HAVE_ACPI_TABLES
1 change: 1 addition & 0 deletions src/drivers/generic/alc1015/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_GENERIC_ALC1015) += alc1015.c
72 changes: 72 additions & 0 deletions src/drivers/generic/alc1015/alc1015.c
@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/device.h>
#include <device/path.h>
#include "chip.h"

static void alc1015_fill_ssdt(const struct device *dev)
{
struct drivers_generic_alc1015_config *config = dev->chip_info;
const char *path;
struct acpi_dp *dp;

if (!config)
return;

const char *scope = acpi_device_scope(dev);
const char *name = acpi_device_name(dev);
if (!scope || !name)
return;

/* Device */
acpigen_write_scope(scope);
acpigen_write_device(name);

acpigen_write_name_string("_HID", "RTL1015");
acpigen_write_name_integer("_UID", 0);
acpigen_write_name_string("_DDN", dev->chip_ops->name);
acpigen_write_STA(acpi_device_status(dev));

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_gpio(&config->sdb);
acpigen_write_resourcetemplate_footer();

/* _DSD for devicetree properties */
/* This points to the first pin in the first gpio entry in _CRS */
path = acpi_device_path(dev);
dp = acpi_dp_new_table("_DSD");
acpi_dp_add_gpio(dp, "sdb-gpios", path, 0, 0, config->sdb.active_low);
acpi_dp_write(dp);

acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */

printk(BIOS_INFO, "%s: %s\n", path, dev->chip_ops->name);
}

static const char *alc1015_acpi_name(const struct device *dev)
{
return "ALCP";
}

static struct device_operations alc1015_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = alc1015_acpi_name,
.acpi_fill_ssdt = alc1015_fill_ssdt,
};

static void alc1015_enable(struct device *dev)
{
dev->ops = &alc1015_ops;
}

struct chip_operations drivers_generic_alc1015_ops = {
CHIP_NAME("ASoC RT1015P Amplifier driver")
.enable_dev = alc1015_enable
};
8 changes: 8 additions & 0 deletions src/drivers/generic/alc1015/chip.h
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_device.h>

struct drivers_generic_alc1015_config {
/* SDMODE GPIO */
struct acpi_gpio sdb;
};
19 changes: 4 additions & 15 deletions src/drivers/generic/cbfs-serial/cbfs-serial.c
Expand Up @@ -10,25 +10,14 @@
const char *smbios_mainboard_serial_number(void)
{
static char serial_number[MAX_SERIAL_LENGTH + 1] = {0};
struct cbfsf file;

if (serial_number[0] != 0)
return serial_number;

if (cbfs_boot_locate(&file, "serial_number", NULL) == 0) {
struct region_device cbfs_region;
size_t serial_len;

cbfs_file_data(&cbfs_region, &file);

serial_len = region_device_sz(&cbfs_region);
if (serial_len <= MAX_SERIAL_LENGTH) {
if (rdev_readat(&cbfs_region, serial_number, 0,
serial_len) == serial_len) {
serial_number[serial_len] = 0;
return serial_number;
}
}
size_t serial_len = cbfs_load("serial_number", serial_number, MAX_SERIAL_LENGTH);
if (serial_len) {
serial_number[serial_len] = '\0';
return serial_number;
}

strncpy(serial_number, CONFIG_MAINBOARD_SERIAL_NUMBER,
Expand Down
1 change: 1 addition & 0 deletions src/drivers/generic/max98357a/Kconfig
@@ -1,2 +1,3 @@
config DRIVERS_GENERIC_MAX98357A
bool
depends on HAVE_ACPI_TABLES
5 changes: 0 additions & 5 deletions src/drivers/generic/max98357a/max98357a.c
Expand Up @@ -8,8 +8,6 @@
#include <gpio.h>
#include "chip.h"

#if CONFIG(HAVE_ACPI_TABLES)

#define MAX98357A_ACPI_NAME "MAXM"

static void max98357a_fill_ssdt(const struct device *dev)
Expand Down Expand Up @@ -65,15 +63,12 @@ static const char *max98357a_acpi_name(const struct device *dev)
{
return MAX98357A_ACPI_NAME;
}
#endif

static struct device_operations max98357a_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = max98357a_acpi_name,
.acpi_fill_ssdt = max98357a_fill_ssdt,
#endif
};

static void max98357a_enable(struct device *dev)
Expand Down
1 change: 1 addition & 0 deletions src/drivers/i2c/rx6110sa/rx6110sa.c
Expand Up @@ -198,6 +198,7 @@ static void rx6110sa_fill_ssdt(const struct device *dev)
/* Device */
acpigen_write_scope(scope);
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name_string("_HID", RX6110SA_HID_NAME);
acpigen_write_name_string("_DDN", RX6110SA_HID_DESC);
acpigen_write_STA(acpi_device_status(dev));

Expand Down
1 change: 1 addition & 0 deletions src/drivers/i2c/rx6110sa/rx6110sa.h
Expand Up @@ -4,6 +4,7 @@
#define _I2C_RX6110SA_H_

#define RX6110SA_ACPI_NAME "ERX6"
#define RX6110SA_HID_NAME "SECC6110"
#define RX6110SA_HID_DESC "Real Time Clock"

/* Register layout */
Expand Down
44 changes: 40 additions & 4 deletions src/drivers/i2c/sx9310/chip.h
Expand Up @@ -6,7 +6,18 @@
#include <acpi/acpi_device.h>
#include <device/i2c_simple.h>

#define REGISTER(NAME) uint8_t NAME
#define MAX_COMBINED_SENSORS_ENTRIES 4

enum sx9310_resolution {
SX9310_COARSEST = 1,
SX9310_VERY_COARSE,
SX9310_COARSE,
SX9310_MEDIUM_COARSE,
SX9310_MEDIUM,
SX9310_FINE,
SX9310_VERY_FINE,
SX9310_FINEST,
};

struct drivers_i2c_sx9310_config {
/* Device Description */
Expand All @@ -23,9 +34,34 @@ struct drivers_i2c_sx9310_config {

/* IO-APIC interrupt */
struct acpi_irq irq;
#include "registers.h"
};

#undef REGISTER
/*
* Registers definition in the kernel source tree at:
* Documentation/devicetree/bindings/iio/proximity/semtech,sx9310.yaml
*/

/* When true, cs0 is the ground. 0 [default] is false. */
uint32_t cs0_ground;

/* Sensor used for start-up proximity detection: Default 0. */
uint32_t startup_sensor;

/* Raw Proximity filter strength: When not set, disabled. */
uint32_t proxraw_strength;

/* Average Proximity filter strength: When not set, disabled. */
uint32_t avg_pos_strength;

/*
* List of which sensors are combined and represented by CS3.
* Could be standalone (3) or combination of 0, 1, 2, 3.
* Driver default: CS0 + CS1.
*/
uint32_t combined_sensors_count;
uint32_t combined_sensors[MAX_COMBINED_SENSORS_ENTRIES];

/* Capacitance measure resolution. Driver default: "finest". */
enum sx9310_resolution resolution;
};

#endif /* __DRIVERS_I2C_SX9310_CHIP_H__ */
29 changes: 0 additions & 29 deletions src/drivers/i2c/sx9310/registers.h

This file was deleted.

46 changes: 39 additions & 7 deletions src/drivers/i2c/sx9310/sx9310.c
Expand Up @@ -12,9 +12,16 @@
#define I2C_SX9310_ACPI_ID "STH9310"
#define I2C_SX9310_ACPI_NAME "Semtech SX9310"

#define REGISTER(NAME) acpi_dp_add_integer(dsd, \
I2C_SX9310_ACPI_ID "," #NAME, \
config->NAME)
static const char * const i2c_sx9310_resolution[] = {
[SX9310_COARSEST] = "coarsest",
[SX9310_VERY_COARSE] = "very-coarse",
[SX9310_COARSE] = "coarse",
[SX9310_MEDIUM_COARSE] = "medium-coarse",
[SX9310_MEDIUM] = "medium",
[SX9310_FINE] = "fine",
[SX9310_VERY_FINE] = "very-fine",
[SX9310_FINEST] = "finest",
};

static void i2c_sx9310_fill_ssdt(const struct device *dev)
{
Expand All @@ -27,6 +34,7 @@ static void i2c_sx9310_fill_ssdt(const struct device *dev)
.resource = scope,
};
struct acpi_dp *dsd;
struct acpi_dp *combined_sensors;

if (!scope || !config)
return;
Expand Down Expand Up @@ -56,18 +64,42 @@ static void i2c_sx9310_fill_ssdt(const struct device *dev)

/* DSD */
dsd = acpi_dp_new_table("_DSD");
#include "registers.h"
acpi_dp_write(dsd);

/*
* Format describe in linux kernel documentation. See
* https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/proximity/semtech%2Csx9310.yaml
*/
acpi_dp_add_integer(dsd, "semtech,cs0-ground", config->cs0_ground);
acpi_dp_add_integer(dsd, "semtech,startup-sensor",
config->startup_sensor);
acpi_dp_add_integer(dsd, "semtech,proxraw-strength",
config->proxraw_strength);
acpi_dp_add_integer(dsd, "semtech,avg-pos-strength",
config->avg_pos_strength);

/* Add combined_sensors package */
if (config->combined_sensors_count > 0) {
combined_sensors = acpi_dp_new_table("semtech,combined-sensors");
for (int i = 0;
i < config->combined_sensors_count &&
i < MAX_COMBINED_SENSORS_ENTRIES; ++i) {
acpi_dp_add_integer(combined_sensors, NULL,
config->combined_sensors[i]);
}
acpi_dp_add_array(dsd, combined_sensors);
}
if (config->resolution && config->resolution < ARRAY_SIZE(i2c_sx9310_resolution))
acpi_dp_add_string(dsd, "semtech,resolution",
i2c_sx9310_resolution[config->resolution]);

acpi_dp_write(dsd);
acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */

printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev),
config->desc ? : dev->chip_ops->name, dev_path(dev));
}

#undef REGISTER

static const char *i2c_sx9310_acpi_name(const struct device *dev)
{
static char name[5];
Expand Down
1 change: 1 addition & 0 deletions src/drivers/intel/dptf/dptf.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpigen.h>
#include <acpi/acpigen_pci.h>
#include <console/console.h>
#include <device/device.h>
#include "chip.h"
Expand Down
8 changes: 4 additions & 4 deletions src/drivers/intel/fsp1_1/car.c
Expand Up @@ -2,13 +2,13 @@

#include <arch/romstage.h>
#include <arch/symbols.h>
#include <cbfs.h>
#include <cbmem.h>
#include <console/console.h>
#include <commonlib/helpers.h>
#include <cpu/x86/mtrr.h>
#include <fsp/car.h>
#include <fsp/util.h>
#include <program_loading.h>

void fill_postcar_frame(struct postcar_frame *pcf)
{
Expand All @@ -27,14 +27,14 @@ void mainboard_romstage_entry(void)
{
/* Need to locate the current FSP_INFO_HEADER. The cache-as-ram
* is still enabled. We can directly access work buffer here. */
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");
void *fsp = cbfs_map("fsp.bin", NULL);

if (prog_locate(&fsp))
if (!fsp)
die_with_post_code(POST_INVALID_CBFS, "Unable to locate fsp.bin");

/* This leaks a mapping which this code assumes is benign as
* the flash is memory mapped CPU's address space. */
FSP_INFO_HEADER *fih = find_fsp((uintptr_t)rdev_mmap_full(prog_rdev(&fsp)));
FSP_INFO_HEADER *fih = find_fsp((uintptr_t)fsp);

if (!fih)
die("Invalid FSP header\n");
Expand Down
15 changes: 5 additions & 10 deletions src/drivers/intel/fsp1_1/fsp_relocate.c
@@ -1,29 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cbfs.h>
#include <cbmem.h>
#include <commonlib/fsp.h>
#include <fsp/util.h>

int fsp_relocate(struct prog *fsp_relocd, const struct region_device *fsp_src)
int fsp_relocate(struct prog *fsp_relocd)
{
void *new_loc;
void *fih;
ssize_t fih_offset;
size_t size = region_device_sz(fsp_src);

new_loc = cbmem_add(CBMEM_ID_REFCODE, size);
size_t size;

void *new_loc = cbfs_cbmem_alloc(prog_name(fsp_relocd),
CBMEM_ID_REFCODE, &size);
if (new_loc == NULL) {
printk(BIOS_ERR, "ERROR: Unable to load FSP into memory.\n");
return -1;
}

if (rdev_readat(fsp_src, new_loc, 0, size) != size) {
printk(BIOS_ERR, "ERROR: Can't read FSP's region device.\n");
return -1;
}

fih_offset = fsp1_1_relocate((uintptr_t)new_loc, new_loc, size);

if (fih_offset <= 0) {
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/include/fsp/romstage.h
Expand Up @@ -34,7 +34,6 @@ void mainboard_add_dimm_info(struct romstage_params *params,
struct memory_info *mem_info,
int channel, int dimm, int index);
void raminit(struct romstage_params *params);
void report_memory_config(void);
/* Initialize memory margin analysis settings. */
void setup_mma(MEMORY_INIT_UPD *memory_upd);
void soc_after_ram_init(struct romstage_params *params);
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/fsp1_1/include/fsp/util.h
Expand Up @@ -40,10 +40,10 @@ static inline uint32_t fsp_version(FSP_INFO_HEADER *fih)

/*
* Relocate FSP entire binary into ram. Returns < 0 on error, 0 on success.
* The FSP source is pointed to by region_device and the relocation information
* The CBFS file name of the FSP source and the relocation information
* is encoded in a struct prog with its entry point set to the FSP info header.
*/
int fsp_relocate(struct prog *fsp_relocd, const struct region_device *fsp_src);
int fsp_relocate(struct prog *fsp_relocd);

/* Additional HOB types not included in the FSP:
* #define EFI_HOB_TYPE_HANDOFF 0x0001
Expand Down
3 changes: 0 additions & 3 deletions src/drivers/intel/fsp1_1/raminit.c
Expand Up @@ -237,9 +237,6 @@ void raminit(struct romstage_params *params)
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();

/* Locate the memory configuration data to speed up the next reboot */
mrc_hob = get_next_guid_hob(&mrc_guid, hob_list_ptr);
if (mrc_hob == NULL) {
Expand Down
17 changes: 1 addition & 16 deletions src/drivers/intel/fsp1_1/ramstage.c
Expand Up @@ -144,29 +144,14 @@ static void fsp_run_silicon_init(FSP_INFO_HEADER *fsp_info_header)
soc_after_silicon_init();
}

static int fsp_find_and_relocate(struct prog *fsp)
{
if (prog_locate(fsp)) {
printk(BIOS_ERR, "ERROR: Couldn't find %s\n", prog_name(fsp));
return -1;
}

if (fsp_relocate(fsp, prog_rdev(fsp))) {
printk(BIOS_ERR, "ERROR: FSP relocation failed.\n");
return -1;
}

return 0;
}

static void fsp_load(void)
{
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");

if (resume_from_stage_cache()) {
stage_cache_load_stage(STAGE_REFCODE, &fsp);
} else {
fsp_find_and_relocate(&fsp);
fsp_relocate(&fsp);

if (prog_entry(&fsp))
stage_cache_add(STAGE_REFCODE, &fsp);
Expand Down
5 changes: 0 additions & 5 deletions src/drivers/intel/fsp1_1/romstage.c
Expand Up @@ -291,11 +291,6 @@ __weak int mrc_cache_stash_data(int type, uint32_t version,
return -1;
}

/* Display the memory configuration */
__weak void report_memory_config(void)
{
}

/* SOC initialization after RAM is enabled */
__weak void soc_after_ram_init(struct romstage_params *params)
{
Expand Down
7 changes: 4 additions & 3 deletions src/drivers/intel/fsp1_1/temp_ram_exit.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <cbmem.h>
#include <cbfs.h>
#include <console/console.h>
#include <fsp/util.h>

Expand All @@ -9,13 +10,13 @@ asmlinkage void chipset_teardown_car_main(void)
FSP_INFO_HEADER *fih;
uint32_t status;
FSP_TEMP_RAM_EXIT temp_ram_exit;
struct prog fsp = PROG_INIT(PROG_REFCODE, "fsp.bin");

/* CBMEM_ID_VBOOT_WORKBUF is used as vboot workbuffer.
* Init CBMEM before loading fsp, to have buffer available */
cbmem_initialize();

if (prog_locate(&fsp)) {
void *fsp = cbfs_map("fsp.bin", NULL);
if (!fsp) {
die("Unable to locate fsp.bin\n");
} else {
/* This leaks a mapping which this code assumes is benign as
Expand All @@ -25,7 +26,7 @@ asmlinkage void chipset_teardown_car_main(void)
as it casts error values to FSP_INFO_HEADER pointers.
Checking for return values can only be done sanely once
that is fixed. */
fih = find_fsp((uintptr_t)rdev_mmap_full(prog_rdev(&fsp)));
fih = find_fsp((uintptr_t)fsp);
}

temp_ram_exit = (FSP_TEMP_RAM_EXIT)(fih->TempRamExitEntryOffset +
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/intel/fsp2_0/Kconfig.debug_blob
Expand Up @@ -38,4 +38,11 @@ config DISPLAY_FSP_VERSION_INFO
help
Select this option to display Firmware version information.

config DISPLAY_FSP_VERSION_INFO_2
bool
default n
help
Select this option to display Firmware version information
using new header 'FirmwareVersionInfo.h'.

endif # PLATFORM_USES_FSP2_0
33 changes: 28 additions & 5 deletions src/drivers/intel/fsp2_0/hand_off_block.c
Expand Up @@ -209,26 +209,49 @@ const void *fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size)

static void display_fsp_version_info_hob(const void *hob)
{
#if CONFIG(DISPLAY_FSP_VERSION_INFO) || CONFIG(DISPLAY_FSP_VERSION_INFO_2)

int index, cnt, tcount;
char *str_ptr;
uint8_t vs;
#if CONFIG(DISPLAY_FSP_VERSION_INFO)
const FIRMWARE_VERSION_INFO *fvi;
const FIRMWARE_VERSION_INFO_HOB *fvih =
(FIRMWARE_VERSION_INFO_HOB *)hob;
int index, cnt;
char *str_ptr;

fvi = (void *)&fvih[1];
str_ptr = (char *)((uintptr_t)fvi +
(fvih->Count * sizeof(FIRMWARE_VERSION_INFO)));
tcount = fvih->Count;
#elif CONFIG(DISPLAY_FSP_VERSION_INFO_2)

uint8_t *hobstart = (uint8_t *) hob;
hobstart += sizeof(EFI_HOB_GUID_TYPE);

const SMBIOS_TABLE_TYPE_OEM_INTEL_FVI *stfvi =
(SMBIOS_TABLE_TYPE_OEM_INTEL_FVI *)hobstart;
const INTEL_FIRMWARE_VERSION_INFO *fvi;

for (index = 0; index < fvih->Count; index++) {
str_ptr = ((char *) &(stfvi->Fvi[0])) +
(stfvi->Count * sizeof(INTEL_FIRMWARE_VERSION_INFO));
tcount = stfvi->Count;
fvi = &stfvi->Fvi[0];
#endif

for (index = 0; index < tcount; index++) {
cnt = strlen(str_ptr);

#if CONFIG(DISPLAY_FSP_VERSION_INFO)
vs = fvi[index].VersionStringIndex;
#elif CONFIG(DISPLAY_FSP_VERSION_INFO_2)
vs = fvi[index].VersionString;
#endif
/* Don't show ingredient name and version if its all 0xFF */
if (fvi[index].Version.MajorVersion == 0xFF &&
fvi[index].Version.MinorVersion == 0xFF &&
fvi[index].Version.Revision == 0xFF &&
fvi[index].Version.BuildNumber == 0xFF &&
fvi[index].VersionStringIndex == 0) {
vs == 0) {
str_ptr = (char *)((uintptr_t)str_ptr + cnt +
sizeof(uint8_t));
continue;
Expand All @@ -241,7 +264,7 @@ static void display_fsp_version_info_hob(const void *hob)
*/
printk(BIOS_DEBUG, "%s = ", str_ptr);

if (!fvi[index].VersionStringIndex)
if (!vs)
printk(BIOS_DEBUG, "%x.%x.%x.%x\n",
fvi[index].Version.MajorVersion,
fvi[index].Version.MinorVersion,
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/intel/fsp2_0/include/fsp/ppi/mp_service_ppi.h
Expand Up @@ -24,7 +24,7 @@ efi_return_status_t mp_get_processor_info(efi_uintn_t processor_number,

/* executes a caller provided function on all enabled APs */
efi_return_status_t mp_startup_all_aps(efi_ap_procedure procedure,
efi_uintn_t timeout_usec, void *argument);
bool run_serial, efi_uintn_t timeout_usec, void *argument);

/* executes a caller provided function on all enabled APs + BSP */
efi_return_status_t mp_startup_all_cpus(efi_ap_procedure procedure,
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/intel/fsp2_0/include/fsp/soc_binding.h
Expand Up @@ -29,6 +29,8 @@
#include <FspsUpd.h>
#if CONFIG(DISPLAY_FSP_VERSION_INFO)
#include <FirmwareVersionInfoHob.h>
#elif CONFIG(DISPLAY_FSP_VERSION_INFO_2)
#include <FirmwareVersionInfo.h>
#endif

#pragma pack(pop)
Expand Down
17 changes: 17 additions & 0 deletions src/drivers/intel/fsp2_0/memory_init.c
Expand Up @@ -239,6 +239,23 @@ static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)

upd = (FSPM_UPD *)(uintptr_t)(hdr->cfg_region_offset + hdr->image_base);

/*
* Verify UPD region size. We don't have malloc before ramstage, so we
* use a static buffer for the FSP-M UPDs which is sizeof(FSPM_UPD)
* bytes long, since that is the value known at compile time. If
* hdr->cfg_region_size is bigger than that, not all UPD defaults will
* be copied, so it'll contain random data at the end, so we just call
* die() in that case. If hdr->cfg_region_size is smaller than that,
* there's a mismatch between the FSP and the header, but since it will
* copy the full UPD defaults to the buffer, we try to continue and
* hope that there was no incompatible change in the UPDs.
*/
if (hdr->cfg_region_size > sizeof(FSPM_UPD))
die("FSP-M UPD size is larger than FSPM_UPD struct size.\n");
if (hdr->cfg_region_size < sizeof(FSPM_UPD))
printk(BIOS_ERR, "FSP-M UPD size is smaller than FSPM_UPD struct size. "
"Check if the FSP binary matches the FSP headers.\n");

fsp_verify_upd_header_signature(upd->FspUpdHeader.Signature, FSPM_UPD_SIGNATURE);

/* Copy the default values from the UPD area */
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/fsp2_0/ppi/mp_service1.c
Expand Up @@ -23,10 +23,10 @@ static efi_return_status_t mps1_get_processor_info(const

static efi_return_status_t mps1_startup_all_aps(const
efi_pei_services **ignored1, efi_pei_mp_services_ppi *ignored2,
efi_ap_procedure procedure, efi_boolean_t ignored3,
efi_ap_procedure procedure, efi_boolean_t run_serial,
efi_uintn_t timeout_usec, void *argument)
{
return mp_startup_all_aps(procedure, timeout_usec, argument);
return mp_startup_all_aps(procedure, run_serial, timeout_usec, argument);
}

static efi_return_status_t mps1_startup_this_ap(const
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/intel/fsp2_0/ppi/mp_service2.c
Expand Up @@ -24,10 +24,10 @@ static efi_return_status_t mps2_get_processor_info(

static efi_return_status_t mps2_startup_all_aps(
efi_pei_mp_services_ppi *ignored1,
efi_ap_procedure procedure, efi_boolean_t ignored2,
efi_ap_procedure procedure, efi_boolean_t run_serial,
efi_uintn_t timeout_usec, void *argument)
{
return mp_startup_all_aps(procedure, timeout_usec, argument);
return mp_startup_all_aps(procedure, run_serial, timeout_usec, argument);
}

static efi_return_status_t mps2_startup_all_cpus(
Expand Down