From 363483ed54ee2936c665ad87fec24e254b31ac3f Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 7 Oct 2026 14:21:43 -0700 Subject: [PATCH] nai_68int6: add wolfBoot target for the NAI 68INT6 (Intel Tiger Lake UP3) OpenVPX SBC --- arch.mk | 13 +- config/examples/nai_68int6.config | 96 ++ docs/Targets.md | 69 ++ hal/kontron_vx3060_s2.c | 81 -- ...ontron_vx3060_s2_loader.c => nai_68int6.c} | 49 +- hal/{x86_fsp_qemu_loader.c => stub_loader.c} | 27 +- hal/x86_fsp_tgl.c | 87 +- include/x86/fsp_config.h | 44 + include/x86/gpio_config.h | 1097 +++++++++++++++++ include/x86/mptable.h | 2 +- include/x86/tgl_fsp.h | 1 + options.mk | 9 + src/boot_x86_fsp_payload.c | 9 + src/pci.c | 14 +- src/tpm.c | 5 +- src/update_disk.c | 5 + src/x86/mptable.c | 4 +- src/x86/tgl_fsp.c | 81 +- tools/scripts/x86_fsp/select_fsp.sh | 109 ++ tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh | 97 ++ tools/unit-tests/unit-kontron-tgl-spi.c | 4 +- 21 files changed, 1772 insertions(+), 131 deletions(-) create mode 100644 config/examples/nai_68int6.config rename hal/{kontron_vx3060_s2_loader.c => nai_68int6.c} (66%) rename hal/{x86_fsp_qemu_loader.c => stub_loader.c} (72%) create mode 100644 include/x86/fsp_config.h create mode 100644 include/x86/gpio_config.h create mode 100755 tools/scripts/x86_fsp/select_fsp.sh create mode 100755 tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh diff --git a/arch.mk b/arch.mk index 84eac55d..c31eab8f 100644 --- a/arch.mk +++ b/arch.mk @@ -2207,13 +2207,13 @@ ifeq ($(USE_GCC),1) endif OUTPUT_FLAG?=-o -ifeq ($(filter $(TARGET),x86_fsp_qemu kontron_vx3060_s2),$(TARGET)) +ifeq ($(filter $(TARGET),x86_fsp_qemu kontron_vx3060_s2 nai_68int6),$(TARGET)) FSP=1 CFLAGS+=-ffunction-sections -fdata-sections -ffreestanding -nostdlib -static # some std libc have headers that bring in extra symbols used in # FORTIFY_SOURCE realated checks. Use -U_FORTIFY_SOURCE to avoid that. CFLAGS+=-U_FORTIFY_SOURCE - ifeq ($(TARGET), kontron_vx3060_s2) + ifeq ($(filter $(TARGET),kontron_vx3060_s2 nai_68int6),$(TARGET)) FSP_TGL=1 CFLAGS+=-DWOLFBOOT_TGL=1 endif @@ -2263,13 +2263,13 @@ ifeq ("${FSP}", "1") OBJS += src/image.o OBJS += src/keystore.o OBJS += src/sig_wolfboot_raw.o - ifeq ($(TARGET), kontron_vx3060_s2) - OBJS += hal/kontron_vx3060_s2_loader.o - endif OBJS += $(WOLFCRYPT_OBJS) CFLAGS+=-DSTAGE1_AUTH endif + # Generic stage1 loader HAL (stubs); shared by all x86 FSP targets. + OBJS += hal/stub_loader.o + CFLAGS += -fno-stack-protector -m32 -fno-PIC -fno-pie -mno-mmx -mno-sse -DDEBUG_UART CFLAGS += -DFSP_M_BASE=$(FSP_M_BASE) ifeq ($(FSP_TGL), 1) @@ -2277,9 +2277,6 @@ ifeq ("${FSP}", "1") OBJS+=src/ucode0.o CFLAGS += -DUCODE0_ADDRESS=$(UCODE0_BASE) endif - ifeq ($(TARGET),x86_fsp_qemu) - OBJS += hal/x86_fsp_qemu_loader.o - endif else # building wolfBoot ifeq ($(FSP_TGL), 1) diff --git a/config/examples/nai_68int6.config b/config/examples/nai_68int6.config new file mode 100644 index 00000000..286f0301 --- /dev/null +++ b/config/examples/nai_68int6.config @@ -0,0 +1,96 @@ +# NAI 68INT6 3U OpenVPX SBC (Tiger Lake UP3); needs the board's own FSP +# (nai_extract_fsp.sh). See the NAI 68INT6 section of docs/Targets.md. + +ARCH=x86_64 +TARGET=nai_68int6 +WOLFBOOT_SMALL_STACK=0 + +# ECC P-384 signature, SHA-384 digest (measured boot uses SHA-256 on an +# SLB9670). See the integrity-algorithm table in docs/Targets.md. +SIGN=ECC384 +HASH=SHA384 + +DEBUG=1 +# FSP-M UPD dump on the console before FspMemInit (bring-up aid). +DUMP_FSP_UPD=0 +SPMATH=1 +ENCRYPTION=0 +WOLFBOOT_NO_PARTITIONS=1 +# Disk boot: signed kernels in GPT partitions 3/4, Ubuntu root in partition 2. +# The A/B boot-partition indices are set per target in src/update_disk.c. +WOLFBOOT_BOOT_DISK=0 +FORCE_32BIT=1 + +########## Flash layout (measured from the factory descriptor, 32 MB) ########## +WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff400000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0 +WOLFBOOT_LOAD_BASE=0x58000200 +WOLFBOOT_SECTOR_SIZE?=0x1000 +WOLFBOOT_DATA_ADDRESS=0x1000000 + +FSP_CONFIG_BASE=0xffe9f800 +FSP_T_BASE=0xfff59000 +FSP_M_BASE=0xfff60000 + +WOLFBOOT_ORIGIN=0xfff00000 +BOOTLOADER_PARTITION_SIZE=0x600000 +# Inert (the flash descriptor is used); kept for config parity. +BIOS_REGION_SIZE=0xc00000 + +UCODE0_BASE=0xffd90000 +UCODE0_BIN=src/x86/ucode0.bin + +FSP_T_BIN=./src/x86/fsp_t.bin +FSP_M_BIN=./src/x86/fsp_m.bin +FSP_S_BIN=./src/x86/fsp_s.bin +FSP_S_UPD_DATA_BIN=./src/x86/fsp_s_upd_data.bin +# Boot Guard is left to the board owner: supply an ACM and key here to build a +# Boot-Guard image. Unset, wolfBoot builds and boots without it. +ACM_BIN= +FSP_S_LOAD_BASE=0x0FED5F00 + +POLICY_BASE=0xffaa4000 +KEYSTORE_OFFSET=0x3FE00 +KEYSTORE_STAGE1_OFFSET=0x400 + +########## Console: LPSS UART2 (PCI 00:19.2), verified on hardware ########## +X86_UART_NUMBER=2 +X86_UART_BASE=0xFE032000 +X86_UART_REG_WIDTH=4 +X86_UART_MMIO=1 + +########## PCH / PCI ########## +PCH_PCR_BASE=0xFD000000 +PCI_ECAM_BASE=0xC0000000 +PCI_USE_ECAM=1 +PCH_HAS_PCR=1 +# Generate ACPI tables so Linux gets the interrupt model and PCI routing. +ACPI=1 + +########## Payload: signed 64-bit Linux bzImage ########## +64BIT=1 +ELF=1 +DEBUG_ELF=0 +MULTIBOOT2=1 +LINUX_PAYLOAD=1 + +########## Security ########## +STAGE1_AUTH=1 +WOLFTPM=1 +MEASURED_BOOT=1 +MEASURED_PCR_A=0 +# Measure the verified OS image into PCR4, alongside the firmware in PCR0. +MEASURED_PCR_OS=4 +WOLFBOOT_UNIVERSAL_KEYSTORE=1 +WOLFBOOT_SKIP_AUTH_CHECK=0 +ENABLE_DEBUG_CONSENT=0 + +# Deferred: TPM sealing and ATA disk lock/erase. +WOLFBOOT_TPM_SEAL=0 +DISK_LOCK=0 +DISK_ERASE=0 + +# Anti-rollback: persistent version floor + audit counters in TPM NV +# (trust-on-first-use; provision before first boot where that matters). +ANTI_ROLLBACK=1 diff --git a/docs/Targets.md b/docs/Targets.md index dd70453c..f0be2260 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -14,6 +14,7 @@ This README describes configuration of supported targets. * [Infineon AURIX TC4xx](#infineon-aurix-tc4xx) * [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support) * [Kontron VX3060-S2](#kontron-vx3060-s2) +* [NAI 68INT6 (Intel Tiger Lake)](#nai-68int6-intel-tiger-lake) * [Microchip PIC32CK](#microchip-pic32ck) * [Microchip PIC32CZ](#microchip-pic32cz) * [Microchip PolarFire SoC](#microchip-polarfire-soc) @@ -9609,6 +9610,74 @@ Attempting boot from partition A ``` At this point, the kernel image in partition "A" is verified and staged and you should be seeing the log messages of your OS booting. +## NAI 68INT6 (Intel Tiger Lake) + +wolfBoot target `nai_68int6` for the North Atlantic Industries 68INT6, a 3U OpenVPX SOSA-aligned single board computer (Intel Core i7-1185GRE, Tiger Lake UP3). It uses the Intel FSP support described [above](#intel-x86_64-with-intel-fsp-support) and shares the Tiger Lake path with the Kontron target. wolfBoot boots a signed 64-bit Linux from the SATA disk with A/B update, measured boot and TPM anti-rollback, verified on a Rev D5 bench board. The public Tiger Lake FSP does not train this board's memory, so the FSP is extracted from a 68INT6 BIOS image. + +| | | +|---|---| +| CPU | i7-1185GRE (`06-8C-01`), Tiger Lake UP3, PCH-LP | +| Memory | 2 x 32 GB DDR4-3200 SODIMM, non-ECC | +| BIOS flash | Rev C/D5: 2 x W25R256JV (32 MB), selected by JP36. Next revision: one 64 MB device | +| TPM | SLB9670 (SHA-1/256), or SLB9672, which adds a SHA-384 bank | +| Storage | Onboard SATA SSD, AHCI at `00:17.0` | +| Console | LPSS UART2, PCI `00:19.2`, RS-232; `X86_UART_NUMBER=2` | + +### Building + +``` +cp config/examples/nai_68int6.config .config +./tools/scripts/x86_fsp/tgl/tgl_download_fsp.sh # FSP UPD headers, first time only +./tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh <68INT6.bin> # board's own FSP blobs +./tools/scripts/x86_fsp/tgl/assemble_image.sh -k # generate signing keys +make +./tools/scripts/x86_fsp/tgl/assemble_image.sh -n <68INT6.bin> +``` + +`nai_extract_fsp.sh` takes FSP-T/M/S and the microcode from a 68INT6 BIOS image. Without it the build uses the public FSP, which compiles but does not train memory. The `-n` stitch replaces the top 6 MB (`BOOTLOADER_PARTITION_SIZE`) of the 12 MB BIOS region and keeps the descriptor and CSME byte for byte. The board has no recovery region (recovery is the second flash device), so use `-n`, not `-m`. The result is `final_image.bin`. + +### Integrity algorithms + +ECC P-384 and SHA-384 match what Intel Boot Guard uses for the Initial Boot Block. + +| Layer | Algorithm | +|---|---| +| Image signature | ECC P-384 (`SIGN=ECC384`) | +| Image digest | SHA-384 (`HASH=SHA384`) | +| Measured boot PCR | SHA-256 (the SLB9670 has only SHA-1 and SHA-256 banks) | + +`wolfBoot_image_measure()` re-hashes the authenticated digest with the PCR bank's algorithm, so one image serves either TPM. `MEASURED_PCR_ALG=SHA384` needs an SLB9672 with its SHA-384 bank allocated (`TPM2_PCR_Allocate` under platform auth, a provisioning step). + +### Configuration + +Notable options in [config/examples/nai_68int6.config](../config/examples/nai_68int6.config): + +| Option | Meaning | +|---|---| +| `X86_UART_NUMBER=2` | LPSS UART2 for all three FSP phases (Kontron uses 0) | +| `ACPI=1` | Required. Generates ACPI tables (RSDP/XSDT/FADT/MADT/MCFG and a minimal DSDT); the board's PCI interrupt routing is only in the DSDT `_PRT`, since the MP table is the Kontron one | +| `ANTI_ROLLBACK=1` | Persistent version floor and boot audit counters in TPM NV | +| `MEASURED_BOOT=1`, `MEASURED_PCR_OS=4` | Firmware into PCR 0, the verified OS image into PCR 4 | +| `WOLFBOOT_BOOT_DISK=0` | Boot from GPT partitions; the A/B indices (sda3/sda4) are set in `src/update_disk.c` | + +### BIOS region lock + +Before handoff, `hal_flash_protect()` in the shared Tiger Lake HAL (`hal/x86_fsp_tgl.c`, as on Kontron) sets SPI Flash Protected Range 0 over the BIOS region with read and write protection, then FLOCKDN. Both hold until the next platform reset, so the booted OS cannot read or reprogram the BIOS region; update it with an external programmer. + +### Anti-rollback + +`ANTI_ROLLBACK=1` keeps a version floor and boot audit counters in a TPM NV index; the backend is `src/boot_state_tpm.c` and the policy is `src/boot_state.c`. The floor is the highest version ever booted, set trust-on-first-use. A validly signed older image still boots and records a rollback event. Only an untrustworthy reference halts the boot; `ANTI_ROLLBACK_HALT_ON_FAILURE=1` also halts when the TPM is unreachable, a write fails or the platform hierarchy cannot be disabled. + +TPM NV is used instead of the partition state trailer because the floor must survive a full reimage of the disk or flash. `DISK_BOOT_CONFIRM` still handles per-slot confirmation, and the backend can move to a root-of-trust device later without changing the policy. + +`ALLOW_DOWNGRADE` is left unset, the secure default: if the higher-versioned slot fails to verify, wolfBoot halts (`Rollback to lower version not allowed`) rather than boot the lower one. Building with `ALLOW_DOWNGRADE=1` allows that fall-back and leaves the TPM floor as the only rollback guard. + +The booted OS cannot lower the floor. The index is platform-created and writable only under platform auth (`TPMA_NV_PPWRITE`), and on every boot wolfBoot disables the platform hierarchy (`TPM2_HierarchyControl`) until the next TPM reset, as in section 10 of the TCG PC Client Platform specification. The OS can then neither write nor undefine the index. An index with any other write attributes is treated as corrupt. Platform-auth provisioning, such as `TPM2_PCR_Allocate`, must be done before wolfBoot is installed. + +### Boot, programming and recovery + +wolfBoot boots the highest-versioned signed 64-bit `bzImage` that verifies from the two GPT boot partitions. It falls back to the other slot only if that is not a downgrade (see Anti-rollback), and halts if neither boots. Program the flash with a Dediprog SF100 on JP4 while the board is off; the BIOS region lock blocks `flashrom` from the booted OS. JP36 selects which bank boots and which one the programmer sees; move it only with the board off. + ## Infineon PSOC Control C3 The [PSOC Control C3](https://www.infineon.com/products/microcontroller/32-bit-psoc-arm-cortex/32-bit-psoc-control-arm-cortex-m33-mcu/psoc-control-c3-main-line) family (PSC3, CAT1B) is an Arm Cortex-M33 motor-control MCU. wolfBoot runs as the first application the BootROM launches, verifies the signed firmware in the BOOT partition and jumps to it. diff --git a/hal/kontron_vx3060_s2.c b/hal/kontron_vx3060_s2.c index fcdefab5..3812f65b 100644 --- a/hal/kontron_vx3060_s2.c +++ b/hal/kontron_vx3060_s2.c @@ -31,87 +31,6 @@ #ifdef __WOLFBOOT -#define SPI_PCI_DEV 31 -#define SPI_PCI_FUN 5 -#define SPI_BAR_OFF 0x10 -/* Tiger Lake SPI controller register offsets, memory-mapped at the - * BAR0 base. FREG1 holds the BIOS flash region base/limit (region 0 - * is the flash descriptor); FPR0 is the protected range register - * with the same base/limit layout. Offsets per the Intel PCH SPI - * register map (see drivers/spi/spi-intel.c in the Linux kernel): - * FDATA0-15 at 0x10-0x4C, FRACC at 0x50, FREG0-7 at 0x54-0x74, - * FPR0-4 at 0x84-0x9C. */ -#define SPI_FREG1 0x58 -#define SPI_FREG_BASE_MASK (0x7fffU << 0) -#define SPI_FREG_LIMIT_MASK (0x7fffU << 16) -#define SPI_FREG_LIMIT_SHIFT (16) -#define SPI_FREG_ADDR_SHIFT (12) -#define SPI_FPR0 (0x84) -#define SPI_FPR_WPE (1U << 31) -#define SPI_FPR_RPE (1U << 15) -#define SPI_BIOS_HSFSTS_CTL (0x4) -#define SPI_FLOCKDN (1U << 15) - -int tgl_lock_bios_region() -{ - uint32_t spi_bar, spi_cmd; - uint32_t reg; - int ret = 0; - -#if defined(DEBUG) - uint32_t bios_reg_base, bios_reg_lim; -#endif - - spi_bar = pci_config_read32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_BAR0_OFFSET); - spi_bar &= PCI_BAR_MASK; - spi_cmd = - pci_config_read32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET); - pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET, - spi_cmd | PCI_COMMAND_MEM_SPACE); - - /* The Flash Protected Range register has the same base/limit - * layout as the Flash Region register: take the BIOS region - * (FREG1, flash region 1) and enable read and write protection - * on it. The SPI registers live in the BAR's memory-mapped - * space, not in PCI configuration space. */ - reg = mmio_read32(spi_bar + SPI_FREG1); -#if defined(DEBUG) - bios_reg_base = (reg & SPI_FREG_BASE_MASK) << SPI_FREG_ADDR_SHIFT; - bios_reg_lim = ((reg & SPI_FREG_LIMIT_MASK) >> SPI_FREG_LIMIT_SHIFT) - << SPI_FREG_ADDR_SHIFT; - wolfBoot_printf("Bios reg base: 0x%x lim: 0x%x\r\n", bios_reg_base, - bios_reg_lim); -#endif - reg |= (SPI_FPR_RPE) | (SPI_FPR_WPE); - mmio_write32(spi_bar + SPI_FPR0, reg); - if ((mmio_read32(spi_bar + SPI_FPR0) & - (SPI_FPR_RPE | SPI_FPR_WPE)) != (SPI_FPR_RPE | SPI_FPR_WPE)) { - ret = -1; - } - - /* lock down BIOS register configuration */ - reg = mmio_read32(spi_bar + SPI_BIOS_HSFSTS_CTL); - reg |= SPI_FLOCKDN; - mmio_write32(spi_bar + SPI_BIOS_HSFSTS_CTL, reg); - if ((mmio_read32(spi_bar + SPI_BIOS_HSFSTS_CTL) & SPI_FLOCKDN) == 0) { - ret = -1; - } - - /* restore original cmd */ - pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET, spi_cmd); - return ret; -} - -int hal_flash_protect(haladdr_t address, int len) -{ - (void)address; - (void)len; - - /* The TGL BIOS region covers the bootloader partition, so the - * hook's address/len are the same range FREG1 describes. */ - return tgl_lock_bios_region(); -} - void hal_init(void) { gdt_setup_table(); diff --git a/hal/kontron_vx3060_s2_loader.c b/hal/nai_68int6.c similarity index 66% rename from hal/kontron_vx3060_s2_loader.c rename to hal/nai_68int6.c index 5e6b7569..3b90d909 100644 --- a/hal/kontron_vx3060_s2_loader.c +++ b/hal/nai_68int6.c @@ -1,4 +1,6 @@ -/* kontron_vx3060_s2_loader.c +/* nai_68int6.c + * + * HAL for the NAI 68INT6 3U OpenVPX SBC (Intel Tiger Lake UP3). * * Copyright (C) 2026 wolfSSL Inc. * @@ -6,7 +8,7 @@ * * wolfBoot is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, @@ -20,27 +22,41 @@ */ #include +#include #include -#include #include +#include +#include +#include +#include +#include #ifdef __WOLFBOOT -#include - - -static void panic(void); void hal_init(void) { + gdt_setup_table(); + gdt_update_segments(); + fsp_init_silicon(); } void hal_prepare_boot(void) { } -#endif +#endif /* __WOLFBOOT */ -int hal_flash_write(uint32_t address, const uint8_t *data, int len) +int hal_flash_write(uintptr_t address, const uint8_t *data, int len) { + (void)address; + (void)data; + (void)len; + return 0; +} + +int hal_flash_erase(uintptr_t address, int len) +{ + (void)address; + (void)len; return 0; } @@ -52,15 +68,11 @@ void hal_flash_lock(void) { } -int hal_flash_erase(uint32_t address, int len) -{ - return 0; -} - +/* No automatic fallback: a verification failure is terminal on this + * target rather than silently reverting. */ int wolfBoot_fallback_is_possible(void) { return 0; - } int wolfBoot_dualboot_candidate(void) @@ -75,7 +87,7 @@ void* hal_get_primary_address(void) void* hal_get_update_address(void) { - return (void*)0; + return (void*)0; } void *hal_get_dts_address(void) @@ -87,8 +99,3 @@ void *hal_get_dts_update_address(void) { return 0; } - -static void panic(void) -{ - while(1) {} -} diff --git a/hal/x86_fsp_qemu_loader.c b/hal/stub_loader.c similarity index 72% rename from hal/x86_fsp_qemu_loader.c rename to hal/stub_loader.c index bae48681..41e840c8 100644 --- a/hal/x86_fsp_qemu_loader.c +++ b/hal/stub_loader.c @@ -1,4 +1,6 @@ -/* x86_fsp_qemu_loader.c +/* stub_loader.c + * + * Generic stage1 loader HAL for x86 FSP targets. * * Copyright (C) 2026 wolfSSL Inc. * @@ -6,7 +8,7 @@ * * wolfBoot is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfBoot is distributed in the hope that it will be useful, @@ -19,10 +21,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* x86 FSP stage1 runs XIP before memory init and only authenticates stage2, + * so every HAL entry point is a stub. */ + #include +#include +#include #include #include -#include #ifdef __WOLFBOOT #include @@ -34,10 +40,13 @@ void hal_init(void) void hal_prepare_boot(void) { } -#endif +#endif /* __WOLFBOOT */ -int hal_flash_write(uintptr_t address, const uint8_t *data, int len) +int hal_flash_write(haladdr_t address, const uint8_t *data, int len) { + (void)address; + (void)data; + (void)len; return 0; } @@ -49,15 +58,16 @@ void hal_flash_lock(void) { } -int hal_flash_erase(uintptr_t address, int len) +int hal_flash_erase(haladdr_t address, int len) { + (void)address; + (void)len; return 0; } int wolfBoot_fallback_is_possible(void) { return 0; - } int wolfBoot_dualboot_candidate(void) @@ -72,7 +82,7 @@ void* hal_get_primary_address(void) void* hal_get_update_address(void) { - return (void*)0; + return (void*)0; } void *hal_get_dts_address(void) @@ -84,4 +94,3 @@ void *hal_get_dts_update_address(void) { return 0; } - diff --git a/hal/x86_fsp_tgl.c b/hal/x86_fsp_tgl.c index 8ff2832d..b0f5889d 100644 --- a/hal/x86_fsp_tgl.c +++ b/hal/x86_fsp_tgl.c @@ -27,6 +27,8 @@ #include "uart_drv.h" #include "printf.h" #include "loader.h" +#include "hal.h" +#include "pci.h" #ifdef WOLFBOOT_FSP #include "x86/ahci.h" @@ -35,7 +37,7 @@ #include "x86/tgl_fsp.h" #endif -#if defined(TARGET_kontron_vx3060_s2) +#if defined(TARGET_kontron_vx3060_s2) || defined(TARGET_nai_68int6) #define PCI_AHCI_BUS 0 #define PCI_AHCI_DEV 0x17 #define PCI_AHCI_FUN 0 @@ -106,5 +108,88 @@ int x86_fsp_tgl_init_sata(uint32_t *bar) *bar = sata_bar; return 0; } + +#ifdef WOLFBOOT_TGL +#define SPI_PCI_DEV 31 +#define SPI_PCI_FUN 5 +#define SPI_BAR_OFF 0x10 +/* Tiger Lake SPI controller register offsets, memory-mapped at the + * BAR0 base. FREG1 holds the BIOS flash region base/limit (region 0 + * is the flash descriptor); FPR0 is the protected range register + * with the same base/limit layout. Offsets per the Intel PCH SPI + * register map (see drivers/spi/spi-intel.c in the Linux kernel): + * FDATA0-15 at 0x10-0x4C, FRACC at 0x50, FREG0-7 at 0x54-0x74, + * FPR0-4 at 0x84-0x9C. */ +#define SPI_FREG1 0x58 +#define SPI_FREG_BASE_MASK (0x7fffU << 0) +#define SPI_FREG_LIMIT_MASK (0x7fffU << 16) +#define SPI_FREG_LIMIT_SHIFT (16) +#define SPI_FREG_ADDR_SHIFT (12) +#define SPI_FPR0 (0x84) +#define SPI_FPR_WPE (1U << 31) +#define SPI_FPR_RPE (1U << 15) +#define SPI_BIOS_HSFSTS_CTL (0x4) +#define SPI_FLOCKDN (1U << 15) + +int tgl_lock_bios_region(void) +{ + uint32_t spi_bar, spi_cmd; + uint32_t reg; + int ret = 0; + +#if defined(DEBUG) + uint32_t bios_reg_base, bios_reg_lim; +#endif + + spi_bar = pci_config_read32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_BAR0_OFFSET); + spi_bar &= PCI_BAR_MASK; + spi_cmd = + pci_config_read32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET); + pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET, + spi_cmd | PCI_COMMAND_MEM_SPACE); + + /* The Flash Protected Range register has the same base/limit + * layout as the Flash Region register: take the BIOS region + * (FREG1, flash region 1) and enable read and write protection + * on it. The SPI registers live in the BAR's memory-mapped + * space, not in PCI configuration space. */ + reg = mmio_read32(spi_bar + SPI_FREG1); +#if defined(DEBUG) + bios_reg_base = (reg & SPI_FREG_BASE_MASK) << SPI_FREG_ADDR_SHIFT; + bios_reg_lim = ((reg & SPI_FREG_LIMIT_MASK) >> SPI_FREG_LIMIT_SHIFT) + << SPI_FREG_ADDR_SHIFT; + wolfBoot_printf("Bios reg base: 0x%x lim: 0x%x\r\n", bios_reg_base, + bios_reg_lim); +#endif + reg |= (SPI_FPR_RPE) | (SPI_FPR_WPE); + mmio_write32(spi_bar + SPI_FPR0, reg); + if ((mmio_read32(spi_bar + SPI_FPR0) & + (SPI_FPR_RPE | SPI_FPR_WPE)) != (SPI_FPR_RPE | SPI_FPR_WPE)) { + ret = -1; + } + + /* lock down BIOS register configuration */ + reg = mmio_read32(spi_bar + SPI_BIOS_HSFSTS_CTL); + reg |= SPI_FLOCKDN; + mmio_write32(spi_bar + SPI_BIOS_HSFSTS_CTL, reg); + if ((mmio_read32(spi_bar + SPI_BIOS_HSFSTS_CTL) & SPI_FLOCKDN) == 0) { + ret = -1; + } + + /* restore original cmd */ + pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET, spi_cmd); + return ret; +} + +int hal_flash_protect(haladdr_t address, int len) +{ + (void)address; + (void)len; + + /* The TGL BIOS region covers the bootloader partition, so the + * hook's address/len are the same range FREG1 describes. */ + return tgl_lock_bios_region(); +} +#endif /* WOLFBOOT_TGL */ #endif diff --git a/include/x86/fsp_config.h b/include/x86/fsp_config.h new file mode 100644 index 00000000..3689c638 --- /dev/null +++ b/include/x86/fsp_config.h @@ -0,0 +1,44 @@ +#ifndef FSP_CONFIG_H +#define FSP_CONFIG_H + +#include + +#ifndef FSP_HYPERTHREADING +#define FSP_HYPERTHREADING 0 +#endif +#if FSP_HYPERTHREADING +/* The MADT and MP table list four single-thread cores (APIC IDs 0/2/4/6). */ +#error "FSP_HYPERTHREADING=1 needs sibling threads in the MADT and MP table" +#endif + +#ifndef FSP_INTEL_SPEED_STEP +#define FSP_INTEL_SPEED_STEP 0 +#endif + +#ifndef FSP_INTEL_SPEED_SHIFT +#define FSP_INTEL_SPEED_SHIFT 0 +#endif + +#define FSP_BOOT_FREQ_MAX_NO_TURBO 0x1 +#ifndef FSP_BOOT_PERFORMANCE_MODE +#define FSP_BOOT_PERFORMANCE_MODE FSP_BOOT_FREQ_MAX_NO_TURBO +#endif + +#ifndef FSP_C_STATES +#define FSP_C_STATES 0 +#endif + +#ifndef FSP_TXT +#define FSP_TXT 0 +#endif + +#ifndef FSP_IN_BAND_ECC +#define FSP_IN_BAND_ECC 1 +#endif + +/* TM1/TM2 throttling at the thermal-control limit, the FSP default */ +#ifndef FSP_THERMAL_THROTTLING +#define FSP_THERMAL_THROTTLING 1 +#endif + +#endif diff --git a/include/x86/gpio_config.h b/include/x86/gpio_config.h new file mode 100644 index 00000000..73bcd468 --- /dev/null +++ b/include/x86/gpio_config.h @@ -0,0 +1,1097 @@ +/** + * @file gpio_config.h + * + */ + +#ifndef GPIO_CONFIG_H +#define GPIO_CONFIG_H + +#include + +#define GPIO_COMM_4_PORT_ID 0x6a +#define GPIO_COMM_0_PORT_ID (0x6e) +#define GPIO_COMM_1_PORT_ID (0x6d) +#define GPIO_COMM_5_PORT_ID (0x69) +#define GPIO_MODE_NATIVE_1 0x01 +#define GPIO_MODE_GPIO (0x0) +#define GPIO_RESET_PLTRST 0x02 +#define GPIO_RESET_HOSTDEEPRESET (0x01) +#define GPIO_DIR_INPUT (0x1) +#define GPIO_DIR_OUTPUT (0x2) +#define GPIO_INTERRUPT_DISABLE (0x0) +#define GPIO_INTERRUPT_SCI (1 << 2) +#define GPIO_TERM_NONE (0x0) +#define GPIO_RXEVCONF_LEVEL (0) +#define GPIO_MODE_SHIFT 10 +#define GPIO_MODE_MASK (0x7) << GPIO_MODE_SHIFT +#define GPIO_RESET_SHIFT 30 +#define GPIO_RESET_MASK (0x3) << GPIO_RESET_SHIFT +#define GPIO_DIR_SHIFT (0x8) +#define GPIO_DIR_MASK (0x3) << GPIO_DIR_SHIFT +#define GPIO_RXINV_SHIFT (23) +#define GPIO_RXINV_MASK (0x1) << 23 +#define GPIO_INTERRUPT_SHIFT (17) +#define GPIO_INTERRUPT_MASK (0xf) << GPIO_INTERRUPT_SHIFT +#define GPIO_TERM_SHIFT (10) +#define GPIO_TERM_MASK (0xf) << GPIO_TERM_SHIFT +#define GPIO_RXEVCONF_SHIFT (25) +#define GPIO_RXEVCONF_MASK (0x3) << GPIO_RXEVCONF_SHIFT + +#define GPIO_GPPC_B9_CFG_OFF (0x790) +#define GPIO_GPPC_B10_CFG_OFF (0x7a0) +#define GPIO_GPPC_C6_CFG_OFF (0x760) +#define GPIO_GPPC_C7_CFG_OFF (0x770) +#define GPIO_GPPC_C8_CFG_OFF (0x780) +#define GPIO_GPPC_C9_CFG_OFF (0x790) +#define GPIO_GPPC_C10_CFG_OFF (0x7a0) +#define GPIO_GPPC_C11_CFG_OFF (0x7b0) +#define GPIO_GPPC_C12_CFG_OFF (0x7c0) +#define GPIO_GPPC_C13_CFG_OFF (0x7d0) +#define GPIO_GPPC_C14_CFG_OFF (0x7e0) +#define GPIO_GPPC_C15_CFG_OFF (0x7f0) +#define GPIO_GPPC_C20_CFG_OFF (0x840) +#define GPIO_GPPC_C21_CFG_OFF (0x850) +#define GPIO_GPPC_C22_CFG_OFF (0x860) +#define GPIO_GPPC_D0_CFG_OFF (0x900) +#define GPIO_GPPC_D1_CFG_OFF (0x910) +#define GPIO_GPPC_D2_CFG_OFF (0x920) +#define GPIO_GPP_R0_CFG_OFF (0x700) +#define GPIO_GPP_R1_CFG_OFF (0x710) +#define GPIO_GPP_R2_CFG_OFF (0x720) +#define GPIO_GPP_R3_CFG_OFF (0x730) +#define GPIO_GPP_R4_CFG_OFF (0x740) +#define GPIO_GPP_R5_CFG_OFF (0x750) +#define GPIO_GPPC_A8_CFG_OFF (0xa20) +#define GPIO_GPPC_E12_CFG_OFF (0xb30) +#define GPIO_GPPC_E15_CFG_OFF (0xb60) +#define GPIO_GPPC_E16_CFG_OFF (0xb70) +#define GPIO_GPPC_F2_CFG_OFF (0xba0) +#define GPIO_GPPC_F4_CFG_OFF (0xbc0) +#define GPIO_GPPC_F5_CFG_OFF (0xbd0) +#define GPIO_GPPC_F9_CFG_OFF (0x910) +#define GPIO_GPPC_A9_CFG_OFF (0xa30) +#define GPIO_GPPC_T2_CFG_OFF (0x8c0) +#define GPIO_GPPC_T3_CFG_OFF (0x8d0) + +#define GPIO_OWN_MASK (0x3) +/* struct tgl_gpio, enum gpio_config_flags and struct tgl_gpio_conf are defined + * by the includer (src/x86/tgl_fsp.c); only the pad tables live here. */ + +#if defined (TARGET_kontron_vx3060_s2) || defined (TARGET_nai_68int6) + +#if defined (TARGET_nai_68int6) +/* Pad settings snapshotted from a running 68INT6 with the stock BIOS. + * HOSTSW_OWN and PADCFGLOCK are not captured. */ + +/* Console UART2 pads (C20/C21), muxed before anything prints. */ +static const struct tgl_gpio_conf gpio_table_tempram[] = { + /* PAD C20 (DW0=0x44000702 DW1=0x00020122) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C20_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C21 (DW0=0x44000700 DW1=0x00000123) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C21_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, +}; + +/* Nothing is required between tempram and memory init on this board. */ +static const struct tgl_gpio_conf gpio_table_premem[] = { +}; + +/* The rest of the stock pad settings, applied after silicon init. */ +static const struct tgl_gpio_conf gpio_table_presilicon[] = { + /* PAD C8 (DW0=0x44000702 DW1=0x00020176) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C8_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C9 (DW0=0x44000700 DW1=0x00000177) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C9_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C10 (DW0=0x44000300 DW1=0x00000018) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C10_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C11 (DW0=0x44000300 DW1=0x00000019) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C11_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C12 (DW0=0x44000702 DW1=0x0002011A) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C12_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C13 (DW0=0x44000700 DW1=0x0000011B) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C13_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C14 (DW0=0x40100102 DW1=0x0000301C) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C14_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = 0x0C, + .gpio_interrupt = 0x08, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x00, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C15 (DW0=0x84000201 DW1=0x0000001D) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C15_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD F2 (DW0=0x44001600 DW1=0x00003C3F) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F2_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x05, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = 0x0F, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD A8 (DW0=0x44000B00 DW1=0x00000048) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_A8_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x02, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD E12 (DW0=0x84000201 DW1=0x00000038) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E12_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD E15 (DW0=0x44000B00 DW1=0x0000003B) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E15_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x02, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD E16 (DW0=0x84000102 DW1=0x0000003C) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E16_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD F9 (DW0=0x84000201 DW1=0x0000005F) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F9_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD A9 (DW0=0x44000B00 DW1=0x00000049) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_A9_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x02, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD F4 (DW0=0x44001600 DW1=0x00003C41) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F4_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x05, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = 0x0F, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD F5 (DW0=0x84000200 DW1=0x00000042) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F5_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD T2 (DW0=0x44000B00 DW1=0x00001032) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_T2_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x02, + .gpio_dir = 0x03, + .gpio_term = 0x04, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD T3 (DW0=0x44000B00 DW1=0x00001033) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_T3_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = 0x02, + .gpio_dir = 0x03, + .gpio_term = 0x04, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C22 (DW0=0x44000102 DW1=0x00000024) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C22_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD B10 (DW0=0x44000300 DW1=0x00000022) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_B10_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD B9 (DW0=0x44000300 DW1=0x00000021) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_B9_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD C6 (DW0=0x04000702 DW1=0x00000074) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C6_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = 0x00}, + /* PAD C7 (DW0=0x04000702 DW1=0x00000075) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C7_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = 0x00}, + /* PAD D1 (DW0=0x84000200 DW1=0x0000002D) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D1_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD D0 (DW0=0x84000102 DW1=0x0000002C) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D0_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD D2 (DW0=0x84000201 DW1=0x0000002E) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D2_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, + /* PAD R0 (DW0=0x44000700 DW1=0x0003C058) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R0_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD R1 (DW0=0x44000700 DW1=0x0003FC59) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R1_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = 0x0F, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD R2 (DW0=0x44000600 DW1=0x0003FC5A) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R2_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = 0x0F, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD R3 (DW0=0x44000700 DW1=0x0003FC5B) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R3_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = 0x0F, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD R4 (DW0=0x44000700 DW1=0x0003C05C) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R4_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = 0x03, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET}, + /* PAD R5 (DW0=0x84000200 DW1=0x0000005D) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R5_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | + GPIO_SET_TERM | GPIO_SET_INTERRUPT | GPIO_SET_RXINV | + GPIO_SET_RXEVCONF), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_interrupt = 0x00, + .gpio_rxinv = 0x00, + .gpio_rxevconf = 0x02, + .gpio_reset = GPIO_RESET_PLTRST}, +}; + +#else /* TARGET_kontron_vx3060_s2 */ +static const struct tgl_gpio_conf gpio_table_tempram[] = { + /* UART 0 */ + {.gpio = + { + /* PAD C8 */ + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C8_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + /* PAD C9 */ + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C9_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C10_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_term = GPIO_TERM_NONE, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C11_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_term = GPIO_TERM_NONE, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_reset = GPIO_RESET_PLTRST}, + /* UART - 1*/ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C12_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C13_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C14_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_term = GPIO_TERM_NONE, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C15_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_term = GPIO_TERM_NONE, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_reset = GPIO_RESET_PLTRST}, + /* UART - 2*/ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C20_CFG_OFF, + }, + .flags = + (GPIO_SET_DIRECTION | GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C21_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_term = GPIO_TERM_NONE, + .gpio_reset = GPIO_RESET_PLTRST}, +}; + +static const struct tgl_gpio_conf gpio_table_premem[] = { +}; + +static const struct tgl_gpio_conf gpio_table_presilicon[] = { + /* Disable CNVi (Bluetooth Radio Interface) */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F2_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + /* set to GPIO mode as native functions aren't used */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_A8_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E12_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E15_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_E16_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F9_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + /* test points */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_A9_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F4_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_F5_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_OUTPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST}, + /* FUSA_DIAGTEST pads (T2/T3) are intentionally not programmed. */ + /* TPM */ + {.gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C22_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_RXINV | GPIO_SET_RESET | + GPIO_SET_RXEVCONF | GPIO_SET_TERM | GPIO_SET_INTERRUPT), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_rxinv = 1, + .gpio_rxevconf = GPIO_RXEVCONF_LEVEL, + .gpio_interrupt = GPIO_INTERRUPT_SCI, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET, + .gpio_term = GPIO_TERM_NONE}, + /* PCH I2C5 */ + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_B10_CFG_OFF, + }, + .flags = + (GPIO_SET_MODE | GPIO_SET_INTERRUPT | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_0_PORT_ID, + .cfg_offset = GPIO_GPPC_B9_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + /* SMLINK1 to PD */ + {/* SM1 CLK */ + .gpio = + { + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C6_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + /* SM1 DATA */ + .comm_port_id = GPIO_COMM_4_PORT_ID, + .cfg_offset = GPIO_GPPC_C7_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_NATIVE_1, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + /* watchdog */ + {.gpio = + { + /* PLD_WDT_IRQ0 */ + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D1_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + /* PLD_WDT_IRQ1 */ + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D0_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET, + .gpio_term = GPIO_TERM_NONE}, + /* wake from i225/E810/i210/M2_TOP/M2_BOT/XMC */ + {.gpio = + { + .comm_port_id = GPIO_COMM_1_PORT_ID, + .cfg_offset = GPIO_GPPC_D2_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_HOSTDEEPRESET, + .gpio_term = GPIO_TERM_NONE}, + /* Audio, disabled */ + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R0_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R1_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R2_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R3_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R4_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + {.gpio = + { + .comm_port_id = GPIO_COMM_5_PORT_ID, + .cfg_offset = GPIO_GPP_R5_CFG_OFF, + }, + .flags = (GPIO_SET_MODE | GPIO_SET_DIRECTION | GPIO_SET_INTERRUPT | + GPIO_SET_RESET | GPIO_SET_TERM), + .gpio_mode = GPIO_MODE_GPIO, + .gpio_dir = GPIO_DIR_INPUT, + .gpio_interrupt = GPIO_INTERRUPT_DISABLE, + .gpio_reset = GPIO_RESET_PLTRST, + .gpio_term = GPIO_TERM_NONE}, + +}; +#endif /* TARGET_nai_68int6 */ + +#endif /* TARGET_kontron_vx3060_s2 || TARGET_nai_68int6 */ + +#endif // GPIO_CONFIG_H diff --git a/include/x86/mptable.h b/include/x86/mptable.h index 41dab2f7..29ad25e5 100644 --- a/include/x86/mptable.h +++ b/include/x86/mptable.h @@ -150,7 +150,7 @@ enum mp_irq_source_types { #define MP_CPU_NUM_ENTRY 1 #endif -#ifdef TARGET_kontron_vx3060_s2 +#if defined(TARGET_kontron_vx3060_s2) || defined(TARGET_nai_68int6) #define MP_IOAPIC_NUM_ENTRY 1 #define MP_INTSRC_NUM_ENTRY 17 #define MP_LINTSRC_NUM_ENTRY 0 diff --git a/include/x86/tgl_fsp.h b/include/x86/tgl_fsp.h index b3b2b148..5145fbc1 100644 --- a/include/x86/tgl_fsp.h +++ b/include/x86/tgl_fsp.h @@ -24,5 +24,6 @@ #include int x86_fsp_tgl_init_sata(uint32_t *bar); +int tgl_lock_bios_region(void); #endif /* TGL_FSP_H */ diff --git a/options.mk b/options.mk index 350620f2..691ebcfd 100644 --- a/options.mk +++ b/options.mk @@ -54,8 +54,16 @@ WOLFBOOT_TIME_TEST?=0 # Generate a minimal ACPI table set (RSDP/XSDT/FADT/MADT/MCFG + DSDT) for the # x86 FSP Linux payload, so the OS gets the interrupt model and PCI routing. ifeq ($(ACPI),1) + ifneq ($(TARGET),nai_68int6) + $(error ACPI=1 tables (CPU list, DSDT routing) are specific to nai_68int6) + endif CFLAGS+=-D"WOLFBOOT_ACPI" endif +ifeq ($(TARGET),nai_68int6) + ifneq ($(ACPI),1) + $(error nai_68int6 needs ACPI=1: its PCI interrupt routing is only in the DSDT) + endif +endif # TPM NV version floor and boot audit counters (see docs/Targets.md). # HALT_ON_FAILURE also halts when the TPM state cannot be read or locked. @@ -1601,6 +1609,7 @@ ifeq ($(FSP), 1) X86_UART_BASE \ X86_UART_REG_WIDTH \ X86_UART_MMIO \ + X86_UART_NUMBER \ PCH_HAS_PCR \ PCI_USE_ECAM \ PCH_PCR_BASE \ diff --git a/src/boot_x86_fsp_payload.c b/src/boot_x86_fsp_payload.c index d7fb793e..c976687f 100644 --- a/src/boot_x86_fsp_payload.c +++ b/src/boot_x86_fsp_payload.c @@ -64,6 +64,15 @@ uint8_t mb2_boot_info[MAX_MB2_BOOT_INFO_SIZE]; #ifdef TARGET_kontron_vx3060_s2 static char *cmdline = "apic=verbose acpi=no pci=debug console=ttyS0,115200 debug"; +#elif defined(TARGET_nai_68int6) +#define CMDLINE_STR_(x) #x +#define CMDLINE_STR(x) CMDLINE_STR_(x) +/* earlycon covers LPSS UART2 at its FSP-assigned base until the 8250 driver + * binds it as ttyS4 */ +static char *cmdline = + "earlycon=uart8250,mmio32," CMDLINE_STR(X86_UART_BASE) ",115200n8 " + "console=ttyS4,115200 console=tty0 " + "root=/dev/sda2 rw rootwait"; #elif TARGET_x86_fsp_qemu static char *cmdline = "console=ttyS0,115200 pci=earlydump debug"; #else diff --git a/src/pci.c b/src/pci.c index 934f8ed3..c969e772 100644 --- a/src/pci.c +++ b/src/pci.c @@ -390,10 +390,18 @@ static int pci_pre_enum_cb(uint8_t bus, uint8_t dev, uint8_t fun) #ifdef WOLFBOOT_TGL if (bus != 0) return 0; - /* don't change UART mapping */ - if (dev == 0x1e && (fun == 0 || fun == 1)) { + /* Leave the console UART BAR at X86_UART_BASE. LPSS UART0/1 are + * 00:1e.0/1, UART2 is 00:19.2. */ +#if defined(X86_UART_NUMBER) && (X86_UART_NUMBER == 2) + if (dev == 0x19 && fun == 2) return 1; - } +#elif defined(X86_UART_NUMBER) && (X86_UART_NUMBER == 1) + if (dev == 0x1e && fun == 1) + return 1; +#else + if (dev == 0x1e && fun == 0) + return 1; +#endif /* PMC BARs shouldn't be programmed as per FSP integration guide */ if (dev == 31 && fun == 2) return 1; diff --git a/src/tpm.c b/src/tpm.c index c44c1767..3df6b66a 100644 --- a/src/tpm.c +++ b/src/tpm.c @@ -477,7 +477,7 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line) int rc; #ifdef WOLFBOOT_DEBUG_TPM uint8_t digest[WOLFBOOT_TPM_PCR_DIG_SZ]; - int digestSz = 0; + int digestSz = (int)sizeof(digest); #endif /* clear auth session for PCR */ @@ -502,7 +502,8 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line) wolfBoot_printf("PCR %d: Res %d, Digest Sz %d\n", pcrIndex, read_rc, digestSz); - wolfBoot_print_bin(digest, digestSz); + if (read_rc == 0) + wolfBoot_print_bin(digest, digestSz); } else { wolfBoot_printf("Measure boot failed! Index %d, %x (%s)\n", diff --git a/src/update_disk.c b/src/update_disk.c index d0343aaa..4e3aedb2 100644 --- a/src/update_disk.c +++ b/src/update_disk.c @@ -91,6 +91,11 @@ static uint8_t disk_encrypt_nonce[ENCRYPT_NONCE_SIZE]; #define BOOT_PART_A 5 #define BOOT_PART_B 6 #endif +#ifdef TARGET_nai_68int6 + /* Signed kernels live in the 3rd and 4th GPT partitions (sda3/sda4). */ + #define BOOT_PART_A 2 + #define BOOT_PART_B 3 +#endif #endif /* WOLFBOOT_FSP */ /* Default values for BOOT_DISK, BOOT_PART_A and BOOT_PART_B */ diff --git a/src/x86/mptable.c b/src/x86/mptable.c index 0edd871d..2d1f2947 100644 --- a/src/x86/mptable.c +++ b/src/x86/mptable.c @@ -27,7 +27,7 @@ #define LOCAL_APIC_ID 0xfee00020 #define LOCAL_APIC_VER 0xfee00030 -#ifdef TARGET_kontron_vx3060_s2 +#if defined(TARGET_kontron_vx3060_s2) || defined(TARGET_nai_68int6) #define ISA_BUS 0x4 /* TGL mptable */ @@ -518,7 +518,7 @@ void mptable_setup(void) _mp->mpce_processor[0]._res[0] = _mp->mpce_processor[0]._res[1] = 0; -#ifdef TARGET_kontron_vx3060_s2 +#if defined(TARGET_kontron_vx3060_s2) || defined(TARGET_nai_68int6) { int i; for (i = 1; i < 4; ++i) { diff --git a/src/x86/tgl_fsp.c b/src/x86/tgl_fsp.c index 4b6f88a9..03066e6f 100644 --- a/src/x86/tgl_fsp.c +++ b/src/x86/tgl_fsp.c @@ -47,6 +47,9 @@ #include #include #include +#ifdef TARGET_nai_68int6 +#include +#endif #define PCR_DMI_PORT_ID 0x88 #define PCR_DMI_LPCLGIR1 0x2730 @@ -238,6 +241,9 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) FSP_M_CONFIG *mem_cfg; mem_cfg = &udp->FspmConfig; + /* Kontron VX3060-S2 DQ maps and DDR tuning; other boards keep the FSP-M + * defaults. */ +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->PlatformMemorySize = 93806592; mem_cfg->DqMapCpu2DramMc0Ch0[0] = 13; mem_cfg->DqMapCpu2DramMc0Ch0[1] = 12; @@ -367,6 +373,7 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->DqMapCpu2DramMc1Ch3[13] = 9; mem_cfg->DqMapCpu2DramMc1Ch3[14] = 8; mem_cfg->DqMapCpu2DramMc1Ch3[15] = 13; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->TsegSize = 8388608; mem_cfg->SpdAddressTable[0] = 160; mem_cfg->SpdAddressTable[1] = 0; @@ -394,8 +401,10 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->VtdBaseAddress[7] = 0; mem_cfg->VtdBaseAddress[8] = 0; mem_cfg->UserBd = 5; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->RMT = 1; mem_cfg->NModeSupport = 2; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->PchHdaEnable = 0; mem_cfg->GttMmAdr = 2147483648; mem_cfg->DdiPort2Hpd = 1; @@ -404,14 +413,22 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->DdiPort4Ddc = 1; mem_cfg->EnableC6Dram = 0; mem_cfg->HyperThreading = 0; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->CpuRatio = 0; mem_cfg->FClkFrequency = 1; +#endif /* TARGET_kontron_vx3060_s2 */ +#ifdef TARGET_nai_68int6 + mem_cfg->VmxEnable = 1; +#else mem_cfg->VmxEnable = 0; +#endif mem_cfg->BiosGuard = 0; mem_cfg->EnableSgx = 0; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->TxtDprMemorySize = 4194304; mem_cfg->BiosAcmBase = 4285267968; mem_cfg->ConfigTdpLevel = 2; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->PcieClkSrcUsage[0] = 128; mem_cfg->PcieClkSrcUsage[1] = 128; mem_cfg->PcieClkSrcUsage[2] = 128; @@ -434,7 +451,9 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) * set from X86_UART_NUMBER or the console changes between phases - output * appears for part of the boot and then stops, reading as a hang. */ mem_cfg->SerialIoUartDebugControllerNumber = X86_UART_NUMBER; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->MrcSafeConfig = 1; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->TcssItbtPcie0En = 0; mem_cfg->TcssItbtPcie1En = 0; mem_cfg->TcssItbtPcie2En = 0; @@ -442,9 +461,12 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->TcssXdciEn = 1; mem_cfg->TcssDma0En = 0; mem_cfg->TcssDma1En = 0; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->RMC = 0; mem_cfg->EccSupport = 0; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->Ibecc = 1; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->IbeccParity = 1; mem_cfg->RankInterleave = 0; mem_cfg->EnhancedInterleave = 0; @@ -452,9 +474,12 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->ChHashMask = 12492; mem_cfg->PowerDownMode = 0; mem_cfg->SafeMode = 1; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->UsbTcPortEnPreMem = 15; mem_cfg->WrcFeatureEnable = 0; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->McParity = 1; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->PchHdaSdiEnable[0] = 1; mem_cfg->PchHdaSdiEnable[1] = 1; mem_cfg->PchHdaAudioLinkDmicEnable[0] = 0; @@ -470,7 +495,9 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->PchHdaAudioLinkSndwEnable[1] = 1; mem_cfg->PchHdaAudioLinkSndwEnable[2] = 0; mem_cfg->PchHdaAudioLinkSndwEnable[3] = 0; +#ifdef TARGET_kontron_vx3060_s2 mem_cfg->SkipCpuReplacementCheck = 1; +#endif /* TARGET_kontron_vx3060_s2 */ mem_cfg->SerialIoUartDebugMode = 4; mem_cfg->PcieRefPllSsc = 0; return 0; @@ -497,7 +524,9 @@ static void fsp_set_silicon_cfg(FSPS_UPD *fsps) { FSP_S_CONFIG *upd = &fsps->FspsConfig; +#ifdef TARGET_kontron_vx3060_s2 upd->GraphicsConfigPtr = 2024131364; +#endif /* TARGET_kontron_vx3060_s2 */ upd->SataPortsEnable[0] = 1; upd->SataPortsEnable[1] = 1; @@ -661,18 +690,33 @@ static void fsp_set_silicon_cfg(FSPS_UPD *fsps) upd->IomTypeCPortPadCfg[7] = 0; upd->UsbTcPortEn = 15; upd->AesEnable = 0; +#ifdef TARGET_kontron_vx3060_s2 upd->PchWriteProtectionEnable[0] = 1; upd->PchWriteProtectionEnable[1] = 1; +#else + upd->PchWriteProtectionEnable[0] = 0; + upd->PchWriteProtectionEnable[1] = 0; +#endif /* TARGET_kontron_vx3060_s2 */ upd->PchWriteProtectionEnable[2] = 0; upd->PchWriteProtectionEnable[3] = 0; upd->PchWriteProtectionEnable[4] = 0; +#ifdef TARGET_kontron_vx3060_s2 upd->PchProtectedRangeLimit[0] = 13679; upd->PchProtectedRangeLimit[1] = 16383; +#else + upd->PchProtectedRangeLimit[0] = 0; + upd->PchProtectedRangeLimit[1] = 0; +#endif /* TARGET_kontron_vx3060_s2 */ upd->PchProtectedRangeLimit[2] = 0; upd->PchProtectedRangeLimit[3] = 0; upd->PchProtectedRangeLimit[4] = 0; +#ifdef TARGET_kontron_vx3060_s2 upd->PchProtectedRangeBase[0] = 13312; upd->PchProtectedRangeBase[1] = 13744; +#else + upd->PchProtectedRangeBase[0] = 0; + upd->PchProtectedRangeBase[1] = 0; +#endif /* TARGET_kontron_vx3060_s2 */ upd->PchProtectedRangeBase[2] = 0; upd->PchProtectedRangeBase[3] = 0; upd->PchProtectedRangeBase[4] = 0; @@ -953,9 +997,16 @@ int fsp_machine_update_s_parameters(uint8_t *default_s_params) upd->MicrocodeRegionBase = 0x0; upd->MicrocodeRegionSize = 0x0; +#ifdef TARGET_nai_68int6 + /* No table: the FSP's built-in PCH interrupt routing matches the DSDT + * _PRT; a partial table leaves other devices' INTx unrouted. */ + upd->DevIntConfigPtr = 0; + upd->NumOfDevIntConfig = 0; +#else /* we can assume that is under 4gb */ upd->DevIntConfigPtr = (uint32_t)(uintptr_t)mPchHDevIntConfig; upd->NumOfDevIntConfig = sizeof(mPchHDevIntConfig)/sizeof(mPchHDevIntConfig[0]); +#endif upd->SataEnable = 1; upd->SataMode = 0; upd->SataSalpSupport = 0; @@ -978,6 +1029,13 @@ int fsp_machine_update_s_parameters(uint8_t *default_s_params) memset(upd->PcieRpHotPlug, 0, sizeof(upd->PcieRpHotPlug)); memset(upd->CpuPcieRpHotPlug, 0, sizeof(upd->CpuPcieRpHotPlug)); +#ifdef TARGET_nai_68int6 + upd->Eist = FSP_INTEL_SPEED_STEP; + upd->Hwp = FSP_INTEL_SPEED_SHIFT; + upd->Cx = FSP_C_STATES; + upd->TxtEnable = FSP_TXT; + upd->ThermalMonitor = FSP_THERMAL_THROTTLING; +#endif return 0; } /** @@ -1470,6 +1528,8 @@ static const struct tgl_gpio_conf gpio_table_presilicon[] = { .gpio_term = GPIO_TERM_NONE}, }; +#elif defined(TARGET_nai_68int6) +#include #endif /* TARGET_kontron_vx3060_s2 */ /** * @brief Configure GPIO settings for a specific device. @@ -1655,6 +1715,16 @@ int post_temp_ram_init_cb(void) kontron_ask_for_recovery(); +#elif defined(TARGET_nai_68int6) + unsigned int i; + unsigned int n; + + /* No CPLD or SuperIO: the LTC2870 transceiver resets to RS-232, so only + * the console pads need setting up. */ + n = sizeof(gpio_table_tempram)/sizeof(gpio_table_tempram[0]); + for (i = 0; i < n; i++) { + tgl_gpio_configure(&gpio_table_tempram[i]); + } #else (void)tgl_gpio_configure; #endif /* TARGET_kontron_vx3060_s2 */ @@ -1691,6 +1761,11 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params, new_udp->FspmArchUpd.NvsBufferPtr = 0; new_udp->FspmArchUpd.StackBase = mem_base; new_udp->FspmArchUpd.StackSize = mem_size; +#ifdef TARGET_nai_68int6 + new_udp->FspmConfig.HyperThreading = FSP_HYPERTHREADING; + new_udp->FspmConfig.BootFrequency = FSP_BOOT_PERFORMANCE_MODE; + new_udp->FspmConfig.Ibecc = FSP_IN_BAND_ECC; +#endif return 0; } @@ -1698,8 +1773,12 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params, int fsp_pre_mem_init_cb(void) { unsigned int i; + unsigned int n; - for (i = 0; i < sizeof(gpio_table_premem)/sizeof(gpio_table_premem[0]); i++) { + /* via a variable: the table is empty on some targets, and comparing + * against the literal 0 that sizeof folds to trips -Wtype-limits. */ + n = sizeof(gpio_table_premem)/sizeof(gpio_table_premem[0]); + for (i = 0; i < n; i++) { tgl_gpio_configure(&gpio_table_premem[i]); } diff --git a/tools/scripts/x86_fsp/select_fsp.sh b/tools/scripts/x86_fsp/select_fsp.sh new file mode 100755 index 00000000..70805a43 --- /dev/null +++ b/tools/scripts/x86_fsp/select_fsp.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# +# Switch the in-tree FSP set (UPD headers and FSP binaries) between QEMU, +# Tiger Lake and NAI; their generators all write the same paths. +# +# Usage: +# select_fsp.sh save {tgl|qemu|nai} snapshot the current in-tree set +# select_fsp.sh use {tgl|qemu|nai} restore a snapshotted set into the tree +# select_fsp.sh show report what is cached and what is in-tree +# +set -e + +CACHE="${WOLFBOOT_FSP_CACHE:-$HOME/.cache/wolfboot-fsp}" +ROOT="$(cd "$(dirname "$0")/../../.." && pwd)" +HDRS="FspUpd.h FspmUpd.h FspsUpd.h FsptUpd.h" +# Headers only some generators emit; each set restores only its own, so one +# cannot leak into another. +HDRS_OPT_ALL="MemInfoHob.h" +HDRS_OPT_tgl="MemInfoHob.h" +HDRS_OPT_nai="MemInfoHob.h" +BINS="fsp_t.bin fsp_m.bin fsp_s.bin" +# ucode0.bin is only produced by the TGL flow +EXTRA_tgl="ucode0.bin" +# NAI: the TGL flow with NAI's own FSP and microcode (nai_extract_fsp.sh) +EXTRA_nai="ucode0.bin" + +usage() { sed -n '3,9p' "$0" | sed 's/^# \{0,1\}//'; exit 1; } + +check_set() { + case "$1" in + tgl|qemu|nai) ;; + *) echo "error: set must be 'tgl', 'qemu' or 'nai'" >&2; exit 1 ;; + esac +} + +do_save() { + local s="$1" extra opt n=0 + eval "extra=\${EXTRA_$s:-}" + eval "opt=\${HDRS_OPT_$s:-}" + mkdir -p "$CACHE/$s" + for f in $HDRS; do + [ -f "$ROOT/include/x86/fsp/$f" ] || { echo "error: missing include/x86/fsp/$f" >&2; exit 1; } + cp "$ROOT/include/x86/fsp/$f" "$CACHE/$s/"; n=$((n+1)) + done + for f in $HDRS_OPT_ALL; do + rm -f "$CACHE/$s/$f" + done + for f in $opt; do + [ -f "$ROOT/include/x86/fsp/$f" ] && { cp "$ROOT/include/x86/fsp/$f" "$CACHE/$s/"; n=$((n+1)); } + done + for f in $BINS $extra; do + [ -f "$ROOT/src/x86/$f" ] || { echo "error: missing src/x86/$f" >&2; exit 1; } + cp "$ROOT/src/x86/$f" "$CACHE/$s/"; n=$((n+1)) + done + echo "saved $n files to $CACHE/$s" +} + +do_use() { + local s="$1" extra opt n=0 + eval "extra=\${EXTRA_$s:-}" + eval "opt=\${HDRS_OPT_$s:-}" + [ -d "$CACHE/$s" ] || { echo "error: no snapshot for '$s'. Run the generator then 'select_fsp.sh save $s'." >&2; exit 1; } + # Check every required file before copying any, so a partial cache fails + # here rather than leaving a half-updated tree. + for f in $HDRS $BINS $extra; do + [ -f "$CACHE/$s/$f" ] || { echo "error: cached '$s' set is missing $f; re-run the generator then 'select_fsp.sh save $s'" >&2; exit 1; } + done + for f in $HDRS; do + cp "$CACHE/$s/$f" "$ROOT/include/x86/fsp/"; n=$((n+1)) + done + for f in $HDRS_OPT_ALL; do + rm -f "$ROOT/include/x86/fsp/$f" + done + for f in $opt; do + [ -f "$CACHE/$s/$f" ] && { cp "$CACHE/$s/$f" "$ROOT/include/x86/fsp/"; n=$((n+1)); } + done + for f in $BINS $extra; do + cp "$CACHE/$s/$f" "$ROOT/src/x86/"; n=$((n+1)) + done + echo "restored $n files of the '$s' FSP set" +} + +do_show() { + echo "cache: $CACHE" + for s in tgl qemu nai; do + if [ -d "$CACHE/$s" ]; then + echo " $s: $(ls "$CACHE/$s" | wc -l) files" + else + echo " $s: (not snapshotted)" + fi + done + echo "in-tree include/x86/fsp/FspmUpd.h:" + if [ -f "$ROOT/include/x86/fsp/FspmUpd.h" ]; then + # the TGL header is thousands of lines; the QEMU one is a small stub + printf " %s lines -> looks like %s\n" \ + "$(wc -l < "$ROOT/include/x86/fsp/FspmUpd.h")" \ + "$([ "$(wc -l < "$ROOT/include/x86/fsp/FspmUpd.h")" -gt 1000 ] && echo TGL || echo QEMU)" + else + echo " (absent)" + fi +} + +[ $# -ge 1 ] || usage +case "$1" in + save) [ $# -eq 2 ] || usage; check_set "$2"; do_save "$2" ;; + use) [ $# -eq 2 ] || usage; check_set "$2"; do_use "$2" ;; + show) do_show ;; + *) usage ;; +esac diff --git a/tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh b/tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh new file mode 100755 index 00000000..c113e0f0 --- /dev/null +++ b/tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# +# Extract FSP-T/M/S and microcode from a 68INT6 BIOS image and rebase them +# to the .config addresses (the public TGL_IOT FSP does not train this board). +# +# Usage: tools/scripts/x86_fsp/tgl/nai_extract_fsp.sh <68INT6_bios_image.bin> + +set -eu + +IMG=${1:?usage: $0 } +WORK_DIR=/tmp/tgl_fsp +EDK2_COMMIT_ID=df25a5457f04ec465dce97428cfee96f462676e7 +FSP_TOOL_URL=https://github.com/tianocore/edk2/raw/${EDK2_COMMIT_ID}/IntelFsp2Pkg/Tools/SplitFspBin.py +SCRIPT_DIR=$(readlink -f "$(dirname "$0")") +WOLFBOOT_DIR="${SCRIPT_DIR}/../../../.." +CFG="${WOLFBOOT_DIR}/.config" + +[ -f "$IMG" ] || { echo "error: image not found: $IMG" >&2; exit 1; } +[ -f "$CFG" ] || { echo "error: no .config in ${WOLFBOOT_DIR}; copy config/examples/nai_68int6.config there first" >&2; exit 1; } + +cfgval() { grep -E "^$1=" "$CFG" | tail -1 | cut -d= -f2 | tr -d ' '; } +FSP_T_BASE=$(cfgval FSP_T_BASE) +FSP_M_BASE=$(cfgval FSP_M_BASE) +FSP_S_LOAD_BASE=$(cfgval FSP_S_LOAD_BASE) +for v in FSP_T_BASE FSP_M_BASE FSP_S_LOAD_BASE; do + [ -n "${!v}" ] || { echo "error: $v not set in .config" >&2; exit 1; } +done + +mkdir -p "$WORK_DIR" +if [ ! -f "$WORK_DIR/SplitFspBin.py" ]; then + echo "fetching SplitFspBin.py (edk2 ${EDK2_COMMIT_ID:0:12})" + curl -sL -o "$WORK_DIR/SplitFspBin.py" "$FSP_TOOL_URL" +fi + +# Locate FSP-T/M/S by their FSP_INFO_HEADER (type = ComponentAttribute bits +# 15:12; the FV starts 0x94 before the header, inner FV for FSP-S). +python3 - "$IMG" "$WORK_DIR" <<'PY' +import struct, sys +img = open(sys.argv[1], 'rb').read() +work = sys.argv[2] +names = {1: 'T', 2: 'M', 3: 'S'} +found = {} +i = 0 +while True: + i = img.find(b'FSPH', i) + if i < 0: + break + hlen = struct.unpack_from('> 12) & 0xF) + if kind and imgid.strip(b'\0') and 0 < imgsize < 0x200000: + fv = i - 0x94 + found.setdefault(kind, (fv, imgsize, imgid, imgbase, imgrev)) + i += 4 +for k in 'TMS': + if k not in found: + print("error: FSP-%s not found in image" % k); sys.exit(1) + fv, size, imgid, base, rev = found[k] + open("%s/NAI_FSP_%s.fd" % (work, k), 'wb').write(img[fv:fv + size]) + print(" FSP-%s %-9r rev %X.%X.%X.%X at 0x%08X size 0x%06X linked at 0x%08X" + % (k, imgid, (rev >> 24) & 0xFF, (rev >> 16) & 0xFF, (rev >> 8) & 0xFF, rev & 0xFF, fv, size, base)) + +# Newest microcode for this CPU from the same image. +best = None +for off in range(0, len(img) - 48, 16): + if struct.unpack_from(' 0x40000 or off + tsz > len(img): + continue + blob = img[off:off + tsz] + if sum(struct.unpack_from('<%dI' % (tsz // 4), blob)) & 0xFFFFFFFF: + continue + if best is None or urev > best[0]: + best = (urev, date, blob) +if best is None: + print("error: no valid 06-8c-01 microcode found in image"); sys.exit(1) +urev, date, blob = best +open("%s/NAI_ucode0.bin" % work, 'wb').write(blob) +print(" ucode 06-8c-01 rev 0x%02X date %08X %d bytes" % (urev, date, len(blob))) +PY + +rebase() { + local c=$1 base=$2 + (cd "$WORK_DIR" && python3 SplitFspBin.py rebase -f "NAI_FSP_${c}.fd" -b "$base" \ + -c "${c,,}" -o . -n "NAI_FSP_${c}_rebased.fd" >/dev/null) + cp "$WORK_DIR/NAI_FSP_${c}_rebased.fd" "${WOLFBOOT_DIR}/src/x86/fsp_${c,,}.bin" + echo " FSP-$c rebased to $base -> src/x86/fsp_${c,,}.bin" +} +rebase T "$FSP_T_BASE" +rebase M "$FSP_M_BASE" +rebase S "$FSP_S_LOAD_BASE" +cp "$WORK_DIR/NAI_ucode0.bin" "${WOLFBOOT_DIR}/src/x86/ucode0.bin" +echo " microcode -> src/x86/ucode0.bin" +echo +echo "Done. Snapshot it: tools/scripts/x86_fsp/select_fsp.sh save nai" diff --git a/tools/unit-tests/unit-kontron-tgl-spi.c b/tools/unit-tests/unit-kontron-tgl-spi.c index 13c984b5..12c02211 100644 --- a/tools/unit-tests/unit-kontron-tgl-spi.c +++ b/tools/unit-tests/unit-kontron-tgl-spi.c @@ -39,7 +39,7 @@ typedef uintptr_t haladdr_t; #define MMIO_BASE 0xFED40000UL /* SPI PCI device constants + register offsets from - * hal/kontron_vx3060_s2.c (extracted by the Makefile). */ + * hal/x86_fsp_tgl.c (extracted by the Makefile). */ #include "kontron_spi_extract.h" /* TGL register offsets used by the model. */ @@ -122,7 +122,7 @@ static uint32_t mmio_read32(uintptr_t address) } /* The real tgl_lock_bios_region() + hal_flash_protect() from - * hal/kontron_vx3060_s2.c (extracted). */ + * hal/x86_fsp_tgl.c (extracted). */ #include "kontron_spi_fn_extract.h" /* The lock must land in the MMIO space: FPR0 carries the FREG1