4 changes: 2 additions & 2 deletions Documentation/superio/common/ssdt.md
Expand Up @@ -50,7 +50,7 @@ end
The following methods are generated for each SuperIO:
## AMTX()
Acquire the global mutex and enter config mode.
It's called this at the begining of an atomic operation to make sure
It's called this at the beginning of an atomic operation to make sure
no other ACPI code messes with the config space while working on it.

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

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

## QLDN(Arg0)
Queries the state of the (virtual) LDN given as Arg0.
Expand Down
2 changes: 1 addition & 1 deletion Documentation/superio/nuvoton/npcd378.md
Expand Up @@ -4,7 +4,7 @@ This page describes the [Nuvoton] SuperIO chip that can be found on various [HP]
mainboards.

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

## LDNs

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

Compiler for the host _must_ support the same language standards as the target
compiler. Ideally the same toolchain should be used for building firmware
executables and test binaries, however the host complier will be used to build
executables and test binaries, however the host compiler will be used to build
unit tests, whereas the coreboot toolchain will be used for building the
firmware executables. For some targets, the host compiler and the target
compiler could be the same, but this is not a requirement.
Expand Down
2 changes: 1 addition & 1 deletion Documentation/tutorial/part1.md
Expand Up @@ -123,7 +123,7 @@ are needed to build the coreboot toolchain. `gcc` and `gnat` have to be
of the same version.

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

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

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

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

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

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

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

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

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

###########################################################################
# Common recipes for all stages
Expand Down
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -102,3 +102,12 @@ were derived from other projects, other (GPL-compatible) licenses may apply.
Please check the individual source files for details.

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


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

If you have any trouble or find any bug, please report an issue in
[this location](https://github.com/pcengines/apu2-documentation/issues). To
create the issue, from the list of available templates select the one, that fits
best the nature of the issue (bug, feature, question or task) and fill it.
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_CBFS_SIZE=0x00200000
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,157b"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu4
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu6
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.14.0.5"
CONFIG_LOCALVERSION="v4.14.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_PXE_ROM_ID="8086,1539"
Expand Down
14 changes: 12 additions & 2 deletions payloads/external/tianocore/Kconfig
Expand Up @@ -76,8 +76,18 @@ config TIANOCORE_BOOTSPLASH_FILE
default "bootsplash.bmp"
help
The path and filename of the file to use as graphical bootsplash
screen. The file format must be uncompressed BMP, and the file's
resolution must be less than the native resolution of the display.
image. The file must be an uncompressed BMP.

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

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

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

If an absolute path is not given, the path will assumed to be
relative to the coreboot root directory.
Expand Down
2 changes: 1 addition & 1 deletion payloads/external/tianocore/Kconfig.name
@@ -1,6 +1,6 @@
config PAYLOAD_TIANOCORE
bool "Tianocore payload"
depends on ARCH_X86
depends on ARCH_X86 || ARCH_ARM64
help
Select this option if you want to build a coreboot image
with a Tianocore payload. If you don't know what this is
Expand Down
10 changes: 10 additions & 0 deletions payloads/libpayload/Kconfig
Expand Up @@ -121,6 +121,14 @@ config ARCH_ARM64
help
Support the ARM64 architecture

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

endchoice

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

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

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

ARCH-y := $(ARCHDIR-y)

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

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

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

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

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

else

ifeq ($(CONFIG_LP_ARCH_MOCK),y)

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

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

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

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

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

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

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

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

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

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

if ARCH_MOCK

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

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

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

head.o-y += head.c

libc-y += virtual.c

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

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

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

#include <cbfs.h>

int libpayload_init_default_cbfs_media(struct cbfs_media *media);

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

#include <unistd.h>

unsigned long virtual_offset = 0;

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

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

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

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

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

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

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

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

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

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

free(line);
return CBGFX_SUCCESS;
}

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

#ifndef __ARCH_BARRIER_H__
#define __ARCH_BARRIER_H__

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

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

#ifndef __ARCH_CACHE_H__
#define __ARCH_CACHE_H__

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

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

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

#ifndef _ARCH_IO_H
#define _ARCH_IO_H

#include <inttypes.h>

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

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

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

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

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

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

#ifndef _ARCH_TYPES_H
#define _ARCH_TYPES_H

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

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

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

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

typedef long time_t;
typedef long suseconds_t;

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

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

#ifndef _ARCH_VIRTUAL_H
#define _ARCH_VIRTUAL_H

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

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

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

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


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

include ../build/xcompile

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

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

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

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

all: $(TARGET).elf

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

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

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

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

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

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

/* Example file for libpayload. */

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

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

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

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

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

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

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

TEST_REGION(heap, CONFIG_LP_HEAP_SIZE);

uint64_t timer_raw_value(void)
{
return 0;
}

uint64_t timer_hz(void)
{
return 0;
}

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

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

testsrc := $(top)/tests

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

coreboottop := ../../

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

CMAKE := cmake

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


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

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

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

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

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

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

TEST_LDFLAGS += -Wl,--gc-sections

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

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


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

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

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

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

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

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

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

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

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

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

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

endef

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

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

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

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

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

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

$(TEST_KCONFIG_AUTOCONFIG): $(TEST_KCONFIG_AUTOHEADER)
true

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

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

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

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

.PHONY: coverage-report clean-coverage-report

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

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

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

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

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

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

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

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

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

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

tests-y += speaker-test

speaker-test-srcs += tests/drivers/speaker-test.c
speaker-test-mocks += inb
speaker-test-mocks += outb
speaker-test-mocks += arch_ndelay
speaker-test-cflags += -include $(testsrc)/include/mocks/x86_io.h
148 changes: 148 additions & 0 deletions payloads/libpayload/tests/drivers/speaker-test.c
@@ -0,0 +1,148 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <libpayload.h>
#include <mocks/x86_io.h>

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

#include <tests/test.h>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

setup_speaker_disable_calls(0xfc);
speaker_disable();

setup_speaker_disable_calls(0xff);
speaker_disable();

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

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

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

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

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

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

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

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

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

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

#ifndef TESTS_MOCKS_X86_IO_H_
#define TESTS_MOCKS_X86_IO_H_

unsigned int inl(int port);

unsigned short inw(int port);

unsigned char inb(int port);

void outl(unsigned int val, int port);

void outw(unsigned short val, int port);

void outb(unsigned char val, int port);

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

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

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

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

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

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

#endif
52 changes: 52 additions & 0 deletions payloads/libpayload/tests/include/tests/test.h
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _TESTS_TEST_H
#define _TESTS_TEST_H

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

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

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

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

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

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

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

#endif /* _TESTS_TEST_H */
3 changes: 2 additions & 1 deletion src/Kconfig
Expand Up @@ -677,7 +677,7 @@ config TIMER_QUEUE

config COOP_MULTITASKING
def_bool n
depends on TIMER_QUEUE && ARCH_X86
depends on TIMER_QUEUE && ARCH_X86 && CPU_INFO_V2
help
Cooperative multitasking allows callbacks to be multiplexed on the
main thread of ramstage. With this enabled it allows for multiple
Expand Down Expand Up @@ -717,6 +717,7 @@ config PCI_IO_CFG_EXT

config IOAPIC
bool
default y if SMP
default n

config USE_WATCHDOG_ON_BOOT
Expand Down
22 changes: 15 additions & 7 deletions src/acpi/acpi.c
Expand Up @@ -263,6 +263,13 @@ void acpi_create_madt(acpi_madt_t *madt)
header->checksum = acpi_checksum((void *)madt, header->length);
}

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

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

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

/* (Re)calculate length and checksum. */
header->length = current - (unsigned long)mcfg;
Expand Down Expand Up @@ -1937,9 +1945,9 @@ int get_acpi_table_revision(enum acpi_tables table)
return 2;
case TPM2:
return 4;
case SSDT: /* ACPI 3.0 upto 6.3: 2 */
case SSDT: /* ACPI 3.0 up to 6.3: 2 */
return 2;
case SRAT: /* ACPI 2.0: 1, ACPI 3.0: 2, ACPI 4.0 upto 6.3: 3 */
case SRAT: /* ACPI 2.0: 1, ACPI 3.0: 2, ACPI 4.0 up to 6.3: 3 */
return 1; /* TODO Should probably be upgraded to 2 */
case HMAT: /* ACPI 6.4: 2 */
return 2;
Expand All @@ -1959,13 +1967,13 @@ int get_acpi_table_revision(enum acpi_tables table)
return IVRS_FORMAT_MIXED;
case DBG2:
return 0;
case FACS: /* ACPI 2.0/3.0: 1, ACPI 4.0 upto 6.3: 2 */
case FACS: /* ACPI 2.0/3.0: 1, ACPI 4.0 up to 6.3: 2 */
return 1;
case RSDT: /* ACPI 1.0 upto 6.3: 1 */
case RSDT: /* ACPI 1.0 up to 6.3: 1 */
return 1;
case XSDT: /* ACPI 2.0 upto 6.3: 1 */
case XSDT: /* ACPI 2.0 up to 6.3: 1 */
return 1;
case RSDP: /* ACPI 2.0 upto 6.3: 2 */
case RSDP: /* ACPI 2.0 up to 6.3: 2 */
return 2;
case EINJ:
return 1;
Expand Down
16 changes: 7 additions & 9 deletions src/acpi/acpigen.c
Expand Up @@ -994,7 +994,7 @@ void acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
acpigen_pop_len();
}

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

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

for (i = 0; i < max; ++i) {
const acpi_addr_t *reg = &(config->regs[i]);
if (reg->space_id == ACPI_ADDRESS_SPACE_MEMORY &&
reg->bit_width == 32 && reg->access_size == ACPI_ACCESS_SIZE_UNDEFINED) {
acpigen_write_dword(reg->addrl);
} else {
acpigen_write_register_resource(reg);
}
const cppc_entry_t *entry = &config->entries[i];
if (entry->type == CPPC_TYPE_DWORD)
acpigen_write_dword(entry->dword);
else
acpigen_write_register_resource(&entry->reg);
}
acpigen_pop_len();
}
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/device.c
Expand Up @@ -139,7 +139,7 @@ static ssize_t acpi_device_path_fill(const struct device *dev, char *buf,

/*
* Warning: just as with dev_path() this uses a static buffer
* so should not be called mulitple times in one statement
* so should not be called multiple times in one statement
*/
const char *acpi_device_path(const struct device *dev)
{
Expand Down
2 changes: 1 addition & 1 deletion src/arch/arm/armv7/cpu.S
Expand Up @@ -16,7 +16,7 @@
* the LSB of the set field, but the latter contains the LSB of the way field
* minus the highest valid set field... such that when you subtract it from a
* [way:0:level] field you end up with a [way - 1:highest_set:level] field
* through the magic of double subtraction. It's quite ingenius, really.
* through the magic of double subtraction. It's quite ingenious, really.
* Takes care to only use r0-r3 and ip so it's pefectly ABI-compatible without
* needing to write to memory.
*
Expand Down
2 changes: 1 addition & 1 deletion src/arch/arm64/include/arch/asm.h
Expand Up @@ -19,7 +19,7 @@
.size name, .-name

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

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

#define MAX_KERNEL_SIZE (64*MiB)

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

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

void run_opensbi(const int hart_id,
const void *fdt,
Expand Down
3 changes: 0 additions & 3 deletions src/arch/x86/assembly_entry.S
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

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

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

push_cpu_info

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

push_cpu_info

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

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

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

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

.globl gdt, gdt_end
.global per_cpu_segment_descriptors, per_cpu_segment_selector

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

.data
.data

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

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

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

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

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

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

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

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

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

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

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

#endif
67 changes: 40 additions & 27 deletions src/arch/x86/ioapic.c
Expand Up @@ -27,18 +27,44 @@ static void write_vector(void *ioapic_base, u8 vector, u32 high, u32 low)
vector, high, low);
}

static int ioapic_interrupt_count(void *ioapic_base)
/* Bits 23-16 of register 0x01 specify the maximum redirection entry, which
* is the number of interrupts minus 1. */
unsigned int ioapic_get_max_vectors(void *ioapic_base)
{
/* Read the available number of interrupts. */
int ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
if (!ioapic_interrupts || ioapic_interrupts == 0xff)
ioapic_interrupts = 23;
ioapic_interrupts += 1; /* Bits 23-16 specify the maximum redirection
entry, which is the number of interrupts
minus 1. */
printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);

return ioapic_interrupts;
u32 reg;
u8 count;

reg = io_apic_read(ioapic_base, 0x01);
count = (reg >> 16) & 0xff;

if (count == 0xff)
count = 23;
count++;

printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", count);
return count;
}

/* Set maximum number of redirection entries (MRE). It is write-once register
* for some chipsets, and a negative mre_count will lock it to the number
* of vectors read from the register. */
void ioapic_set_max_vectors(void *ioapic_base, int mre_count)
{
u32 reg;
u8 count;

reg = io_apic_read(ioapic_base, 0x01);
count = (reg >> 16) & 0xff;
if (mre_count > 0)
count = mre_count - 1;
reg &= ~(0xff << 16);
reg |= count << 16;
io_apic_write(ioapic_base, 0x01, reg);
}

void ioapic_lock_max_vectors(void *ioapic_base)
{
ioapic_set_max_vectors(ioapic_base, -1);
}

static void clear_vectors(void *ioapic_base, u8 first, u8 last)
Expand All @@ -60,11 +86,6 @@ static void clear_vectors(void *ioapic_base, u8 first, u8 last)
}
}

void clear_ioapic(void *ioapic_base)
{
clear_vectors(ioapic_base, 0, ioapic_interrupt_count(ioapic_base) - 1);
}

static void route_i8259_irq0(void *ioapic_base)
{
u32 bsp_lapicid = lapicid();
Expand Down Expand Up @@ -136,17 +157,9 @@ void ioapic_set_boot_config(void *ioapic_base, bool irq_on_fsb)
}
}

void setup_ioapic_helper(void *ioapic_base, u8 ioapic_id, bool enable_virtual_wire)
{
set_ioapic_id(ioapic_base, ioapic_id);
clear_ioapic(ioapic_base);

if (enable_virtual_wire)
route_i8259_irq0(ioapic_base);
}


void setup_ioapic(void *ioapic_base, u8 ioapic_id)
{
setup_ioapic_helper(ioapic_base, ioapic_id, true);
set_ioapic_id(ioapic_base, ioapic_id);
clear_vectors(ioapic_base, 0, ioapic_get_max_vectors(ioapic_base) - 1);
route_i8259_irq0(ioapic_base);
}
49 changes: 49 additions & 0 deletions src/arch/x86/smbios.c
Expand Up @@ -489,6 +489,7 @@ static int smbios_write_type1(unsigned long *current, int handle)
t->manufacturer = smbios_add_string(t->eos, smbios_system_manufacturer());
t->product_name = smbios_add_string(t->eos, smbios_system_product_name());
t->serial_number = smbios_add_string(t->eos, smbios_system_serial_number());
t->wakeup_type = smbios_system_wakeup_type();
t->sku = smbios_add_string(t->eos, smbios_system_sku());
t->version = smbios_add_string(t->eos, smbios_system_version());
#ifdef CONFIG_MAINBOARD_FAMILY
Expand Down Expand Up @@ -1031,6 +1032,50 @@ static int smbios_write_type19(unsigned long *current, int *handle, int type16)
return len;
}

static int smbios_write_type20_table(unsigned long *current, int *handle, u32 addr_start,
u32 addr_end, int type17_handle, int type19_handle)
{
struct smbios_type20 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE_MAPPED_ADDRESS,
sizeof(*t), *handle);

t->memory_device_handle = type17_handle;
t->memory_array_mapped_address_handle = type19_handle;
t->addr_start = addr_start;
t->addr_end = addr_end;
t->partition_row_pos = 0xff;
t->interleave_pos = 0xff;
t->interleave_depth = 0xff;

const int len = smbios_full_table_len(&t->header, t->eos);
*current += len;
*handle += 1;
return len;
}

static int smbios_write_type20(unsigned long *current, int *handle,
int type17_handle, int type19_handle)
{
u32 start_addr = 0;
int totallen = 0;
int i;

struct memory_info *meminfo;
meminfo = cbmem_find(CBMEM_ID_MEMINFO);
if (meminfo == NULL)
return 0; /* can't find mem info in cbmem */

printk(BIOS_INFO, "Create SMBIOS type 20\n");
for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
struct dimm_info *dimm;
dimm = &meminfo->dimm[i];
u32 end_addr = start_addr + (dimm->dimm_size << 10) - 1;
totallen += smbios_write_type20_table(current, handle, start_addr, end_addr,
type17_handle, type19_handle);
start_addr = end_addr + 1;
}
return totallen;
}

static int smbios_write_type32(unsigned long *current, int handle)
{
struct smbios_type32 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_BOOT_INFORMATION,
Expand Down Expand Up @@ -1281,8 +1326,12 @@ unsigned long smbios_write_tables(unsigned long current)

const int type16 = handle;
update_max(len, max_struct_size, smbios_write_type16(&current, &handle));
const int type17 = handle;
update_max(len, max_struct_size, smbios_write_type17(&current, &handle, type16));
const int type19 = handle;
update_max(len, max_struct_size, smbios_write_type19(&current, &handle, type16));
update_max(len, max_struct_size,
smbios_write_type20(&current, &handle, type17, type19));
update_max(len, max_struct_size, smbios_write_type32(&current, handle++));

update_max(len, max_struct_size, smbios_walk_device_tree(all_devices,
Expand Down
5 changes: 5 additions & 0 deletions src/arch/x86/smbios_defaults.c
Expand Up @@ -27,6 +27,11 @@ __weak void smbios_fill_dimm_asset_tag(const struct dimm_info *dimm, struct smbi
t->asset_tag = smbios_add_string(t->eos, buf);
}

__weak smbios_wakeup_type smbios_system_wakeup_type(void)
{
return SMBIOS_WAKEUP_TYPE_RESERVED;
}

__weak const char *smbios_mainboard_bios_version(void)
{
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion src/arch/x86/tables.c
Expand Up @@ -143,7 +143,7 @@ static unsigned long write_smbios_table(unsigned long rom_table_end)
{
unsigned long high_table_pointer;

#define MAX_SMBIOS_SIZE 2048
#define MAX_SMBIOS_SIZE (4 * KiB)

high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_SMBIOS,
MAX_SMBIOS_SIZE);
Expand Down
2 changes: 1 addition & 1 deletion src/commonlib/bsd/include/commonlib/bsd/compiler.h
Expand Up @@ -36,7 +36,7 @@
#endif

/* This evaluates to the type of the first expression, unless that is constant
in which case it evalutates to the type of the second. This is useful when
in which case it evaluates to the type of the second. This is useful when
assigning macro parameters to temporary variables, because that would
normally circumvent the special loosened type promotion rules for integer
literals. By using this macro, the promotion can happen at the time the
Expand Down
4 changes: 2 additions & 2 deletions src/commonlib/include/commonlib/iobuf.h
Expand Up @@ -81,7 +81,7 @@ int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b,
/* Out-of-band drain of ibuf by returning pointer to data of specified size. */
const void *ibuf_oob_drain(struct ibuf *ib, size_t sz);

/* Read arbitray data from input buffer. */
/* Read arbitrary data from input buffer. */
int ibuf_read(struct ibuf *ib, void *data, size_t sz);

/* Read big endian fixed size values. */
Expand Down Expand Up @@ -125,7 +125,7 @@ int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b,
/* Fill the buffer out-of-band. The size is accounted for. */
void *obuf_oob_fill(struct obuf *ob, size_t sz);

/* Write arbitray data to output buffer. */
/* Write arbitrary data to output buffer. */
int obuf_write(struct obuf *ob, const void *data, size_t sz);

/* Write big endian fixed size values. */
Expand Down
2 changes: 1 addition & 1 deletion src/console/Kconfig
Expand Up @@ -193,7 +193,7 @@ config CONSOLE_NE2K
help
Send coreboot debug output to a Ethernet console, it works
same way as Linux netconsole, packets are received to UDP
port 6666 on IP/MAC specified with options bellow.
port 6666 on IP/MAC specified with options below.
Use following netcat command: nc -u -l -p 6666

config CONSOLE_NE2K_DST_MAC
Expand Down
4 changes: 0 additions & 4 deletions src/cpu/amd/agesa/family14/Makefile.inc
Expand Up @@ -7,7 +7,3 @@ ramstage-y += chip_name.c
ramstage-y += model_14_init.c

subdirs-y += ../../mtrr
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
subdirs-y += ../../../x86/mtrr
subdirs-y += ../../../x86/pae
2 changes: 1 addition & 1 deletion src/cpu/amd/agesa/family14/model_14_init.c
Expand Up @@ -54,7 +54,7 @@ static void model_14_init(struct device *dev)
restore_mtrr();

x86_mtrr_check();
x86_enable_cache();
enable_cache();

/* zero the machine check error status registers */
mca_clear_status();
Expand Down
4 changes: 0 additions & 4 deletions src/cpu/amd/agesa/family15tn/Makefile.inc
Expand Up @@ -10,7 +10,3 @@ smm-y += udelay.c

subdirs-y += ../../mtrr
subdirs-y += ../../smm
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
subdirs-y += ../../../x86/mtrr
subdirs-y += ../../../x86/pae
4 changes: 2 additions & 2 deletions src/cpu/amd/agesa/family15tn/model_15_init.c
Expand Up @@ -25,7 +25,7 @@ static void model_15_init(struct device *dev)
u32 siblings;
#endif

//x86_enable_cache();
//enable_cache();
//amd_setup_mtrrs();
//x86_mtrr_check();
disable_cache();
Expand Down Expand Up @@ -53,7 +53,7 @@ static void model_15_init(struct device *dev)
restore_mtrr();

x86_mtrr_check();
x86_enable_cache();
enable_cache();

/* zero the machine check error status registers */
mca_clear_status();
Expand Down
4 changes: 0 additions & 4 deletions src/cpu/amd/agesa/family16kb/Makefile.inc
Expand Up @@ -7,7 +7,3 @@ ramstage-y += chip_name.c
ramstage-y += model_16_init.c

subdirs-y += ../../mtrr
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
subdirs-y += ../../../x86/mtrr
subdirs-y += ../../../x86/pae
4 changes: 2 additions & 2 deletions src/cpu/amd/agesa/family16kb/model_16_init.c
Expand Up @@ -23,7 +23,7 @@ static void model_16_init(struct device *dev)
u32 siblings;
#endif

//x86_enable_cache();
//enable_cache();
//amd_setup_mtrrs();
//x86_mtrr_check();
disable_cache();
Expand Down Expand Up @@ -51,7 +51,7 @@ static void model_16_init(struct device *dev)
restore_mtrr();

x86_mtrr_check();
x86_enable_cache();
enable_cache();

/* zero the machine check error status registers */
mca_clear_status();
Expand Down
4 changes: 0 additions & 4 deletions src/cpu/amd/pi/00730F01/Makefile.inc
Expand Up @@ -8,7 +8,3 @@ ramstage-y += model_16_init.c
ramstage-y += update_microcode.c

subdirs-y += ../../mtrr
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
subdirs-y += ../../../x86/mtrr
subdirs-y += ../../../x86/pae
1 change: 1 addition & 0 deletions src/cpu/intel/common/common.h
Expand Up @@ -4,6 +4,7 @@
#define _CPU_INTEL_COMMON_H

#include <types.h>
#include <acpi/acpigen.h>

void set_vmx_and_lock(void);
void set_feature_ctrl_vmx(void);
Expand Down
199 changes: 26 additions & 173 deletions src/cpu/intel/common/common_init.c
Expand Up @@ -103,184 +103,37 @@ void set_feature_ctrl_lock(void)
*/
void cpu_init_cppc_config(struct cppc_config *config, u32 version)
{
acpi_addr_t msr = {
.space_id = ACPI_ADDRESS_SPACE_FIXED,
.bit_width = 8,
.bit_offset = 0,
.access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS,
.addrl = 0,
.addrh = 0,
};
static const acpi_addr_t unsupported = {
.space_id = ACPI_ADDRESS_SPACE_MEMORY,
.bit_width = 0,
.bit_offset = 0,
.access_size = ACPI_ACCESS_SIZE_UNDEFINED,
.addrl = 0,
.addrh = 0,
};

config->version = version;

msr.addrl = IA32_HWP_CAPABILITIES;

/*
* Highest Performance:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x771, 0x04,)},
*/
config->regs[CPPC_HIGHEST_PERF] = msr;

/*
* Lowest Nonlinear Performance -> Most Efficient Performance:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x771, 0x04,)},
*/
msr.bit_offset = 16;
config->regs[CPPC_LOWEST_NONL_PERF] = msr;

/*
* Lowest Performance:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x18, 0x771, 0x04,)},
*/
msr.bit_offset = 24;
config->regs[CPPC_LOWEST_PERF] = msr;

/*
* Guaranteed Performance Register:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x771, 0x04,)},
*/
msr.bit_offset = 8;
config->regs[CPPC_GUARANTEED_PERF] = msr;

msr.addrl = MSR_PLATFORM_INFO;

/*
* Nominal Performance -> Maximum Non-Turbo Ratio:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0xce, 0x04,)},
*/
msr.bit_offset = 8;
config->regs[CPPC_NOMINAL_PERF] = msr;

msr.addrl = IA32_HWP_REQUEST;

/*
* Desired Performance Register:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x774, 0x04,)},
*/
msr.bit_offset = 16;
config->regs[CPPC_DESIRED_PERF] = msr;

/*
* Minimum Performance Register:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x774, 0x04,)},
*/
msr.bit_offset = 0;
config->regs[CPPC_MIN_PERF] = msr;

/*
* Maximum Performance Register:
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x774, 0x04,)},
*/
msr.bit_offset = 8;
config->regs[CPPC_MAX_PERF] = msr;

/*
* Performance Reduction Tolerance Register:
* ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)},
*/
config->regs[CPPC_PERF_REDUCE_TOLERANCE] = unsupported;

/*
* Time Window Register:
* ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)},
*/
config->regs[CPPC_TIME_WINDOW] = unsupported;

/*
* Counter Wraparound Time:
* ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)},
*/
config->regs[CPPC_COUNTER_WRAP] = unsupported;

msr.addrl = IA32_MPERF;

/*
* Reference Performance Counter Register:
* ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E7, 0x04,)},
*/
msr.bit_width = 64;
msr.bit_offset = 0;
config->regs[CPPC_REF_PERF_COUNTER] = msr;

msr.addrl = IA32_APERF;

/*
* Delivered Performance Counter Register:
* ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E8, 0x04,)},
*/
config->regs[CPPC_DELIVERED_PERF_COUNTER] = msr;

msr.addrl = IA32_HWP_STATUS;

/*
* Performance Limited Register:
* ResourceTemplate(){Register(FFixedHW, 0x01, 0x02, 0x777, 0x04,)},
*/
msr.bit_width = 1;
msr.bit_offset = 2;
config->regs[CPPC_PERF_LIMITED] = msr;

msr.addrl = IA32_PM_ENABLE;

/*
* CPPC Enable Register:
* ResourceTemplate(){Register(FFixedHW, 0x01, 0x00, 0x770, 0x04,)},
*/
msr.bit_offset = 0;
config->regs[CPPC_ENABLE] = msr;

if (version >= 2) {
/* Autonomous Selection Enable is populated below */

msr.addrl = IA32_HWP_REQUEST;
config->entries[CPPC_HIGHEST_PERF] = CPPC_REG_MSR(IA32_HWP_CAPABILITIES, 0, 8);
config->entries[CPPC_NOMINAL_PERF] = CPPC_REG_MSR(MSR_PLATFORM_INFO, 8, 8);
config->entries[CPPC_LOWEST_NONL_PERF] = CPPC_REG_MSR(IA32_HWP_CAPABILITIES, 16, 8);
config->entries[CPPC_LOWEST_PERF] = CPPC_REG_MSR(IA32_HWP_CAPABILITIES, 24, 8);
config->entries[CPPC_GUARANTEED_PERF] = CPPC_REG_MSR(IA32_HWP_CAPABILITIES, 8, 8);
config->entries[CPPC_DESIRED_PERF] = CPPC_REG_MSR(IA32_HWP_REQUEST, 16, 8);
config->entries[CPPC_MIN_PERF] = CPPC_REG_MSR(IA32_HWP_REQUEST, 0, 8);
config->entries[CPPC_MAX_PERF] = CPPC_REG_MSR(IA32_HWP_REQUEST, 8, 8);
config->entries[CPPC_PERF_REDUCE_TOLERANCE] = CPPC_UNSUPPORTED;
config->entries[CPPC_TIME_WINDOW] = CPPC_UNSUPPORTED;
config->entries[CPPC_COUNTER_WRAP] = CPPC_UNSUPPORTED;
config->entries[CPPC_REF_PERF_COUNTER] = CPPC_REG_MSR(IA32_MPERF, 0, 64);
config->entries[CPPC_DELIVERED_PERF_COUNTER] = CPPC_REG_MSR(IA32_APERF, 0, 64);
config->entries[CPPC_PERF_LIMITED] = CPPC_REG_MSR(IA32_HWP_STATUS, 2, 1);
config->entries[CPPC_ENABLE] = CPPC_REG_MSR(IA32_PM_ENABLE, 0, 1);

if (version < 2)
return;

/*
* Autonomous Activity Window Register
* ResourceTemplate(){Register(FFixedHW, 0x0a, 0x20, 0x774, 0x04,)},
*/
msr.bit_width = 10;
msr.bit_offset = 32;
config->regs[CPPC_AUTO_ACTIVITY_WINDOW] = msr;
config->entries[CPPC_AUTO_SELECT] = CPPC_DWORD(1);
config->entries[CPPC_AUTO_ACTIVITY_WINDOW] = CPPC_REG_MSR(IA32_HWP_REQUEST, 32, 10);
config->entries[CPPC_PERF_PREF] = CPPC_REG_MSR(IA32_HWP_REQUEST, 24, 8);
config->entries[CPPC_REF_PERF] = CPPC_UNSUPPORTED;

/*
* Autonomous Energy Performance Preference Register
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x18, 0x774, 0x04,)},
*/
msr.bit_width = 8;
msr.bit_offset = 24;
config->regs[CPPC_PERF_PREF] = msr;

/* Reference Performance */
config->regs[CPPC_REF_PERF] = unsupported;

if (version >= 3) {
/* Lowest Frequency */
config->regs[CPPC_LOWEST_FREQ] = unsupported;
/* Nominal Frequency */
config->regs[CPPC_NOMINAL_FREQ] = unsupported;
}
if (version < 3)
return;

/*
* Autonomous Selection Enable = 1
* This field is actually the first addition in version 2 but
* it's so unlike the others I'm populating it last.
*/
msr.space_id = ACPI_ADDRESS_SPACE_MEMORY;
msr.bit_width = 32;
msr.bit_offset = 0;
msr.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
msr.addrl = 1;
config->regs[CPPC_AUTO_SELECT] = msr;
}
config->entries[CPPC_LOWEST_FREQ] = CPPC_UNSUPPORTED;
config->entries[CPPC_NOMINAL_FREQ] = CPPC_UNSUPPORTED;
}

void set_aesni_lock(void)
Expand Down
30 changes: 17 additions & 13 deletions src/cpu/intel/common/hyperthreading.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/x86/lapic.h>
#include <cpu/intel/common/common.h>
#include <arch/cpu.h>
#include <types.h>
Expand All @@ -18,31 +17,36 @@ bool intel_ht_supported(void)
bool intel_ht_sibling(void)
{
struct cpuid_result result;
unsigned int core_ids, apic_ids, threads;
unsigned int core_ids, apic_ids;
unsigned int max_leaf;
uint32_t initial_lapicid, threads;

if (!intel_ht_supported())
return false;

if (is_x2apic_mode()) {
if (cpuid_eax(0) >= 0xb) {
result = cpuid_ext(0xb, 0);
const uint32_t div = 1 << (result.eax & 0x1f);
return result.edx % div > 0;
}
max_leaf = cpuid_get_max_func();

/* Detect from 32-bit X2APIC ID. */
if (max_leaf >= 0xb) {
result = cpuid_ext(0xb, 0);
threads = 1 << (result.eax & 0x1f);
initial_lapicid = result.edx;
return initial_lapicid % threads > 0;
}

apic_ids = 1;
if (cpuid_eax(0) >= 1)
apic_ids = (cpuid_ebx(1) >> 16) & 0xff;
/* Detect from 8-bit XAPIC ID. */
result = cpuid_ext(0x1, 0);
initial_lapicid = result.ebx >> 24;
apic_ids = (result.ebx >> 16) & 0xff;
if (apic_ids == 0)
apic_ids = 1;

core_ids = 1;
if (cpuid_eax(0) >= 4) {
if (max_leaf >= 4) {
result = cpuid_ext(4, 0);
core_ids += (result.eax >> 26) & 0x3f;
}

threads = (apic_ids / core_ids);
return !!(lapicid() & (threads - 1));
return initial_lapicid % threads > 0;
}
1 change: 0 additions & 1 deletion src/cpu/intel/haswell/Kconfig
Expand Up @@ -19,7 +19,6 @@ config CPU_SPECIFIC_OPTIONS
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_TIMEBASE
select HAVE_ASAN_IN_ROMSTAGE
select HAVE_DISPLAY_MTRRS
select CPU_INTEL_COMMON_VOLTAGE

config SMM_TSEG_SIZE
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/haswell/Makefile.inc
Expand Up @@ -15,9 +15,6 @@ bootblock-y += bootblock.c

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

subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../turbo

Expand Down
6 changes: 4 additions & 2 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -17,6 +17,7 @@
#include <northbridge/intel/haswell/haswell.h>
#include <southbridge/intel/lynxpoint/pch.h>
#include <cpu/intel/common/common.h>
#include <types.h>
#include "haswell.h"
#include "chip.h"

Expand Down Expand Up @@ -395,6 +396,7 @@ static void configure_c_states(void)
msr.lo |= (1 << 27); // C3 Auto Undemotion Enable
msr.lo |= (1 << 26); // C1 Auto Demotion Enable
msr.lo |= (1 << 25); // C3 Auto Demotion Enable
msr.lo |= (1 << 15); // Lock bits 15:0
msr.lo &= ~(1 << 10); // Disable IO MWAIT redirection

if (timed_mwait_capable)
Expand Down Expand Up @@ -640,8 +642,8 @@ static const struct mp_ops mp_ops = {

void mp_init_cpus(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
/* TODO: Handle mp_init_with_smm failure? */
mp_init_with_smm(cpu_bus, &mp_ops);
}

static struct device_operations cpu_dev_ops = {
Expand Down
5 changes: 3 additions & 2 deletions src/cpu/intel/model_1067x/mp_init.c
Expand Up @@ -7,6 +7,7 @@
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/common/common.h>
#include <device/device.h>
#include <types.h>

/* Parallel MP initialization support. */
static void pre_mp_init(void)
Expand Down Expand Up @@ -97,6 +98,6 @@ static const struct mp_ops mp_ops = {

void mp_init_cpus(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
/* TODO: Handle mp_init_with_smm failure? */
mp_init_with_smm(cpu_bus, &mp_ops);
}
3 changes: 0 additions & 3 deletions src/cpu/intel/model_2065x/Makefile.inc
@@ -1,8 +1,5 @@
ramstage-y += model_2065x_init.c
subdirs-y += ../../x86/name
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../intel/turbo
subdirs-y += ../../intel/microcode
subdirs-y += ../smm/gen1
Expand Down
5 changes: 3 additions & 2 deletions src/cpu/intel/model_2065x/model_2065x_init.c
Expand Up @@ -19,6 +19,7 @@
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/common/common.h>
#include <smp/node.h>
#include <types.h>

static void configure_thermal_target(void)
{
Expand Down Expand Up @@ -174,8 +175,8 @@ static const struct mp_ops mp_ops = {

void mp_init_cpus(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
/* TODO: Handle mp_init_with_smm failure? */
mp_init_with_smm(cpu_bus, &mp_ops);
}

static struct device_operations cpu_dev_ops = {
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/model_206ax/Makefile.inc
Expand Up @@ -2,9 +2,6 @@ ramstage-y += model_206ax_init.c
subdirs-y += ../../x86/name
subdirs-y += ../smm/gen1

subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../turbo

Expand Down
5 changes: 3 additions & 2 deletions src/cpu/intel/model_206ax/model_206ax_init.c
Expand Up @@ -19,6 +19,7 @@
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/common/common.h>
#include <smbios.h>
#include <types.h>

/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
static const u8 power_limit_time_sec_to_msr[] = {
Expand Down Expand Up @@ -430,8 +431,8 @@ static const struct mp_ops mp_ops = {

void mp_init_cpus(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
/* TODO: Handle mp_init_with_smm failure? */
mp_init_with_smm(cpu_bus, &mp_ops);
}

static struct device_operations cpu_dev_ops = {
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_65x/model_65x_init.c
Expand Up @@ -16,7 +16,7 @@ static void model_65x_init(struct device *dev)
p6_configure_l2_cache();

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

Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_67x/model_67x_init.c
Expand Up @@ -17,7 +17,7 @@ static void model_67x_init(struct device *cpu)
p6_configure_l2_cache();

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

/* Setup MTRRs */
x86_setup_mtrrs();
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_68x/model_68x_init.c
Expand Up @@ -14,7 +14,7 @@ static void model_68x_init(struct device *cpu)
char processor_name[49];

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

/* Update the microcode */
intel_update_microcode_from_cbfs();
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_6bx/model_6bx_init.c
Expand Up @@ -14,7 +14,7 @@ static void model_6bx_init(struct device *cpu)
char processor_name[49];

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

/* Update the microcode */
intel_update_microcode_from_cbfs();
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_6ex/model_6ex_init.c
Expand Up @@ -97,7 +97,7 @@ static void model_6ex_init(struct device *cpu)
char processor_name[49];

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

/* Print processor name */
fill_processor_name(processor_name);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_6fx/model_6fx_init.c
Expand Up @@ -111,7 +111,7 @@ static void model_6fx_init(struct device *cpu)
char processor_name[49];

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

/* Print processor name */
fill_processor_name(processor_name);
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_6xx/model_6xx_init.c
Expand Up @@ -10,7 +10,7 @@
static void model_6xx_init(struct device *dev)
{
/* Turn on caching if we haven't already */
x86_enable_cache();
enable_cache();
x86_setup_mtrrs();
x86_mtrr_check();

Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_f2x/model_f2x_init.c
Expand Up @@ -12,7 +12,7 @@
static void model_f2x_init(struct device *cpu)
{
/* Turn on caching if we haven't already */
x86_enable_cache();
enable_cache();

if (!intel_ht_sibling()) {
/* MTRRs are shared between threads */
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_f3x/model_f3x_init.c
Expand Up @@ -12,7 +12,7 @@
static void model_f3x_init(struct device *cpu)
{
/* Turn on caching if we haven't already */
x86_enable_cache();
enable_cache();

if (!CONFIG(PARALLEL_MP) && !intel_ht_sibling()) {
/* MTRRs are shared between threads */
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/model_f4x/model_f4x_init.c
Expand Up @@ -8,7 +8,7 @@
static void model_f4x_init(struct device *cpu)
{
/* Turn on caching if we haven't already */
x86_enable_cache();
enable_cache();

/* Enable the local CPU APICs */
setup_lapic();
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/slot_1/Makefile.inc
Expand Up @@ -7,9 +7,6 @@ subdirs-y += ../model_65x
subdirs-y += ../model_67x
subdirs-y += ../model_68x
subdirs-y += ../model_6bx
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode

bootblock-y += ../car/p3/cache_as_ram.S
Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/socket_441/Makefile.inc
@@ -1,7 +1,4 @@
subdirs-y += ../model_106cx
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/socket_BGA956/Makefile.inc
@@ -1,7 +1,4 @@
subdirs-y += ../model_1067x
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
3 changes: 0 additions & 3 deletions src/cpu/intel/socket_FCBGA559/Makefile.inc
@@ -1,7 +1,4 @@
subdirs-y += ../model_106cx
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
2 changes: 0 additions & 2 deletions src/cpu/intel/socket_LGA775/Kconfig
Expand Up @@ -8,8 +8,6 @@ config SOCKET_SPECIFIC_OPTIONS
select CPU_INTEL_MODEL_6FX
select CPU_INTEL_MODEL_F3X
select CPU_INTEL_MODEL_F4X
# select CPU_INTEL_MODEL_F6X
# select CPU_INTEL_MODEL_1066X
select CPU_INTEL_MODEL_1067X
select MMX
select SSE
Expand Down
5 changes: 0 additions & 5 deletions src/cpu/intel/socket_LGA775/Makefile.inc
@@ -1,12 +1,7 @@
subdirs-y += ../model_6fx
subdirs-y += ../model_f3x
subdirs-y += ../model_f4x
#subdirs-y += ../model_f6x
#subdirs-y += ../model_1066x
subdirs-y += ../model_1067x
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
2 changes: 0 additions & 2 deletions src/cpu/intel/socket_m/Makefile.inc
@@ -1,8 +1,6 @@
subdirs-y += ../model_6ex
subdirs-y += ../model_6fx
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
2 changes: 0 additions & 2 deletions src/cpu/intel/socket_mPGA604/Makefile.inc
@@ -1,7 +1,5 @@
subdirs-y += ../model_f2x
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode

bootblock-y += ../car/p4-netburst/cache_as_ram.S
Expand Down
2 changes: 0 additions & 2 deletions src/cpu/intel/socket_p/Makefile.inc
@@ -1,8 +1,6 @@
subdirs-y += ../model_6fx
subdirs-y += ../model_1067x
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../microcode
subdirs-y += ../speedstep

Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/speedstep/acpi.c
Expand Up @@ -88,7 +88,7 @@ void generate_cpu_entries(const struct device *device)
CPUs share the same
layout. */
int num_cstates;
acpi_cstate_t *cstates;
const acpi_cstate_t *cstates;
sst_table_t pstates;
uint8_t coordination;

Expand Down
3 changes: 0 additions & 3 deletions src/cpu/qemu-x86/Makefile.inc
Expand Up @@ -6,6 +6,3 @@ bootblock-y += bootblock.c
romstage-y += ../intel/car/romstage.c

ramstage-y += qemu.c

subdirs-y += ../x86/mtrr
subdirs-y += ../x86/lapic
4 changes: 2 additions & 2 deletions src/cpu/x86/64bit/exit32.inc
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */

/*
* For droping from long mode to protected mode.
* For dropping from long mode to protected mode.
*
* For reference see "AMD64 ArchitectureProgrammer's Manual Volume 2",
* Document 24593-Rev. 3.31-July 2019 Chapter 5.3
Expand Down Expand Up @@ -47,7 +47,7 @@ SetCodeSelector32:

# use iret to jump to a 32-bit offset in a new code segment
# iret will pop cs:rip, flags, then ss:rsp
mov %ss, %ax # need to push ss, but push ss instuction
mov %ss, %ax # need to push ss, but push ss instruction
push %rax # not valid in x64 mode, so use ax
push %rdx # the rsp to load
pushfq # push rflags
Expand Down
9 changes: 9 additions & 0 deletions src/cpu/x86/Kconfig
Expand Up @@ -2,6 +2,7 @@ config PARALLEL_MP
def_bool y
depends on !LEGACY_SMP_INIT
depends on SMP
select CPU_INFO_V2
help
This option uses common MP infrastructure for bringing up APs
in parallel. It additionally provides a more flexible mechanism
Expand Down Expand Up @@ -193,3 +194,11 @@ config RESERVE_MTRRS_FOR_OS
the system BIOS and the last 2 are to be reserved for OS usage.
However, modern OSes use PAT to control cacheability instead of
using MTRRs.

config CPU_INFO_V2
bool
depends on PARALLEL_MP
help
Enables the new method of locating struct cpu_info. This new method
uses the %gs segment to locate the cpu_info pointer. The old method
relied on the stack being CONFIG_STACK_SIZE aligned.
4 changes: 0 additions & 4 deletions src/cpu/x86/Kconfig.debug_cpu
Expand Up @@ -5,12 +5,8 @@ config DEBUG_CAR
bool "Output verbose Cache-as-RAM debug messages"
depends on HAVE_DEBUG_CAR

config HAVE_DISPLAY_MTRRS
bool

config DISPLAY_MTRRS
bool "Display intermediate MTRR settings"
depends on HAVE_DISPLAY_MTRRS

config DEBUG_SMM_RELOCATION
bool "Debug SMM relocation code"
Expand Down
2 changes: 2 additions & 0 deletions src/cpu/x86/Makefile.inc
@@ -1,3 +1,5 @@
subdirs-y += lapic
subdirs-y += mtrr
subdirs-y += pae
subdirs-$(CONFIG_HAVE_SMI_HANDLER) += smm
subdirs-$(CONFIG_UDELAY_TSC) += tsc
Expand Down
1 change: 0 additions & 1 deletion src/cpu/x86/cache/Makefile.inc

This file was deleted.

11 changes: 0 additions & 11 deletions src/cpu/x86/cache/cache.c

This file was deleted.

72 changes: 67 additions & 5 deletions src/cpu/x86/cpu_info.S.inc
@@ -1,10 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

/*
* Pushes a 32-bit register onto the stack.
*
* There are two possible code sections where this code can be included:
* .code32 and .code64
*
* Doing a `push %eax` while in a .code64 section will result in a compiler
* error. This macro manually pushes the 32-bit register onto the stack so we
* can share the code between 32 and 64 bit builds.
*/
.macro pushr reg:req
#if ENV_X86_64
movl $0, -4(%esp)
movl \reg, -8(%esp)
sub $8, %esp
#else
push \reg
#endif
.endm

/* Push struct cpu_info */
.macro push_cpu_info index=$0
#if CONFIG(COOP_MULTITASKING)
push $0 /* *thread */
#endif
push \index /* index */
push $0 /* *cpu */
pushr \index /* index (size_t) */
pushr $0 /* *cpu */
.endm

/* Push struct per_cpu_segment_data */
.macro push_per_cpu_segment_data cpu_info_pointer=%esp
pushr \cpu_info_pointer /* *cpu_info */
.endm

/*
* Sets the base address in the segment descriptor array.
*
* A segment descriptor has the following structure:
* struct {
* uint16_t segment_limit_0_15;
* uint16_t base_address_0_15;
* uint8_t base_address_16_23;
* uint8_t attrs[2];
* uint8_t base_address_24_31;
* };
*
* @desc_array: Address of the descriptor table
* @base: Address to set in the descriptor
* @desc_index: Index of the descriptor in the table. Defaults to 0. Must be a
* register if specified.
*
* Clobbers %eax, %ebx.
*/
.macro set_segment_descriptor_base desc_array:req, base:req, desc_index
mov \base, %eax

mov \desc_array, %ebx

.ifb \desc_index
movw %ax, 2(%ebx)
shr $16, %eax
movb %al, 4(%ebx)
shr $8, %eax
movb %al, 7(%ebx)
.else
movw %ax, 2(%ebx, \desc_index, 8)
shr $16, %eax
movb %al, 4(%ebx, \desc_index, 8)
shr $8, %eax
movb %al, 7(%ebx, \desc_index, 8)
.endif

.endm
47 changes: 22 additions & 25 deletions src/cpu/x86/lapic/lapic.c
Expand Up @@ -5,17 +5,21 @@
#include <cpu/x86/lapic_def.h>
#include <cpu/x86/msr.h>
#include <console/console.h>
#include <smp/node.h>
#include <stdint.h>

void enable_lapic(void)
{
msr_t msr;

msr = rdmsr(LAPIC_BASE_MSR);
msr.hi &= 0xffffff00;
msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
msr.lo |= LAPIC_DEFAULT_BASE;
msr.lo |= LAPIC_BASE_MSR_ENABLE;
wrmsr(LAPIC_BASE_MSR, msr);

printk(BIOS_INFO, "Setting up local APIC 0x%x\n", lapicid());
}

void disable_lapic(void)
Expand All @@ -39,45 +43,38 @@ static int need_lapic_init(void)

static void lapic_virtual_wire_mode_init(void)
{
/* this is so interrupts work. This is very limited scope --
* linux will do better later, we hope ...
*/
/* this is the first way we learned to do it. It fails on real SMP
* stuff. So we have to do things differently ...
* see the Intel mp1.4 spec, page A-3
*/

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

/* Enable the local APIC */
enable_lapic();

/*
* Set Task Priority to 'accept all'.
*/
lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0);

/* Put the local APIC in virtual wire mode */
/* Set spurious interrupt vector to 0 and keep LAPIC enabled to
be able to clear LVT register mask bits. */
lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE);

uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_LVT_REMOTE_IRR |
LAPIC_INPUT_POLARITY | LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
/* Put the local APIC in virtual wire mode */
uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_INPUT_POLARITY |
LAPIC_DELIVERY_MODE_MASK;

lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT);

lapic_update32(LAPIC_LVT1, ~mask, LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI);
if (boot_cpu())
lapic_update32(LAPIC_LVT0, ~mask, LAPIC_DELIVERY_MODE_EXTINT);
else
lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_MASKED |
LAPIC_DELIVERY_MODE_EXTINT);

printk(BIOS_DEBUG, " apic_id: 0x%x ", lapicid());
printk(BIOS_INFO, "done.\n");
lapic_update32(LAPIC_LVT1, ~mask, LAPIC_DELIVERY_MODE_NMI);
}

void setup_lapic(void)
{
/* Enable the local APIC */
if (need_lapic_init())
lapic_virtual_wire_mode_init();
else
enable_lapic();
else if (!CONFIG(UDELAY_LAPIC))
disable_lapic();

/* This programming is for PIC mode i8259 interrupts to be delivered to CPU
while LAPIC is enabled. */
if (need_lapic_init())
lapic_virtual_wire_mode_init();
}
3 changes: 1 addition & 2 deletions src/cpu/x86/lapic/lapic_cpu_init.c
Expand Up @@ -128,7 +128,7 @@ static int lapic_start_cpu(unsigned long apicid)
printk(BIOS_ERR, "ESR is 0x%x\n", lapic_read(LAPIC_ESR));
if (lapic_read(LAPIC_ESR)) {
printk(BIOS_ERR, "Try to reset ESR\n");
xapic_write_atomic(LAPIC_ESR, 0);
lapic_write(LAPIC_ESR, 0);
printk(BIOS_ERR, "ESR is 0x%x\n",
lapic_read(LAPIC_ESR));
}
Expand Down Expand Up @@ -253,7 +253,6 @@ static int start_cpu(struct device *cpu)
info->index = index;
info->cpu = cpu;
cpu_add_map_entry(info->index);
thread_init_cpu_info_non_bsp(info);

/* Advertise the new stack and index to start_cpu */
secondary_stack = stack_top;
Expand Down