Merge pull request #443 from wolfSSL/x86_fsp_backport

x86 fsp backport
pull/450/head
David Garske 2024-05-09 07:46:56 -07:00 committed by GitHub
commit 027c6847e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
71 changed files with 3062 additions and 684 deletions

View File

@ -0,0 +1,23 @@
name: X86 FSP QEMU test
on:
pull_request:
branches: [ '*' ]
jobs:
fsp_qemu_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: install req
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y -q nasm gcc-multilib qemu-system-x86 swtpm
- name: setup git
run: |
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
- name: run test
run: |
./tools/scripts/x86_fsp/qemu/test_qemu.sh

11
.gitignore vendored
View File

@ -132,6 +132,8 @@ CMakeCache.txt
# Stage 1
stage1/loader_stage1.ld
hal/x86_fsp_tgl_stage1.ld
hal/x86_fsp_qemu_stage1.ld
debug/lauterbach
@ -177,3 +179,12 @@ IDE/Renesas/e2studio/RZN2L/wolfboot/.secure_azone
IDE/Renesas/e2studio/RZN2L/wolfboot/.secure_xml
IDE/Renesas/e2studio/RZN2L/wolfboot/configuration.xml
tpm_seal_key.key
# FSP downloaded headers
include/x86/fsp/FspUpd.h
include/x86/fsp/FspmUpd.h
include/x86/fsp/FspsUpd.h
include/x86/fsp/FsptUpd.h
include/x86/fsp/MemInfoHob.h

17
arch.mk
View File

@ -671,6 +671,7 @@ endif
ifeq ($(filter $(TARGET),x86_fsp_qemu kontron_vx3060_s2),$(TARGET))
FSP=1
CFLAGS+=-DWOLFBOOT_FSP=1
CFLAGS+=-ffunction-sections -fdata-sections
ifeq ($(TARGET), kontron_vx3060_s2)
FSP_TGL=1
CFLAGS+=-DWOLFBOOT_TGL=1
@ -697,11 +698,11 @@ ifeq ("${FSP}", "1")
LSCRIPT_IN = ../hal/$(TARGET)_stage1.ld
endif
# using ../wolfboot.map as stage1 is built from stage1 sub-directory
LDFLAGS = --defsym main=`grep main ../wolfboot.map | awk '{print $$1}'` \
--defsym wb_start_bss=`grep _start_bss ../wolfboot.map | awk '{print $$1}'` \
--defsym wb_end_bss=`grep _end_bss ../wolfboot.map | awk '{print $$1}'` \
--defsym _stage2_params=`grep _stage2_params ../wolfboot.map | awk '{print $$1}'`
LDFLAGS += --no-gc-sections --print-gc-sections -T $(LSCRIPT) -m elf_i386 -Map=loader_stage1.map
LDFLAGS = --defsym main=0x`nm ../wolfboot.elf | grep -w main | awk '{print $$1}'` \
--defsym wb_start_bss=0x`nm ../wolfboot.elf | grep -w _start_bss | awk '{print $$1}'` \
--defsym wb_end_bss=0x`nm ../wolfboot.elf | grep -w _end_bss | awk '{print $$1}'` \
--defsym _stage2_params=0x`nm ../wolfboot.elf | grep -w _stage2_params | awk '{print $$1}'`
LDFLAGS += --gc-sections --entry=reset_vector -T $(LSCRIPT) -m elf_i386 -Map=loader_stage1.map
OBJS += src/boot_x86_fsp.o
OBJS += src/boot_x86_fsp_start.o
OBJS += src/fsp_m.o
@ -713,6 +714,7 @@ ifeq ("${FSP}", "1")
OBJS += src/pci.o
OBJS += hal/x86_uart.o
OBJS += src/string.o
OBJS += src/stage2_params.o
ifeq ($(filter-out $(STAGE1_AUTH),1),)
OBJS += src/libwolfboot.o
OBJS += src/image.o
@ -729,7 +731,6 @@ ifeq ("${FSP}", "1")
CFLAGS += -fno-stack-protector -m32 -fno-PIC -fno-pie -mno-mmx -mno-sse -DDEBUG_UART
ifeq ($(FSP_TGL), 1)
OBJS+=src/x86/tgl_fsp.o
OBJS+=src/fsp_tgl_s_upd.o
OBJS+=src/ucode0.o
CFLAGS += -DUCODE0_ADDRESS=$(UCODE0_BASE)
endif
@ -743,7 +744,7 @@ ifeq ("${FSP}", "1")
else
LSCRIPT_IN = hal/$(TARGET).ld.in
endif
LDFLAGS = --no-gc-sections --print-gc-sections -T $(LSCRIPT) -Map=wolfboot.map
LDFLAGS = --gc-sections --entry=main -T $(LSCRIPT) -Map=wolfboot.map
CFLAGS += -fno-stack-protector -fno-PIC -fno-pie -mno-mmx -mno-sse -Os -DDEBUG_UART
OBJS += hal/x86_fsp_tgl.o
OBJS += hal/x86_uart.o
@ -755,6 +756,8 @@ ifeq ("${FSP}", "1")
OBJS += src/x86/ata.o
OBJS += src/x86/gpt.o
OBJS += src/x86/mptable.o
OBJS += src/stage2_params.o
OBJS += src/x86/exceptions.o
UPDATE_OBJS := src/update_disk.o
ifeq ($(64BIT),1)
LDFLAGS += -m elf_x86_64 --oformat elf64-x86-64

View File

@ -1,7 +1,7 @@
ARCH=x86_64
TARGET=kontron_vx3060_s2
WOLFBOOT_SMALL_STACK=0
SIGN=ECC256
SIGN=ECC384
HASH=SHA256
DEBUG=1
SPMATH=1
@ -14,9 +14,8 @@ WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff400000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0
# 128mb
WOLFBOOT_LOAD_BASE=0x8000000
WOLFBOOT_LOAD_ADDRESS=0x1000000
# 1408mb + 0x200 (For the header)
WOLFBOOT_LOAD_BASE=0x58000200
# required for keytools
WOLFBOOT_SECTOR_SIZE?=0x1000
@ -24,7 +23,6 @@ WOLFBOOT_DATA_ADDRESS=0x1000000
FSP_S_BASE=0xffea0000
FSP_S_UPD_DATA_BASE=0xffd00000
FSP_T_BASE=0xfff59000
FSP_M_BASE=0xfff60000
@ -59,8 +57,10 @@ MULTIBOOT2=1
FSP_S_LOAD_BASE=0x0FED5F00
STAGE1_AUTH=1
# MEASURED_BOOT=1
# MEASURED_PCR_A=0
# DISK_LOCK=1
# WOLFTPM=1
# WOLFBOOT_TPM_SEAL=1
MEASURED_BOOT=1
MEASURED_PCR_A=0
DISK_LOCK=0
WOLFTPM=1
WOLFBOOT_TPM_SEAL=1
WOLFBOOT_TPM_SEAL_KEY_ID=1
WOLFBOOT_UNIVERSAL_KEYSTORE=1

View File

@ -1,8 +1,8 @@
ARCH=x86_64
TARGET=x86_fsp_qemu
WOLFBOOT_SMALL_STACK=1
SIGN?=ECC384
HASH?=SHA384
SIGN=ECC256
HASH=SHA256
DEBUG=1
SPMATH=1
FORCE_32BIT=1
@ -16,9 +16,6 @@ WOLFTPM=0
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
# 4gb - 8mb
WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff800000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0
WOLFBOOT_LOAD_BASE=0x2000000
WOLFBOOT_LOAD_ADDRESS=0x1000000
@ -30,13 +27,15 @@ FSP_M_BASE=0xffe30000
FSP_S_BASE=0xffed6000
FSP_T_BASE=0xfffe0000
FSP_S_LOAD_BASE=0x0FED5F00
WOLFBOOT_ORIGIN=0xfffa0000
LINUX_PAYLOAD=1
WOLFBOOT_ORIGIN=0xfff80000
BOOTLOADER_PARTITION_SIZE=0xa0000
BOOTLOADER_PARTITION_SIZE=0xe0000
BIOS_REGION_SIZE=0x800000
MACHINE_OBJ=src/x86/qemu_fsp.o
FSP_T_BIN=./src/x86/fsp_t.bin
FSP_M_BIN=./src/x86/fsp_m.bin
FSP_S_BIN=./src/x86/fsp_s.bin
STAGE1_AUTH=1
64BIT=1
ELF=1
MULTIBOOT2=1

View File

@ -1,20 +1,14 @@
ARCH=x86_64
TARGET=x86_fsp_qemu
WOLFBOOT_SMALL_STACK=0
SIGN?=ECC256
HASH?=SHA256
SIGN=ECC384
HASH=SHA256
DEBUG=1
SPMATH=1
FORCE_32BIT=1
ENCRYPTION=0
WOLFBOOT_NO_PARTITIONS=1
WOLFTPM=1
# Measured boot
MEASURED_BOOT=1
MEASURED_PCR_A=0
WOLFBOOT_TPM_SEAL=1
DISK_LOCK=1
# TPM Keystore options
#WOLFBOOT_TPM_KEYSTORE?=1
@ -22,9 +16,6 @@ DISK_LOCK=1
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
# 4gb - 8mb
WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff800000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0
WOLFBOOT_LOAD_BASE=0x2000000
WOLFBOOT_LOAD_ADDRESS=0x1000000
@ -36,13 +27,22 @@ FSP_M_BASE=0xffe30000
FSP_S_BASE=0xffed6000
FSP_T_BASE=0xfffe0000
FSP_S_LOAD_BASE=0x0FED5F00
WOLFBOOT_ORIGIN=0xfff90000
LINUX_PAYLOAD=1
WOLFBOOT_ORIGIN=0xfff80000
BOOTLOADER_PARTITION_SIZE=0xb0000
BOOTLOADER_PARTITION_SIZE=0xe0000
BIOS_REGION_SIZE=0x800000
MACHINE_OBJ=src/x86/qemu_fsp.o
FSP_T_BIN=./src/x86/fsp_t.bin
FSP_M_BIN=./src/x86/fsp_m.bin
FSP_S_BIN=./src/x86/fsp_s.bin
STAGE1_AUTH=1
64BIT=1
ELF=1
MULTIBOOT2=1
MEASURED_BOOT=1
MEASURED_PCR_A=0
WOLFBOOT_TPM_SEAL=1
WOLFBOOT_TPM_SEAL_KEY_ID=1
DISK_LOCK=1
WOLFBOOT_UNIVERSAL_KEYSTORE=1

View File

@ -1,42 +0,0 @@
ARCH=x86_64
TARGET=x86_fsp_qemu
WOLFBOOT_SMALL_STACK=1
SIGN?=ECC256
HASH?=SHA256
DEBUG=1
SPMATH=1
FORCE_32BIT=1
ENCRYPTION=0
WOLFBOOT_NO_PARTITIONS=1
WOLFTPM=0
# TPM Keystore options
#WOLFBOOT_TPM_KEYSTORE?=1
#WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
#WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
# 4gb - 8mb
WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff800000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0
WOLFBOOT_LOAD_BASE=0x2000000
WOLFBOOT_LOAD_ADDRESS=0x1000000
# required for keytools
WOLFBOOT_SECTOR_SIZE?=0x1000
WOLFBOOT_DATA_ADDRESS=0x1000000
FSP_M_BASE=0xffe30000
FSP_S_BASE=0xffed6000
FSP_T_BASE=0xfffe0000
FSP_S_LOAD_BASE=0x0FED5F00
WOLFBOOT_ORIGIN=0xfffa0000
LINUX_PAYLOAD=1
BOOTLOADER_PARTITION_SIZE=0xa0000
BIOS_REGION_SIZE=0x800000
MACHINE_OBJ=src/x86/qemu_fsp.o
FSP_T_BIN=./src/x86/fsp_t.bin
FSP_M_BIN=./src/x86/fsp_m.bin
FSP_S_BIN=./src/x86/fsp_s.bin
STAGE1_AUTH=1

View File

@ -1,40 +0,0 @@
ARCH=x86_64
TARGET=x86_fsp_qemu
WOLFBOOT_SMALL_STACK=1
SIGN?=ECC256
HASH?=SHA256
DEBUG=1
SPMATH=1
FORCE_32BIT=1
ENCRYPTION=0
WOLFBOOT_NO_PARTITIONS=1
WOLFTPM=1
# TPM Keystore options
WOLFBOOT_TPM_KEYSTORE?=1
WOLFBOOT_TPM_KEYSTORE_NV_BASE?=0x01800200
WOLFBOOT_TPM_POLICY_NV_INDEX?=0x01800201
# 4gb - 8mb
WOLFBOOT_PARTITION_BOOT_ADDRESS=0xff800000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x0
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x0
WOLFBOOT_LOAD_BASE=0x2000000
WOLFBOOT_LOAD_ADDRESS=0x1000000
# required for keytools
WOLFBOOT_SECTOR_SIZE?=0x1000
WOLFBOOT_DATA_ADDRESS=0x1000000
FSP_M_BASE=0xffe30000
FSP_S_BASE=0xffed6000
FSP_T_BASE=0xfffe0000
BOOTLOADER_START=0xffff0000
LINUX_PAYLOAD=1
BOOTLOADER_PARTITION_SIZE=0xa0000
BIOS_REGION_SIZE=0x800000
MACHINE_OBJ=src/x86/qemu_fsp.o
FSP_T_BIN=./src/x86/fsp_t.bin
FSP_M_BIN=./src/x86/fsp_m.bin
FSP_S_BIN=./src/x86/fsp_s.bin

View File

@ -2198,56 +2198,60 @@ The following variables must be set in your `.config` file when using this featu
- `WOLFBOOT_LOAD_BASE`: the address where wolfboot will be loaded in RAM after the first initialization phase
While Intel FSP aims to abstract away specific machine details, you still need
some machine-specific code. In the next section we show how to retrieve the
target-specific code for qemu. Refer to the Intel Integration Guide of the selected
silicon for more information.
some machine-specific code. Current supported targets are QEMU and the TigerLake based Kontron VX3060-S2 board.
Refer to the Intel Integration Guide of the selected silicon for more information.
Note:
- This feature requires `NASM` to be installed on the machine building wolfBoot.
### Running on 64-bit Qemu
### Running on 64-bit QEMU
An example configuration file is available in `config/examples/x86_fsp_qemu.config`.
Two example configuration files are available: `config/examples/x86_fsp_qemu.config` and `config/examples/x86_fsp_qemu_seal.config`.
Both will try to load a 64bit ELF/Multiboot2 payload from the emulated sata drive.
The second one is an example of configuration that also do measure boot and seal/unseal secrets using a TPM.
A test ELF/Multiboot2 image is provided as well. To test `config/examples/x86_fsp_qemu.config` use the following steps:
Assuming that you have compiled a linux kernel that can boot on qemu, you can verify
and stage it by running the following commands:
```
# Copy the example configuration for this target
cp config/examples/x86_fsp_qemu.config .config
# Create necessary Intel FSP binaries from edk2 repo
tools/x86_fsp/qemu/qemu_build_fsp.sh
./tools/scripts/x86_fsp/qemu/qemu_build_fsp.sh
# build wolfboot
make
# The next script needs to be run from wolboot root folder and assumes your
# kernel is in th root folder, named bzImage
# If this is not the case, change the path in the script accordingly
tools/x86_fsp/qemu/make_hd.sh
# make test-app
make test-app/image.elf
# Run wolfBoot + Linux in qemu
tools/scripts/qemu64/qemu64.sh
# make_hd.sh sign the image, creates a file-based hard disk image with GPT table and raw partitions and then copies the signed images into the partitions.
IMAGE=test-app/image.elf tools/scripts/x86_fsp/qemu/make_hd.sh
# run wolfBoot + test-image
./tools/scripts/x86_fsp/qemu/qemu.sh
```
#### Sample boot output
#### Sample boot output using config/examples/x86_fsp_qemu.config
```
Cache-as-RAM initialized
FSP-T:0.0.10 build 0
FSP-M:0.0.10 build 0
no microcode for QEMU target
calling FspMemInit...
============= FSP Spec v2.0 Header Revision v3 ($QEMFSP$ v0.0.10.0) =============
Fsp BootFirmwareVolumeBase - 0xFFE30000
Fsp BootFirmwareVolumeSize - 0x22000
Fsp TemporaryRamBase - 0x4
Fsp TemporaryRamSize - 0x20000
Fsp TemporaryRamSize - 0x50000
Fsp PeiTemporaryRamBase - 0x4
Fsp PeiTemporaryRamSize - 0x14CCC
Fsp StackBase - 0x14CD0
Fsp StackSize - 0xB334
Fsp PeiTemporaryRamSize - 0x34000
Fsp StackBase - 0x34004
Fsp StackSize - 0x1C000
Register PPI Notify: DCD0BE23-9586-40F4-B643-06522CED4EDE
Install PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
Install PPI: 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
@ -2273,15 +2277,15 @@ Install PPI: 7408D748-FC8C-4EE6-9288-C4BEC092A410
Register PPI Notify: F894643D-C449-42D1-8EA8-85BDD8C65BDE
PeiInstallPeiMemory MemoryBegin 0x3EF00000, MemoryLength 0x100000
FspmInitPoint() - End
Temp Stack : BaseAddress=0x14CD0 Length=0xB334
Temp Heap : BaseAddress=0x4 Length=0x14CCC
Total temporary memory: 131072 bytes.
Temp Stack : BaseAddress=0x34004 Length=0x1C000
Temp Heap : BaseAddress=0x4 Length=0x34000
Total temporary memory: 327680 bytes.
temporary memory stack ever used: 3360 bytes.
temporary memory heap used for HobList: 2104 bytes.
temporary memory heap occupied by memory pages: 0 bytes.
Old Stack size 45876, New stack size 131072
Old Stack size 114688, New stack size 131072
Stack Hob: BaseAddress=0x3EF00000 Length=0x20000
Heap Offset = 0x3EF1FFFC Stack Offset = 0x3EEFFFFC
Heap Offset = 0x3EF1FFFC Stack Offset = 0x3EECFFFC
Loading PEIM 52C05B14-0B98-496C-BC3B-04B50211D680
Loading PEIM at 0x0003EFF5150 EntryPoint=0x0003EFFBBC6 PeiCore.efi
Reinstall PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
@ -2291,19 +2295,34 @@ Install PPI: F894643D-C449-42D1-8EA8-85BDD8C65BDE
Notify: PPI Guid: F894643D-C449-42D1-8EA8-85BDD8C65BDE, Peim notify entry point: FFE40AB2
Memory Discovered Notify invoked ...
FSP TOLM = 0x3F000000
Migrate FSP-M UPD from 7F548 to 3EFF4000
Migrate FSP-M UPD from 7F540 to 3EFF4000
FspMemoryInitApi() - [Status: 0x00000000] - End
success
top reserved 0_3EF00000h
mem: [ 0x3EEF0000, 0x3EF00000 ] - stack (0x10000)
mem: [ 0x3EEEFFF4, 0x3EEF0000 ] - stage2 parameter (0xC)
hoblist@0x3EF20000
mem: [ 0x3EEE8000, 0x3EEEFFF4 ] - page tables (0x7FF4)
page table @ 0x3EEE8000 [length: 7000]
mem: [ 0x3EEE7FF8, 0x3EEE8000 ] - stage2 ptr holder (0x8)
TOLUM: 0x3EEE7FF8
TempRamExitApi() - Begin
Memory Discovered Notify completed ...
TempRamExitApi() - [Status: 0x00000000] - End
mem: [ 0x800000, 0x800084 ] - stage1 .data (0x84)
mem: [ 0x8000A0, 0x801A80 ] - stage1 .bss (0x19E0)
mem: [ 0xFED5E00, 0xFEEAF00 ] - FSPS (0x15100)
Authenticating FSP_S at FED5E00...
Image size 86016
verify_payload: image open successfully.
verify_payload: integrity OK. Checking signature.
FSP_S: verified OK.
FSP-S:0.0.10 build 0
call silicon...
SiliconInitApi() - Begin
Install PPI: 49EDB1C1-BF21-4761-BB12-EB0031AABB39
Notify: PPI Guid: 49EDB1C1-BF21-4761-BB12-EB0031AABB39, Peim notify entry point: FFE370A2
The 1th FV start address is 0x000FFED6000, size is 0x00015000, handle is 0xFFED6000
The 1th FV start address is 0x0000FED5F00, size is 0x00015000, handle is 0xFED5F00
DiscoverPeimsAndOrderWithApriori(): Found 0x4 PEI FFS files in the 1th FV
Loading PEIM 86D70125-BAA3-4296-A62F-602BEBBB9081
Loading PEIM at 0x0003EFEE150 EntryPoint=0x0003EFF15B9 DxeIpl.efi
@ -2335,6 +2354,11 @@ FspInitEndOfPeiCallback--
FSP is waiting for NOTIFY
FspSiliconInitApi() - [Status: 0x00000000] - End
success
pcie retraining failed FFFFFFFF
cap a 0
ddt disabled 0
device enable: 0
device enable: 128
NotifyPhaseApi() - Begin [Phase: 00000020]
FSP Post PCI Enumeration ...
Install PPI: 30CFE3E7-3DE1-4586-BE20-DEABA1B3B793
@ -2357,8 +2381,15 @@ FspEndOfFirmwareCallback++
FspEndOfFirmwareCallback--
NotifyPhaseApi() - End [Status: 0x00000000]
CPUID(0):D 68747541 444D4163
loading wolfboot at 2000000...
mem: [ 0x1FFFF00, 0x200CC70 ] - wolfboot (0xCD70)
mem: [ 0x200CC70, 0x222FA00 ] - wolfboot .bss (0x222D90)
load wolfboot end
Authenticating wolfboot at 2000000...
Image size 52336
verify_payload: image open successfully.
verify_payload: integrity OK. Checking signature.
wolfBoot: verified OK.
starting wolfboot 64bit
AHCI port 0: No disk detected
AHCI port 1: No disk detected
AHCI port 2: No disk detected
@ -2381,46 +2412,95 @@ Total partitions on disk0: 2
Checking primary OS image in 0,0...
Checking secondary OS image in 0,1...
Versions, A:1 B:2
Load address 0x222FA00
Attempting boot from partition B
Image size 11982512
Firmware Valid
Booting at 5000100
linux payload
mem: [ 0x222FA00, 0x2241DC8 ] - ELF (0x123C8)
Loading image from disk...done.
Image size 74696
Checking image integrity...done.
Verifying image signature...done.
Firmware Valid.
Booting at 222FB00
mem: [ 0x100, 0x1E0 ] - MPTABLE (0xE0)
Loading elf at 0x222FB00
Found valid elf64 (little endian)
Program Headers 7 (size 56)
Load 504 bytes (offset 0x0) to 0x400000 (p 0x400000)
Load 3999 bytes (offset 0x1000) to 0x401000 (p 0x401000)
Load 1952 bytes (offset 0x2000) to 0x402000 (p 0x402000)
Load 32 bytes (offset 0x3000) to 0x403000 (p 0x403000)
Entry point 0x401000
Elf loaded (ret 0), entry 0x0_401000
mb2 header found at 2232B00
booting...
Linux version 5.17.15 (arch@wb-hg-2) (x86_64-linux-gcc.br_real (Buildroot toolchains.bootlin.com-2021.11-5) 11.2.0, GNU ld (GNU Binutils) 2.37) #24 PREEMPT Wed May 17 13:47:24 UTC 2023
wolfBoot QEMU x86 FSP test app
```
### Running on 64-bit Qemu with swtpm (TPM emulator)
### Running on QEMU with swtpm (TPM emulator)
The example configuration for this setup can be found in
`config/examples/x86_fsp_qemu_tpm.config`.
First step: [clone and install swtpm](https://github.com/stefanberger/swtpm), a
TPM emulator that can be connected to qemu guest VMs. This TPM emulator will
create a memory-mapped I/O device.
First step: [clone and install swtpm](https://github.com/stefanberger/swtpm), a TPM emulator that can be connected to qemu
guest VMs. This TPM emulator will create a memory-mapped I/O device.
The other steps to follow are:
A small note is that `config/examples/x86_fsp_qemu_seal.config` showcases two
different key ecc size of 384 and 256 of authentication for image verification
and TPM sealing respectively.
The correct steps to run the example:
```
# Copy the example configuration for this target
cp config/examples/x86_fsp_qemu_tpm.config .config
# copy the example configuration for this target
cp config/examples/x86_fsp_qemu_seal.config .config
# Create necessary Intel FSP binaries from edk2 repo
tools/x86_fsp/qemu/qemu_build_fsp.sh
# create necessary Intel FSP binaries from edk2 repo
tools/scripts/x86_fsp/qemu/qemu_build_fsp.sh
# Compile wolfBoot and assemble the loader image
make
# make keytools and tpmtools
make keytools
make tpmtools
# The next script needs to be run from wolboot root folder and assumes your
# kernel is in wolfBoot's root folder. The file should be named `bzImage`.
# If this is not the case, change the path in the script accordingly
# create two keys, one for signing the images (ecc384) and one to seal/unseal secret into the TPM (ecc256)
./tools/keytools/keygen --force --ecc384 -g wolfboot_signing_private_key.der --ecc256 -g tpm_seal_key.key
tools/x86_fsp/qemu/make_hd.sh
# build wolfboot, manually add ECC256 for TPM
make CFLAGS_EXTRA="-DHAVE_ECC256"
# Run wolfBoot + linux in qemu, with swTPM connected to the guest machine.
# The script will start the TPM emulator before launching the VM.
tools/scripts/qemu64/qemu64-tpm.sh
# compute the value of PCR0 to sign with TPM key
PCR0=$(python ./tools/scripts/x86_fsp/compute_pcr.py --target qemu wolfboot_stage1.bin | tail -n 1)
# sign the policy
./tools/tpm/policy_sign -ecc256 -key=tpm_seal_key.key -pcr=0 -pcrdigest=$PCR0
# install the policy
./tools/scripts/x86_fsp/tpm_install_policy.sh policy.bin.sig
# make test-app
make test-app/image.elf
# make_hd.sh sign the image, creates a file-based hard disk image with GPT table and raw partitions and then copy the signed images into the partitions.
IMAGE=test-app/image.elf SIGN=--ecc384 tools/scripts/x86_fsp/qemu/make_hd.sh
# run wolfBoot + test-image, use -t to emulate a TPM (requires swtpm)
./tools/scripts/x86_fsp/qemu/qemu.sh -t
```
For more advanced uses of TPM, please check [TPM.md](TPM.md) to configure wolfBoot
according to your secure boot strategy.
### Running on Kontron VX3060-S2
A reference configuration and helper scripts are provided to run wolfBoot on
Kontron VX3060-S2 board.
A flash dump of the original Flash BIOS is needed.
To compile a flashable image run the following steps:
```
cp config/examples/kontron_vx3060_s2.config .config
./tools/scripts/x86_fsp/tgl/tgl_download_fsp.sh
make tpmtools
./tools/scripts/x86_fsp/tgl/assemble_image.sh -k
make CFLAGS_EXTRA="-DHAVE_ECC256"
./tools/scripts/x86_fsp/tgl/assemble_image.sh -n /path/to/original/flash/dump
```
they produce a file named `final_image.bin` inside the root folder of the
repository that can be directly flashed into the BIOS flash of the board.

View File

@ -0,0 +1,44 @@
# ATA Security
## Introduction
This document provides an overview of how wolfBoot can leaverage the ATA security features to lock or unlock ATA drive.
The ATA drive may be locked either by using a hardcoded password or by using a secret that is sealed in the TPM.
## Table of Contents
- [ATA Security](#ata-security)
- [Introduction](#introduction)
- [Table of Contents](#table-of-contents)
- [Unlocking the Disk with a Hardcoded Password](#unlocking-the-disk-with-a-hardcoded-password)
- [Unlocking the Disk with a TPM-Sealed Secret](#unlocking-the-disk-with-a-tpm-sealed-secret)
- [Disabling the password](#disabling-the-password)
## Unlocking the Disk with a Hardcoded Password
To unlock the disk using a hardcoded password, use the following options in your .config file:
```
DISK_LOCK=1
DISK_LOCK_PASSWORD=hardcoded_password
```
If the ATA disk has no password set, the disk will be locked with the password provided at the first boot.
## Unlocking the Disk with a TPM-Sealed Secret
wolfBoot allows to seal secret safely in the TPM in a way that it can be unsealed only under specific conditions. Please refer to files TPM.md and measured_boot.md for more information.
If the options `WOLFBOOT_TPM_SEAL` and `DISK_LOCK` are enabled, wolfBoot will use a TPM sealed secret as the password to unlock the disk. The following options controls the sealing and unsealing of the secret:
| Option | Description |
|--------|-------------|
| WOLFBOOT_TPM_SEAL_KEY_ID| The key ID to use for sign the policy |
| ATA_UNLOCK_DISK_KEY_NV_INDEX | The NV index to store the sealed secret. |
| WOLFBOOT_DEBUG_REMOVE_SEALED_ON_ERROR| In case of error, delete the secret and panic() |
In case there are no secret sealed at `ATA_UNLOCK_DISK_KEY_NV_INDEX`, a new random secret will be created and sealed at that index.
In case the ATA drive is not locked, it will be locked at the first boot with the secret sealed in the TPM.
## Disabling the password
If you need to disable the password, a master password should be already set on the device. Then you can use the following options to compile wolfBoot so that it will disable the password from the drive and panic:
```
WOLFBOOT_ATA_DISABLE_USER_PASSWORD=1
ATA_MASTER_PASSWORD=the_master_password
```

View File

@ -23,10 +23,66 @@
#include <stdint.h>
#include <uart_drv.h>
#include <printf.h>
#include <x86/tgl_fsp.h>
#include <pci.h>
#include <x86/common.h>
#ifdef __WOLFBOOT
#define SPI_PCI_DEV 31
#define SPI_PCI_FUN 5
#define SPI_BAR_OFF 0x10
#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 (0x48)
#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;
#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);
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
/* Flash Protected Range register has very similar layout of the Flash
* Region Register, so we can reuse it and just enable read and write
* protection
*/
reg |= (SPI_FPR_RPE) | (SPI_FPR_WPE);
pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, SPI_FPR0, reg);
/* lock down BIOS register configuration */
reg = pci_config_read32(0, SPI_PCI_DEV, SPI_PCI_FUN, SPI_BIOS_HSFSTS_CTL);
reg |= SPI_FLOCKDN;
pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, SPI_BIOS_HSFSTS_CTL, reg);
/* restore original cmd */
pci_config_write32(0, SPI_PCI_DEV, SPI_PCI_FUN, PCI_COMMAND_OFFSET, spi_cmd);
return 0;
}
void hal_init(void)
{
}

View File

@ -24,7 +24,7 @@ SECTIONS
{
_wolfboot_flash_start = .;
KEEP(*(.sig_wolfboot_raw*))
*(.wolfboot)
KEEP(*(.wolfboot))
_wolfboot_flash_end = .;
} > FLASH
@ -41,7 +41,7 @@ SECTIONS
.keystore KEYSTORE_START :
{
_start_keystore = .;
*(.keystore*)
KEEP(*(.keystore*))
} > FLASH
.jmpto32 BOOTLOADER_JUMP32_START :
@ -60,7 +60,6 @@ SECTIONS
KEEP(*(.boot*))
*(.text*)
*(.rodata*)
*(.eh_frame*)
. = ALIGN(256);
} > FLASH
@ -90,7 +89,7 @@ SECTIONS
AT(FSP_T_ORIGIN)
{
_start_fsp_t = .;
*(.fsp_t)
KEEP(*(.fsp_t))
}
.fsp_s FSP_S_ORIGIN :
@ -98,14 +97,14 @@ SECTIONS
_fsp_s_hdr = .;
KEEP(*(.sig_fsp_s*))
_start_fsp_s = .;
*(.fsp_s)
KEEP(*(.fsp_s))
_end_fsp_s = .;
}
.fsp_m FSP_M_ORIGIN :
{
_start_fsp_m = .;
*(.fsp_m)
KEEP(*(.fsp_m))
_end_fsp_m = .;
}
}

View File

@ -1,6 +1,5 @@
FLASH_SIZE = @BOOTLOADER_PARTITION_SIZE@;
FLASH_START = 0x100000000 - @BOOTLOADER_PARTITION_SIZE@;
FSP_S_UPD_DATA_BASE = @FSP_S_UPD_DATA_BASE@;
UCODE0_BASE = @UCODE0_BASE@;
FIT_TABLE = 0xffe00000;
FSP_S_ORIGIN = @FSP_S_BASE@;
@ -28,7 +27,7 @@ SECTIONS
{
_wolfboot_flash_start = .;
KEEP(*(.sig_wolfboot_raw*))
*(.wolfboot)
KEEP(*(.wolfboot))
_wolfboot_flash_end = .;
} > FLASH
@ -38,18 +37,13 @@ SECTIONS
_policy_size_u32 = .;
. += 4;
_start_policy = .;
. += MAX_POLICY_SIZE;
. += MAX_POLICY_SIZE;
_end_policy = .;
} > FLASH
.fsps_upd FSP_S_UPD_DATA_BASE :
{
KEEP(./fsp_tgl_s_upd.o(.fsps_upd))
} > FLASH
.ucode_update0 UCODE0_BASE :
{
*(.ucode0)
KEEP(*(.ucode0))
} > FLASH
.fit_table FIT_TABLE :
@ -63,19 +57,18 @@ SECTIONS
_fsp_s_hdr = .;
KEEP(*(.sig_fsp_s*))
_start_fsp_s = .;
*(.fsp_s)
KEEP(*(.fsp_s))
_end_fsp_s = .;
} > FLASH
.bootloader WOLFBOOT_ORIGIN :
{
KEEP(./tgl_fsp.o(.boot))
*(.boot*)
KEEP(*(.boot*))
KEYSTORE_START = .;
*(.keystore*)
KEEP(*(.keystore*))
*(.text*)
*(.rodata*)
*(.eh_frame*)
. = ALIGN(256);
} > FLASH
@ -106,13 +99,13 @@ SECTIONS
AT(FSP_T_ORIGIN)
{
_start_fsp_t = .;
*(.fsp_t)
KEEP(*(.fsp_t))
} > FLASH
.fsp_m FSP_M_ORIGIN :
{
_start_fsp_m = .;
*(.fsp_m)
KEEP(*(.fsp_m))
_end_fsp_m = .;
} > FLASH

View File

@ -25,7 +25,9 @@
#define PCI_VENDOR_ID_OFFSET 0x00
#define PCI_DEVICE_ID_OFFSET 0x02
#define PCI_COMMAND_OFFSET 0x04
#define PCI_COMMAND_OFFSET 0x04
#define PCI_STATUS_OFFSET 0x06
#define PCI_CAP_OFFSET 0x34
/* Programming interface, Rev. ID and class code */
#define PCI_RID_CC_OFFSET 0x08
#define PCI_HEADER_TYPE_OFFSET 0x0E
@ -69,9 +71,17 @@
#define PCI_COMMAND_SPECIAL_CYCLE (1 << 3)
#define PCI_COMMAND_BUS_MASTER (1 << 2)
#define PCI_COMMAND_MEM_SPACE (1 << 1)
#define PCI_COMMAND_IO_SPACE (1 << 0)
#define PCI_COMMAND_IO_SPACE (1 << 0)
typedef struct {
/* STATUS bits */
#define PCI_STATUS_CAP_LIST (1 << 4)
#define PCI_PCIE_CAP_ID (0x10)
#define PCIE_LINK_STATUS_OFF (0x12)
#define PCIE_LINK_CONTROL_OFF (0x10)
#define PCIE_LINK_STATUS_TRAINING (1 << 11)
#define PCIE_LINK_CONTROL_RETRAINING (1 << 5)
typedef struct {
int bus;
int device;
int function;
@ -113,6 +123,7 @@ uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info);
int pci_enum_do(void);
int pci_pre_enum(void);
void pci_dump_config_space(void);
#ifdef __cplusplus
}

View File

@ -1,4 +1,4 @@
/* stage1.h
/* stage2_params.h
*
* Copyright (C) 2023 wolfSSL Inc.
*
@ -35,8 +35,15 @@ struct stage2_parameter {
#endif
} __attribute__((packed));
/* implemented in src/boot_x86_fsp_payload.c */
struct stage2_parameter *stage2_get_parameters();
#define DUMMY_IDT_DESC_SIZE 4
struct stage2_ptr_holder {
struct stage2_parameter *ptr;
uint8_t dummy_idt[DUMMY_IDT_DESC_SIZE];
} __attribute__((packed));
struct stage2_parameter *stage2_get_parameters(void);
void stage2_set_parameters(struct stage2_parameter *p, struct stage2_ptr_holder *holder);
void stage2_copy_parameter(struct stage2_parameter *p);
#if defined(WOLFBOOT_TPM_SEAL)
int stage2_get_tpm_policy(const uint8_t **policy, uint16_t *policy_size);

View File

@ -106,6 +106,8 @@ int wolfBoot_tpm2_extend(uint8_t pcrIndex, uint8_t* hash, int line);
wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, (hash), __LINE__)
#endif /* WOLFBOOT_MEASURED_BOOT */
int wolfBoot_tpm_self_test(void);
/* debugging */
void wolfBoot_print_hexstr(const unsigned char* bin, unsigned long sz,
unsigned long maxLine);

View File

@ -132,31 +132,36 @@ extern int tolower(int c);
/* Curve */
# ifdef WOLFBOOT_SIGN_ECC256
# define HAVE_ECC256
# define FP_MAX_BITS (256 + 32)
# if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL)
# define WOLFSSL_SP_NO_384
# define WOLFSSL_SP_NO_521
# endif
# elif defined(WOLFBOOT_SIGN_ECC384)
# define HAVE_ECC384
# define FP_MAX_BITS (384 * 2)
# if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL)
# define WOLFSSL_SP_384
# define WOLFSSL_SP_NO_256
# endif
# if !defined(WOLFBOOT_TPM_PARMENC)
# define NO_ECC256
# endif
# define WOLFSSL_SP_384
# elif defined(WOLFBOOT_SIGN_ECC521)
# define HAVE_ECC521
# define FP_MAX_BITS (528 * 2)
# if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL)
# define WOLFSSL_SP_521
# define WOLFSSL_SP_NO_256
# endif
# if !defined(WOLFBOOT_TPM_PARMENC)
# define NO_ECC256
# endif
# define WOLFSSL_SP_521
# endif
/* FP MAX BITS */
# if defined(HAVE_ECC521)
# define FP_MAX_BITS ((528 * 2))
# elif defined(HAVE_ECC384)
# define FP_MAX_BITS ((384 * 2))
# elif defined(HAVE_ECC256)
# define FP_MAX_BITS ((256 + 32))
# endif
# if !defined(HAVE_ECC256) && !defined(WOLFBOOT_TPM_PARMENC)
# define NO_ECC256
# endif
# if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL)
# if !defined(HAVE_ECC521)
# define WOLFSSL_SP_NO_521
# endif
# if !defined(HAVE_ECC384)
# define WOLFSSL_SP_NO_384
# endif
# if !defined(HAVE_ECC256)
# define WOLFSSL_SP_NO_256
# endif
# endif
#endif /* WOLFBOOT_SIGN_ECC521 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC256 */

View File

@ -174,5 +174,6 @@ struct ahci_received_fis {
uint32_t ahci_enable(uint32_t bus, uint32_t dev, uint32_t fun);
void sata_enable(uint32_t base);
void sata_disable(uint32_t base);
int sata_unlock_disk(int drv, int freeze);
#endif /* AHCI_H */

View File

@ -41,10 +41,15 @@ int ata_drive_read(int drv, uint64_t start, uint32_t count, uint8_t *buf);
int ata_drive_write(int drv, uint64_t start, uint32_t count,
const uint8_t *buf);
int ata_identify_device(int drv);
int ata_security_erase_prepare(int drv);
int ata_security_erase_unit(int drv, const char *passphrase, int master);
int ata_security_set_password(int drv, int master, const char *passphrase);
int ata_security_disable_password(int drv, const char *passphrase, int master);
int ata_device_config_identify(int drv);
int ata_security_freeze_lock(int drv);
int ata_security_unlock_device(int drv, const char *passphrase);
int ata_security_unlock_device(int drv, const char *passphrase, int master);
int ata_cmd_complete_async();
/* @brief Enum with the possible state for each drive.
* See ATA/ATAPI Command Set (ATA8-ACS) section 4.7.4
@ -101,5 +106,7 @@ enum ata_security_state ata_security_get_state(int);
/* Constants for security set commands */
#define ATA_SECURITY_COMMAND_LEN (256 * 2)
#define ATA_SECURITY_PASSWORD_OFFSET (1 * 2)
#define ATA_ERR_BUSY -2
#define ATA_ERR_OP_IN_PROGRESS -3
#define ATA_ERR_OP_NOT_IN_PROGRESS -4
#endif

View File

@ -67,4 +67,5 @@ void cpuid(uint32_t eax_param,
int cpuid_is_1gb_page_supported();
void switch_to_long_mode(uint64_t *entry, uint32_t page_table);
void x86_log_memory_load(uint32_t start, uint32_t end, const char *name);
void hlt();
#endif /* COMMON_H */

View File

@ -0,0 +1,32 @@
/* exceptions.h
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H
#include <stdint.h>
int setup_interrupt_gate(int vnum, uintptr_t handler);
int setup_interrupts();
void deinit_interrupts();
void wfi();
#endif /* EXCEPTIONS_H */

View File

@ -24,4 +24,5 @@
int disk_open(int drv);
int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf);
int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf);
int disk_find_partion_by_label(int drv, const char *label);
#endif

View File

@ -34,7 +34,9 @@ ifeq ($(WOLFBOOT_TPM_SEAL),1)
ifneq ($(WOLFBOOT_TPM_SEAL_NV_BASE),)
CFLAGS+=-D"WOLFBOOT_TPM_SEAL_NV_BASE=$(WOLFBOOT_TPM_SEAL_NV_BASE)"
endif
ifneq ($(WOLFBOOT_TPM_SEAL_KEY_ID),)
CFLAGS+=-D"WOLFBOOT_TPM_SEAL_KEY_ID=$(WOLFBOOT_TPM_SEAL_KEY_ID)"
endif
ifneq ($(POLICY_FILE),)
SIGN_OPTIONS+=--policy $(POLICY_FILE)
endif
@ -779,7 +781,6 @@ ifeq ($(FSP), 1)
PCI_USE_ECAM \
PCH_PCR_BASE \
PCI_ECAM_BASE \
FSP_S_UPD_DATA_BASE \
WOLFBOOT_LOAD_BASE \
FSP_S_LOAD_BASE

View File

@ -33,7 +33,7 @@
#include <x86/paging.h>
#include <pci.h>
#include <target.h>
#include <stage1.h>
#include <stage2_params.h>
#include "wolfboot/wolfboot.h"
#include "image.h"
@ -74,7 +74,7 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw")))
/* Amount of car memory to provide to FSP-M, machine dependent, find the value
* in the integration guide */
#ifndef FSP_M_CAR_MEM_SIZE
#define FSP_M_CAR_MEM_SIZE 0x20000
#define FSP_M_CAR_MEM_SIZE 0x50000
#endif
/* offset of the header from the base image */
@ -85,6 +85,9 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw")))
#define MEMORY_4GB (4ULL * 1024 * 1024 * 1024)
#define ENDLINE "\r\n"
#define PCI_DEVICE_CONTROLLER_TO_PEX 0x6
#define PCIE_TRAINING_TIMEOUT_MS (100)
typedef uint32_t (*memory_init_cb)(void *udp, struct efi_hob **HobList);
typedef uint32_t (*temp_ram_exit_cb)(void *udp);
typedef uint32_t (*silicon_init_cb)(void *udp);
@ -95,8 +98,11 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params,
uint32_t mem_base, uint32_t mem_size);
int fsp_machine_update_s_parameters(uint8_t *default_s_params);
int post_temp_ram_init_cb(void);
int fsp_pre_mem_init_cb(void);
int fsp_pre_silicon_init_cb(void);
/* from the linker */
extern uint8_t _start_fsp_t[];
extern uint8_t _start_fsp_m[];
extern uint8_t _fsp_s_hdr[];
extern uint8_t _end_fsp_m[];
@ -110,10 +116,8 @@ extern const uint8_t _start_policy[], _end_policy[];
extern const uint32_t _policy_size_u32[];
extern const uint8_t _start_keystore[];
/* wolfboot symbols */
/* wolfboot symbol */
extern int main(void);
extern uint8_t _stage2_params[];
/*!
* \brief Get the top address from the EFI HOB (Hand-Off Block) list.
@ -150,15 +154,13 @@ static int get_top_address(uint64_t *top, struct efi_hob *hoblist)
* \param ptr Pointer to the parameter to be passed to the invoked function.
*/
static void change_stack_and_invoke(uint32_t new_stack,
void (*other_func)(void *), void *ptr)
void (*other_func)(void))
{
__asm__ volatile("movl %0, %%eax\n"
"subl $4, %%eax\n"
"movl %1, (%%eax)\n"
"mov %%eax, %%esp\n"
"call *%2\n"
"call *%1\n"
:
: "r"(new_stack), "r"(ptr), "r"(other_func)
: "r"(new_stack), "r"(other_func)
: "%eax");
}
static int range_overlaps(uint32_t start1, uint32_t end1, uint32_t start2,
@ -230,19 +232,6 @@ static void load_fsp_s_to_ram(void)
memcpy((uint8_t*)fsp_start, _fsp_s_hdr, fsp_s_size);
}
/*!
* \brief Set the stage 2 parameter for the WolfBoot bootloader.
*
* This static function sets the stage 2 parameter for the WolfBoot bootloader,
* which will be used by the bootloader during its execution.
*
* \param p Pointer to the stage 2 parameter structure.
*/
static void set_stage2_parameter(struct stage2_parameter *p)
{
memcpy((uint8_t*)_stage2_params, (uint8_t*)p, sizeof(*p));
}
#ifdef WOLFBOOT_64BIT
/*!
* \brief Jump into the WolfBoot bootloader.
@ -252,25 +241,28 @@ static void set_stage2_parameter(struct stage2_parameter *p)
*/
static void jump_into_wolfboot(void)
{
struct stage2_parameter *params = (struct stage2_parameter*)_stage2_params;
struct stage2_parameter *params;
uint32_t cr3;
int ret;
x86_log_memory_load((uint32_t)(uintptr_t)params->page_table,params->page_table + x86_paging_get_page_table_size(),
"IdentityPageTablePage");
params = stage2_get_parameters();
ret = x86_paging_build_identity_mapping(MEMORY_4GB,
(uint8_t*)(uintptr_t)params->page_table);
if (ret != 0) {
wolfBoot_printf("can't build identity mapping\r\n");
panic();
}
stage2_copy_parameter(params);
wolfBoot_printf("starting wolfboot 64bit\r\n");
switch_to_long_mode((uint64_t*)&main, params->page_table);
panic();
}
#else
static void jump_into_wolfboot()
static void jump_into_wolfboot(void)
{
struct stage2_parameter *params = stage2_get_parameters();
stage2_copy_parameter(params);
main();
}
#endif /* WOLFBOOT_64BIT */
@ -350,6 +342,133 @@ static inline void memory_init_data_bss(void)
memset(_start_bss, 0, (_end_bss - _start_bss));
}
/*!
* \brief Check if the FSP info header is valid.
*
* This static function checks if the given FSP info header is valid by verifying
* its signature.
*
* \param hdr Pointer to the FSP info header structure.
* \return 1 if the FSP info header is valid, 0 otherwise.
*/
static int fsp_info_header_is_ok(struct fsp_info_header *hdr)
{
uint8_t *raw_signature;
raw_signature = (uint8_t *)&hdr->Signature;
if (raw_signature[0] != 'F' || raw_signature[1] != 'S' ||
raw_signature[2] != 'P' || raw_signature[3] != 'H') {
return 0;
}
return 1;
}
static int fsp_get_image_revision(struct fsp_info_header *h, int *build,
int *rev, int *maj, int *min)
{
uint16_t ext_revision;
uint32_t revision;
if (!fsp_info_header_is_ok(h)) {
wolfBoot_printf("Wrong FSP Header\r\n");
return -1;
}
revision = h->ImageRevision;
*build = revision & 0xff;
*rev = (revision >> 8) & 0xff;
*min = (revision >> 16) & 0xff;
*maj = (revision >> 24) & 0xff;
if (h->HeaderRevision >= 6) {
*build = *build | ((h->ExtendedImageRevision & 0xff) << 8);
*rev = *rev | (h->ExtendedImageRevision & 0xff00);
}
return 0;
}
static void print_fsp_image_revision(struct fsp_info_header *h)
{
int build, rev, maj, min;
int r;
r = fsp_get_image_revision(h, &build, &rev, &maj, &min);
if (r != 0) {
wolfBoot_printf("failed to get fsp image revision\r\n");
return;
}
wolfBoot_printf("%x.%x.%x build %x\r\n", maj, min, rev, build);
}
static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun,
uint8_t cap_id, uint8_t *cap_off)
{
uint8_t r8, id;
uint32_t r32;
r32 = pci_config_read16(bus, dev, fun, PCI_STATUS_OFFSET);
if (!(r32 & PCI_STATUS_CAP_LIST))
return -1;
r8 = pci_config_read8(bus, dev, fun, PCI_CAP_OFFSET);
while (r8 != 0) {
id = pci_config_read8(bus, dev, fun, r8);
if (id == cap_id) {
*cap_off = r8;
return 0;
}
r8 = pci_config_read8(bus, dev, fun, r8 + 1);
}
return -1;
}
int pcie_retraining_link(uint8_t bus, uint8_t dev, uint8_t fun)
{
uint16_t link_status, link_control, vid;
uint8_t pcie_cap_off;
int ret, tries;
vid = pci_config_read16(bus, dev, 0, PCI_VENDOR_ID_OFFSET);
if (vid == 0xffff) {
return -1;
}
ret = pci_get_capability(bus, dev, fun, PCI_PCIE_CAP_ID, &pcie_cap_off);
if (ret != 0) {
return -1;
}
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
delay(PCIE_TRAINING_TIMEOUT_MS);
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
return -1;
}
}
link_control = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_CONTROL_OFF);
link_control |= PCIE_LINK_CONTROL_RETRAINING;
pci_config_write16(bus, dev, fun, pcie_cap_off + PCIE_LINK_CONTROL_OFF,
link_control);
tries = PCIE_TRAINING_TIMEOUT_MS / 10;
do {
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (!(link_status & PCIE_LINK_STATUS_TRAINING))
break;
delay(10);
} while(tries--);
if ((link_status & PCIE_LINK_STATUS_TRAINING)) {
return -1;
}
return 0;
}
/*!
* \brief Staging of FSP_S after verification
@ -373,9 +492,17 @@ static int fsp_silicon_init(struct fsp_info_header *fsp_info, uint8_t *fsp_s_bas
memcpy(silicon_init_parameter, fsp_s_base + fsp_info->CfgRegionOffset,
FSP_S_PARAM_SIZE);
status = fsp_machine_update_s_parameters(silicon_init_parameter);
fsp_info = (struct fsp_info_header *)(fsp_s_base + FSP_INFO_HEADER_OFFSET);
SiliconInit = (silicon_init_cb)(fsp_s_base + fsp_info->FspSiliconInitEntryOffset);
#if defined(WOLFBOOT_DUMP_FSP_UPD)
wolfBoot_printf("Dumping fsps upd (%d bytes)" ENDLINE, (int)fsp_info->CfgRegionSize);
wolfBoot_print_hexstr(silicon_init_parameter, fsp_info->CfgRegionSize, 16);
#endif
status = fsp_pre_silicon_init_cb();
if (status != 0) {
wolfBoot_printf("pre silicon init cb returns %d", status);
panic();
}
wolfBoot_printf("call silicon..." ENDLINE);
status = SiliconInit(silicon_init_parameter);
if (status != EFI_SUCCESS) {
@ -383,7 +510,12 @@ static int fsp_silicon_init(struct fsp_info_header *fsp_info, uint8_t *fsp_s_bas
return -1;
}
wolfBoot_printf("success" ENDLINE);
status = pcie_retraining_link(0, PCI_DEVICE_CONTROLLER_TO_PEX, 0);
if (status != 0)
wolfBoot_printf("pcie retraining failed %x\n", status);
pci_enum_do();
pci_dump_config_space();
notifyPhase = (notify_phase_cb)(fsp_s_base +
fsp_info->NotifyPhaseEntryOffset);
param.Phase = EnumInitPhaseAfterPciEnumeration;
@ -451,11 +583,9 @@ static int self_extend_pcr(void)
* This static function serves as the entry point for further execution after the
* memory initialization is completed and the stack has been remapped.
*
* \param ptr Pointer to a parameter structure.
*/
static void memory_ready_entry(void *ptr)
static void memory_ready_entry(void)
{
struct stage2_parameter *stage2_params = (struct stage2_parameter *)ptr;
struct fsp_info_header *fsp_info;
temp_ram_exit_cb TempRamExit;
uint8_t *fsp_s_base;
@ -463,6 +593,7 @@ static void memory_ready_entry(void *ptr)
uint32_t cpu_info[4];
uint32_t status;
int ret;
/* FSP_M is located in flash */
fsp_m_base = _start_fsp_m;
/* fsp_s is loaded to RAM for validation */
@ -483,14 +614,20 @@ static void memory_ready_entry(void *ptr)
*/
memory_init_data_bss();
#if (defined(TARGET_x86_fsp_qemu) && defined(WOLFBOOT_MEASURED_BOOT)) || \
(defined(STAGE1_AUTH) && defined (WOLFBOOT_TPM))
#if (defined(WOLFBOOT_MEASURED_BOOT)) || \
(defined(STAGE1_AUTH) && defined (WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY))
wolfBoot_printf("Initializing WOLFBOOT_TPM" ENDLINE);
ret = wolfBoot_tpm2_init();
if (ret != 0) {
wolfBoot_printf("tpm init failed" ENDLINE);
panic();
}
ret = wolfBoot_tpm_self_test();
if (ret != 0) {
wolfBoot_printf("tpm self test failed" ENDLINE);
panic();
}
#endif
#if (defined(TARGET_x86_fsp_qemu) && defined(WOLFBOOT_MEASURED_BOOT))
@ -522,6 +659,10 @@ static void memory_ready_entry(void *ptr)
#endif /* WOLFBOOT_MEASURED_BOOT */
/* Call FSP_S initialization */
fsp_info =
(struct fsp_info_header *)(fsp_s_base + FSP_INFO_HEADER_OFFSET);
wolfBoot_printf("FSP-S:");
print_fsp_image_revision((struct fsp_info_header *)fsp_info);
if (fsp_silicon_init(fsp_info, fsp_s_base) != EFI_SUCCESS)
panic();
/* Get CPUID */
@ -549,36 +690,36 @@ static void memory_ready_entry(void *ptr)
}
#endif /* WOLFBOOT_MEASURED_BOOT */
#if (defined(TARGET_x86_fsp_qemu) && defined(WOLFBOOT_MEASURED_BOOT)) || \
(defined(STAGE1_AUTH) && defined (WOLFBOOT_TPM))
#if (defined(WOLFBOOT_MEASURED_BOOT)) || \
(defined(STAGE1_AUTH) && defined (WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY))
wolfBoot_tpm2_deinit();
#endif
/* Finalize staging to stage2 */
set_stage2_parameter(stage2_params);
jump_into_wolfboot();
}
/*!
* \brief Check if the FSP info header is valid.
*
* This static function checks if the given FSP info header is valid by verifying
* its signature.
*
* \param hdr Pointer to the FSP info header structure.
* \return 1 if the FSP info header is valid, 0 otherwise.
*/
static int fsp_info_header_is_ok(struct fsp_info_header *hdr)
static void print_ucode_revision(void)
{
uint8_t *raw_signature;
#if !defined(TARGET_x86_fsp_qemu)
/* incomplete */
struct ucode_header {
uint32_t header_version;
uint32_t update_revision;
uint32_t date;
/* other fields not needed */
} __attribute__((packed));
struct ucode_header *h;
raw_signature = (uint8_t *)&hdr->Signature;
if (raw_signature[0] != 'F' || raw_signature[1] != 'S' ||
raw_signature[2] != 'P' || raw_signature[3] != 'H') {
return 0;
}
return 1;
h = (struct ucode_header *)UCODE0_ADDRESS;
wolfBoot_printf("microcode revision: %x, date: %x-%x-%x\r\n",
(int)h->update_revision,
(int)((h->date >> 24) & 0xff), /* month */
(int)((h->date >> 16) & 0xff), /* day */
(int)(h->date & 0xffff)); /* year */
#else
wolfBoot_printf("no microcode for QEMU target\r\n");
#endif
}
/*!
* \brief Entry point for the FSP-M (Firmware Support Package - Memory) module.
*
@ -595,8 +736,11 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
uint32_t bist)
{
uint8_t udp_m_parameter[FSP_M_UDP_MAX_SIZE], *udp_m_default;
struct stage2_ptr_holder *mem_stage2_holder;
struct fsp_info_header *fsp_m_info_header;
struct stage2_parameter *stage2_params;
struct stage2_ptr_holder stage2_holder;
struct stage2_parameter temp_params;
uint8_t *fsp_m_base, done = 0;
struct efi_hob *hobList, *it;
memory_init_cb MemoryInit;
@ -621,8 +765,20 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
wolfBoot_printf("post temp ram init cb failed" ENDLINE);
panic();
}
memset(&temp_params, 0, sizeof(temp_params));
stage2_set_parameters(&temp_params, &stage2_holder);
wolfBoot_printf("Cache-as-RAM initialized" ENDLINE);
wolfBoot_printf("FSP-T:");
print_fsp_image_revision((struct fsp_info_header *)
(_start_fsp_t + FSP_INFO_HEADER_OFFSET));
wolfBoot_printf("FSP-M:");
print_fsp_image_revision((struct fsp_info_header *)
(_start_fsp_m + FSP_INFO_HEADER_OFFSET));
print_ucode_revision();
fsp_m_info_header =
(struct fsp_info_header *)(fsp_m_base + FSP_INFO_HEADER_OFFSET);
udp_m_default = fsp_m_base + fsp_m_info_header->CfgRegionOffset;
@ -643,6 +799,16 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
panic();
}
#if defined(WOLFBOOT_DUMP_FSP_UPD)
wolfBoot_printf("Dumping fspm udp (%d bytes)" ENDLINE, (int)fsp_m_info_header->CfgRegionSize);
wolfBoot_print_hexstr(udp_m_parameter, fsp_m_info_header->CfgRegionSize, 16);
#endif
status = fsp_pre_mem_init_cb();
if (status != 0) {
wolfBoot_printf("pre mem init cb returns %d", status);
panic();
}
wolfBoot_printf("calling FspMemInit..." ENDLINE);
MemoryInit = (memory_init_cb)(fsp_m_base +
fsp_m_info_header->FspMemoryInitEntryOffset);
@ -675,10 +841,13 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
}
new_stack = top_address;
x86_log_memory_load(new_stack - WOLFBOOT_X86_STACK_SIZE, new_stack, "stack");
x86_log_memory_load(new_stack - WOLFBOOT_X86_STACK_SIZE - sizeof(struct stage2_parameter),
new_stack - WOLFBOOT_X86_STACK_SIZE, "stage2 parameter");
top_address =
new_stack - WOLFBOOT_X86_STACK_SIZE - sizeof(struct stage2_parameter);
stage2_params = (struct stage2_parameter *)(uint32_t)top_address;
memset((uint8_t *)stage2_params, 0, sizeof(struct stage2_parameter));
memcpy((uint8_t *)stage2_params, (uint8_t*)&temp_params, sizeof(struct stage2_parameter));
wolfBoot_printf("hoblist@0x%x" ENDLINE, (uint32_t)hobList);
stage2_params->hobList = (uint32_t)hobList;
@ -686,10 +855,14 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
stage2_params->page_table = ((uint32_t)(top_address) -
x86_paging_get_page_table_size());
stage2_params->page_table = (((uint32_t)stage2_params->page_table) & ~((1 << 12) - 1));
x86_log_memory_load(stage2_params->page_table, top_address, "page tables");
memset((uint8_t*)stage2_params->page_table, 0, x86_paging_get_page_table_size());
wolfBoot_printf("page table @ 0x%x [length: %x]" ENDLINE, (uint32_t)stage2_params->page_table, x86_paging_get_page_table_size());
top_address = stage2_params->page_table;
#endif /* WOLFBOOT_64BIT */
x86_log_memory_load(top_address - sizeof(struct stage2_ptr_holder), top_address, "stage2 ptr holder");
top_address = top_address - sizeof(struct stage2_ptr_holder);
mem_stage2_holder = (struct stage2_ptr_holder*)(uintptr_t)top_address;
stage2_params->tolum = top_address;
@ -704,14 +877,14 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
stage2_params->tpm_policy_size);
#endif
stage2_set_parameters(stage2_params, mem_stage2_holder);
wolfBoot_printf("TOLUM: 0x%x\r\n", stage2_params->tolum);
/* change_stack_and_invoke() never returns.
*
* Execution here is eventually transferred to memory_ready_entry
* after the stack has been remapped.
*/
change_stack_and_invoke(new_stack, memory_ready_entry,
(void*)stage2_params);
change_stack_and_invoke(new_stack, memory_ready_entry);
/* Returning from change_stack_and_invoke() implies a fatal error
* while attempting to remap the stack.

View File

@ -34,7 +34,7 @@
#include <x86/common.h>
#include <printf.h>
#include <stage1.h>
#include <stage2_params.h>
#include <x86/mptable.h>
#if defined(WOLFBOOT_LINUX_PAYLOAD)
@ -70,10 +70,6 @@ static char *cmdline = "console=ttyS0,115200 pci=earlydump debug";
static char *cmdline = "auto";
#endif /* TARGET_kontron_vx3060_s2 */
/* must be global so the linker will export the symbol. It's used from loader 1
* to fill the parameters */
struct stage2_parameter _stage2_params;
/**
* @brief Jump to the specified entry point.
*
@ -89,26 +85,6 @@ void jump(uintptr_t entry)
: "g"(entry));
}
struct stage2_parameter *stage2_get_parameters()
{
return &_stage2_params;
}
#if defined(WOLFBOOT_TPM_SEAL)
int stage2_get_tpm_policy(const uint8_t **policy, uint16_t *policy_sz)
{
#if defined(WOLFBOOT_FSP) && !defined(BUILD_LOADER_STAGE1)
struct stage2_parameter *p;
p = stage2_get_parameters();
*policy = (const uint8_t*)(uintptr_t)p->tpm_policy;
*policy_sz = p->tpm_policy_size;
return 0;
#else
#error "wolfBoot_get_tpm_policy is not implemented"
#endif
}
#endif /* WOLFBOOT_TPM_SEAL */
/**
* @brief Perform the boot process for the given application.
*
@ -144,7 +120,7 @@ void do_boot(const uint32_t *app)
mptable_setup();
x86_paging_dump_info();
r = elf_load_image_mmu((uint8_t *)app, &e, mmu_cb);
wolfBoot_printf("Elf loaded (ret %d), entry 0x%x_%x\r\n", 0,
wolfBoot_printf("Elf loaded (ret %d), entry 0x%x_%x\r\n", r,
(uint32_t)(e >> 32),
(uint32_t)(e));
x86_paging_dump_info();

View File

@ -151,6 +151,7 @@ TempRamInitSuccess:
[section .reset_vector]
BITS 16
ALIGN 16
global reset_vector
reset_vector:
nop
nop

View File

@ -77,7 +77,7 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
int is_elf32, is_le, i;
#ifdef DEBUG_ELF
wolfBoot_printf("Loading elf at %p\n", (void*)image);
wolfBoot_printf("Loading elf at %p\r\n", (void*)image);
#endif
/* Verify ELF header */
@ -95,7 +95,7 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
}
#ifdef DEBUG_ELF
wolfBoot_printf("Found valid elf%d (%s endian)\n",
wolfBoot_printf("Found valid elf%d (%s endian)\r\n",
is_elf32 ? 32 : 64, is_le ? "little" : "big");
#endif
@ -104,7 +104,7 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
entry_size = GET_H16(ph_entry_size);
entry_count = GET_H16(ph_entry_count);
#ifdef DEBUG_ELF
wolfBoot_printf("Program Headers %d (size %d)\n", entry_count, entry_size);
wolfBoot_printf("Program Headers %d (size %d)\r\n", entry_count, entry_size);
#endif
for (i = 0; i < entry_count; i++) {
uint8_t *ptr = ((uint8_t*)entry_off) + (i * entry_size);
@ -124,12 +124,12 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
#ifdef DEBUG_ELF
if (file_size > 0) {
wolfBoot_printf(
"\tLoad %u bytes (offset %p) to %p (p %p)\n",
"Load %u bytes (offset %p) to %p (p %p)\r\n",
(uint32_t)mem_size, (void*)offset, (void*)vaddr, (void*)paddr);
}
if (mem_size > file_size) {
wolfBoot_printf(
"\tClear %u bytes at %p (p %p)\n",
"Clear %u bytes at %p (p %p)\r\n",
(uint32_t)(mem_size - file_size), (void*)vaddr, (void*)paddr);
}
#endif
@ -139,7 +139,7 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
if (mmu_cb(vaddr, paddr, mem_size) != 0) {
#ifdef DEBUG_ELF
wolfBoot_printf(
"\tFail to map %u bytes to %p (p %p)\n",
"Fail to map %u bytes to %p (p %p)\r\n",
(uint32_t)mem_size, (void*)vaddr, (void*)paddr);
#endif
continue;
@ -159,7 +159,7 @@ int elf_load_image_mmu(uint8_t *image, uintptr_t *entry, elf_mmu_map_cb mmu_cb)
*entry = GET_H64(entry);
#ifdef DEBUG_ELF
wolfBoot_printf("Entry point %p\n", (void*)*entry);
wolfBoot_printf("Entry point %p\r\n", (void*)*entry);
#endif
return 0;

View File

@ -28,7 +28,7 @@
#include <multiboot.h>
#ifdef WOLFBOOT_FSP
#include <stage1.h>
#include <stage2_params.h>
#endif
#define MB2_HEADER_MAX_OFF (32768 - 4)

View File

@ -794,6 +794,102 @@ int pci_pre_enum(void)
return 0;
}
#if defined(DEBUG_PCI)
/**
* @brief Dump PCI configuration space
*
* @param bus PCI bus number
* @param dev PCI device number
* @param fun PCI function number
*/
void pci_dump(uint8_t bus, uint8_t dev, uint8_t fun)
{
uint32_t reg[256/4];
uint8_t *ptr;
int i;
for (i = 0; i < 256 / 4; i++) {
reg[i] = pci_config_read32(bus, dev, fun, i * 4);
}
ptr = (uint8_t*)reg;
for (i = 0; i < 256; i++) {
if (i % 0x10 == 0x0) {
if (i < 0x10) {
wolfBoot_printf("0");
}
wolfBoot_printf("%x: ", (int)i);
}
wolfBoot_printf("%s%x%s", (ptr[i] < 0x10 ? "0" :""), (int)ptr[i],
(i % 0x10 == 0xf ? "\r\n":" "));
}
}
/**
* @brief Dump PCI configuration space for all devices in the bus
*
* This function will dump the PCI configuration space for all devices in the
* bus, it will recursively dump buses behind bridges.
*
* @param bus PCI bus number
*/
static void pci_dump_bus(uint8_t bus)
{
uint16_t vendor_id, device_id, header_type;
uint8_t dev, fun, sec_bus;
uint32_t vd_code, reg;
int ret;
for (dev = 0; dev < PCI_ENUM_MAX_DEV; dev++) {
vd_code = pci_config_read32(bus, dev, 0, PCI_VENDOR_ID_OFFSET);
if (vd_code == 0xFFFFFFFF) {
/* No device here. */
continue;
}
for (fun = 0; fun < PCI_ENUM_MAX_FUN; fun++) {
vd_code = pci_config_read32(bus, dev, fun, PCI_VENDOR_ID_OFFSET);
if (vd_code == 0xFFFFFFFF) {
/* No device here. */
continue;
}
if (bus < 0x10)
wolfBoot_printf("0");
wolfBoot_printf("%x:", bus);
if (dev < 0x10)
wolfBoot_printf("0");
wolfBoot_printf("%x.", dev);
wolfBoot_printf("%d \r\n", fun);
pci_dump(bus, dev, fun);
header_type = pci_config_read16(bus, dev, fun,
PCI_HEADER_TYPE_OFFSET);
if ((header_type & PCI_HEADER_TYPE_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
sec_bus = pci_config_read8(bus, dev, fun, PCI_SECONDARY_BUS);
if (sec_bus != 0)
pci_dump_bus(sec_bus);
}
/* just one function */
if ((fun == 0) && !(header_type & PCI_HEADER_TYPE_MULTIFUNC_MASK)) {
break;
}
}
}
}
/**
* @brief Dump full PCI configuration space
*/
void pci_dump_config_space(void)
{
return pci_dump_bus(0);
}
#else
void pci_dump_config_space(void) {};
#endif
int pci_enum_do(void)
{
struct pci_enum_info enum_info;

132
src/stage2_params.c 100644
View File

@ -0,0 +1,132 @@
/* stage2_params.c
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stage2_params.h>
#include <string.h>
/*
* The storage of the stage2_params variable during memory initialization
* involves several changes of locations. Initially, before memory becomes
* available, it is stored inside the Cache-As-RAM, more precisely as the stack
* variable `temp_params` in `boot_x86_fsp.c:start()`. Once memory initialization
* occurs in stage1, the stage2_params is copied into memory. In stage2, when
* writable data sections are available, stage2_params resides in the .data
* section.
*
* The function `stage2_get_parameters()` is utilized throughout the code to
* obtain the correct address of stage2_params. It's important to note that
* whenever the location changes, the structure is copied verbatim. References to
* the struct must be updated manually. Additionally, during the transition to
* stage2, all references to function pointers will not be valid anymore.
*
* Internals:
* During stage1, the pointer to the parameter is stored just before the IDT
* (Interrupt Descriptor Table) table, and it can be recovered using the sidt
* instruction. This necessitates the presence of a dummy table with a single
* NULL descriptor. In stage2, stage2_get_parameter() serves as a wrapper
* function that simply returns the address of the _stage2_parameter global
* variable.
*/
#if defined(WOLFBOOT_TPM_SEAL)
int stage2_get_tpm_policy(const uint8_t **policy, uint16_t *policy_sz)
{
#if defined(WOLFBOOT_FSP)
struct stage2_parameter *p;
p = stage2_get_parameters();
*policy = (const uint8_t*)(uintptr_t)p->tpm_policy;
*policy_sz = p->tpm_policy_size;
return 0;
#else
#error "wolfBoot_get_tpm_policy is not implemented"
#endif
}
#endif /* WOLFBOOT_TPM_SEAL */
#if defined(BUILD_LOADER_STAGE1)
extern uint8_t _stage2_params[];
struct idt_descriptor {
uint16_t limit;
uint32_t base;
} __attribute__ ((packed));
/**
* @brief Set the stage 2 parameter pointer during stage 1.
*
* @param p Pointer to the stage 2 parameter structure.
* @param holder Pointer to the stage 2 parameter holder structure.
*
* This function sets the stage 2 parameter pointer during stage 1. The pointer
* is stored just before a dummy IDTR table, that is defined inside the holder
* struct.
*/
void stage2_set_parameters(struct stage2_parameter *p, struct stage2_ptr_holder *holder)
{
struct idt_descriptor idt;
idt.limit = sizeof(holder->dummy_idt) - 1;
idt.base = (uint32_t)&holder->dummy_idt;
memset(holder->dummy_idt, 0, sizeof(holder->dummy_idt));
holder->ptr = p;
asm ("lidt %0\r\n" : : "m"(idt));
}
/**
* @brief Get the stage 2 parameter pointer during stage 1.
*
* This function gets the stage 2 parameter pointer during stage 1. The pointer
* is stored just before a dummy IDTR table, stored in the IDT register.
*
* @return Pointer to the stage 2 parameter structure.
*/
struct stage2_parameter *stage2_get_parameters(void)
{
struct stage2_parameter **ptr;
struct idt_descriptor idt;
asm ("sidt %0\r\n" : "=m"(idt) : );
ptr = (struct stage2_parameter**)(uintptr_t)(idt.base - sizeof(struct stage2_parameter*));
return *ptr;
}
/*!
* \brief Set the stage 2 parameter for the WolfBoot bootloader.
*
* This static function sets the stage 2 parameter for the WolfBoot bootloader,
* which will be used by the bootloader during its execution.
*
* \param p Pointer to the stage 2 parameter structure.
*/
void stage2_copy_parameter(struct stage2_parameter *p)
{
memcpy((uint8_t*)&_stage2_params, (uint8_t*)p, sizeof(*p));
}
#else
/* must be global so the linker will export the symbol. It's used from loader 1
* to fill the parameters */
struct stage2_parameter _stage2_params;
struct stage2_parameter *stage2_get_parameters(void)
{
return &_stage2_params;
}
#endif

View File

@ -851,10 +851,15 @@ int wolfBoot_seal_auth(const uint8_t* pubkey_hint,
WOLFTPM2_KEYBLOB seal_blob;
word32 nvAttributes;
if (auth == NULL && authSz > 0)
return BAD_FUNC_ARG;
memset(&seal_blob, 0, sizeof(seal_blob));
seal_blob.handle.auth.size = authSz;
XMEMCPY(seal_blob.handle.auth.buffer, auth, authSz);
if (auth != NULL)
XMEMCPY(seal_blob.handle.auth.buffer, auth, authSz);
/* creates a sealed keyed hash object (not loaded to TPM) */
rc = wolfBoot_seal_blob(pubkey_hint, policy, policySz, &seal_blob,
@ -1320,5 +1325,17 @@ int wolfBoot_check_rot(int key_slot, uint8_t* pubkey_hint)
return rc;
}
#endif
/**
* @brief Perform TPM2 self test.
*
* This function performs the TPM2 self test.
*
* @return TPM_RC_SUCCESS in case of success
*
*/
int wolfBoot_tpm_self_test(void)
{
return wolfTPM2_SelfTest(&wolftpm_dev);
}
#endif /* WOLFBOOT_TPM */

View File

@ -41,7 +41,7 @@
#include "hal.h"
#include "spi_flash.h"
#include "printf.h"
#include "stage1.h"
#include "stage2_params.h"
#include "wolfboot/wolfboot.h"
#include <stdint.h>
#include <string.h>
@ -96,7 +96,12 @@ void RAMFUNCTION wolfBoot_start(void)
ret = x86_fsp_tgl_init_sata(&sata_bar);
if (ret != 0)
panic();
#endif
#if defined(WOLFBOOT_ATA_DISK_LOCK)
ret = sata_unlock_disk(BOOT_DISK, 1);
if (ret != 0)
panic();
#endif /* WOLFBOOT_ATA_DISK_LOCK */
#endif /* WOLFBOOT_FSP */
if (disk_open(BOOT_DISK) < 0)
panic();
@ -218,6 +223,5 @@ void RAMFUNCTION wolfBoot_start(void)
wolfBoot_printf("Booting at %08lx\r\n", os_image.fw_base);
hal_prepare_boot();
do_boot((uint32_t*)os_image.fw_base);
}
#endif /* UPDATE_DISK_H_ */

View File

@ -45,7 +45,7 @@
#include <tpm.h>
#if defined(WOLFBOOT_FSP)
#include <stage1.h>
#include <stage2_params.h>
#endif
#include <wolfssl/wolfcrypt/coding.h>
@ -63,6 +63,9 @@
#ifndef ATA_UNLOCK_DISK_KEY_SZ
#define ATA_UNLOCK_DISK_KEY_SZ 32
#endif
#ifndef WOLFBOOT_TPM_SEAL_KEY_ID
#define WOLFBOOT_TPM_SEAL_KEY_ID (0)
#endif
#endif /* defined(WOLFBOOT_ATA_DISK_LOCK_PASSWORD) || defined(WOLFBOOT_TPM_SEAL) */
#if defined(WOLFBOOT_ATA_DISK_LOCK_PASSWORD) && defined(WOLFBOOT_TPM_SEAL)
@ -223,7 +226,10 @@ static int sata_get_unlock_secret(uint8_t *secret, int *secret_size)
{
int password_len;
*secret_size = strlen(WOLFBOOT_ATA_DISK_LOCK_PASSWORD);
password_len = strlen(WOLFBOOT_ATA_DISK_LOCK_PASSWORD);
if (*secret_size < password_len)
return -1;
*secret_size = password_len;
memcpy(secret, (uint8_t*)WOLFBOOT_ATA_DISK_LOCK_PASSWORD, *secret_size);
return 0;
}
@ -236,8 +242,9 @@ static int sata_get_unlock_secret(uint8_t *secret, int *secret_size)
*
* @param key_slot The key slot ID to calculate the hash for.
* @param hash A pointer to store the resulting SHA256 hash.
* @return 0 on success, -1 on failure
*/
static void get_key_sha256(uint8_t key_slot, uint8_t *hash)
static int get_key_sha256(uint8_t key_slot, uint8_t *hash)
{
int blksz;
unsigned int i = 0;
@ -246,7 +253,7 @@ static void get_key_sha256(uint8_t key_slot, uint8_t *hash)
wc_Sha256 sha256_ctx;
if (!pubkey || (pubkey_sz < 0))
return;
return -1;
wc_InitSha256(&sha256_ctx);
while (i < (uint32_t)pubkey_sz) {
@ -257,25 +264,31 @@ static void get_key_sha256(uint8_t key_slot, uint8_t *hash)
i += blksz;
}
wc_Sha256Final(&sha256_ctx, hash);
return 0;
}
static int sata_get_random_base64(uint8_t *out, int *out_size)
{
uint8_t rand[ATA_SECRET_RANDOM_BYTES];
word32 _out_size;
word32 base_64_len;
int ret;
ret = wolfBoot_get_random(rand, ATA_SECRET_RANDOM_BYTES);
if (ret != 0)
return ret;
_out_size = *out_size;
ret = Base64_Encode(rand, ATA_SECRET_RANDOM_BYTES, out, &_out_size);
base_64_len = *out_size;
ret = Base64_Encode_NoNl(rand, ATA_SECRET_RANDOM_BYTES, out, &base_64_len);
if (ret != 0)
return ret;
/* double check we have a NULL-terminated string */
*out_size = (int)_out_size;
out[*out_size] = '\0';
if ((int)base_64_len < *out_size) {
out[base_64_len] = '\0';
base_64_len += 1;
} else {
out[base_64_len-1] = '\0';
}
*out_size = (int)base_64_len;
return 0;
}
@ -296,12 +309,13 @@ static int sata_create_and_seal_unlock_secret(const uint8_t *pubkey_hint,
if (ret == 0) {
wolfBoot_printf("Creating new secret (%d bytes)\r\n", *secret_size);
wolfBoot_printf("%s\r\n", secret);
/* seal new secret */
/* seal new secret */
ret = wolfBoot_seal(pubkey_hint, policy, policy_size,
ATA_UNLOCK_DISK_KEY_NV_INDEX,
secret, *secret_size);
}
if (ret == 0) {
/* unseal again to make sure it works */
memset(secret_check, 0, sizeof(secret_check));
@ -352,7 +366,11 @@ static int sata_get_unlock_secret(uint8_t *secret, int *secret_size)
return -1;
memcpy(policy, pol, policy_size);
get_key_sha256(0, pubkey_hint);
ret = get_key_sha256(WOLFBOOT_TPM_SEAL_KEY_ID, pubkey_hint);
if (ret != 0) {
wolfBoot_printf("failed to find key id %d\r\n", WOLFBOOT_TPM_SEAL_KEY_ID);
return ret;
}
ret = wolfBoot_unseal(pubkey_hint, policy, policy_size,
ATA_UNLOCK_DISK_KEY_NV_INDEX,
secret, secret_size);
@ -361,6 +379,13 @@ static int sata_get_unlock_secret(uint8_t *secret, int *secret_size)
ret = sata_create_and_seal_unlock_secret(pubkey_hint, policy, policy_size, secret,
secret_size);
}
#if defined(WOLFBOOT_DEBUG_REMOVE_SEALED_ON_ERROR)
if (ret != 0) {
wolfBoot_printf("deleting secret and panic!\r\n");
wolfBoot_delete_seal(ATA_UNLOCK_DISK_KEY_NV_INDEX);
panic();
}
#endif
if (ret != 0) {
wolfBoot_printf("get sealed unlock secret failed! %d (%s)\n", ret,
wolfTPM2_GetRCString(ret));
@ -370,52 +395,108 @@ static int sata_get_unlock_secret(uint8_t *secret, int *secret_size)
}
#endif /* WOLFBOOT_TPM_SEAL */
static int sata_unlock_disk(int drv)
#ifdef WOLFBOOT_ATA_DISABLE_USER_PASSWORD
static int sata_disable_password(int drv)
{
enum ata_security_state ata_st;
int r;
wolfBoot_printf("DISK DISABLE PASSWORD\r\n");
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: State SEC%d\r\n", ata_st);
if (ata_st == ATA_SEC4) {
r = ata_security_unlock_device(drv, ATA_MASTER_PASSWORD, 1);
wolfBoot_printf("ATA device unlock: returned %d\r\n", r);
if (r == 0) {
r = ata_security_disable_password(drv, ATA_MASTER_PASSWORD, 1);
wolfBoot_printf("ATA disable password: returned %d\r\n", r);
}
}
panic();
return 0;
}
#endif
/**
* @brief Unlocks a SATA disk for a given drive.
*
* This function unlocks a SATA disk identified by the specified drive number.
* If the SATA disk has no user password set, this function locks the disk.
*
* @param drv The drive number of the SATA disk to be unlocked.
* @return An integer indicating the success or failure of the unlocking
* operation.
* - 0: Success (disk unlocked).
* - -1: Failure (unable to unlock the disk).
*/
int sata_unlock_disk(int drv, int freeze)
{
int secret_size = ATA_UNLOCK_DISK_KEY_SZ;
uint8_t secret[ATA_UNLOCK_DISK_KEY_SZ];
enum ata_security_state ata_st;
int r;
#ifdef WOLFBOOT_ATA_DISABLE_USER_PASSWORD
sata_disable_password(0);
#endif
r = sata_get_unlock_secret(secret, &secret_size);
if (r != 0)
return r;
#ifdef TARGET_x86_fsp_qemu
wolfBoot_printf("DISK LOCK SECRET: %s\r\n", secret);
#endif
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security state SEC%d\r\n", ata_st);
#if defined(TARGET_x86_fsp_qemu)
if (ata_st == ATA_SEC0)
return 0;
#endif
if (ata_st == ATA_SEC1) {
AHCI_DEBUG_PRINTF("ATA identify: calling freeze lock\r\n", r);
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA security freeze lock: returned %d\r\n", r);
AHCI_DEBUG_PRINTF("ATA: calling set passphrase\r\n", r);
r = ata_security_set_password(drv, 0, (char*)secret);
if (r != 0)
return -1;
AHCI_DEBUG_PRINTF("ATA: calling freeze lock\r\n", r);
if (freeze) {
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA security freeze lock: returned %d\r\n", r);
if (r != 0)
return -1;
}
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security disabled. State SEC%d\r\n", ata_st);
wolfBoot_printf("ATA: State SEC%d\r\n", ata_st);
}
else if (ata_st == ATA_SEC4) {
AHCI_DEBUG_PRINTF("ATA identify: calling device unlock\r\n", r);
r = ata_security_unlock_device(drv, (char*)secret);
r = ata_security_unlock_device(drv, (char*)secret, 0);
AHCI_DEBUG_PRINTF("ATA device unlock: returned %d\r\n", r);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
ata_st = ata_security_get_state(drv);
if (ata_st == ATA_SEC5) {
AHCI_DEBUG_PRINTF("ATA identify: calling device freeze\r\n", r);
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA device freeze: returned %d\r\n", r);
if (freeze) {
AHCI_DEBUG_PRINTF("ATA identify: calling freeze lock\r\n", r);
r = ata_security_freeze_lock(drv);
AHCI_DEBUG_PRINTF("ATA security freeze lock: returned %d\r\n",
r);
if (r != 0)
return -1;
} else {
AHCI_DEBUG_PRINTF("ATA security freeze skipped\r\n");
}
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
}
ata_st = ata_security_get_state(drv);
if (ata_st != ATA_SEC6) {
panic();
}
ata_st = ata_security_get_state(drv);
wolfBoot_printf("ATA: Security enabled. State SEC%d\r\n", ata_st);
}
ata_st = ata_security_get_state(drv);
if ((freeze && ata_st != ATA_SEC6) || (!freeze && ata_st != ATA_SEC5)) {
AHCI_DEBUG_PRINTF("ATA: Security is not enabled/locked (State SEC%d)\r\n",
ata_st);
panic();
}
AHCI_DEBUG_PRINTF("ATA: Security enabled. State SEC%d\r\n", ata_st);
return 0;
}
#endif /* WOLFBOOT_ATA_DISK_LOCK */
@ -656,10 +737,6 @@ void sata_enable(uint32_t base)
drv, i);
r = ata_identify_device(drv);
AHCI_DEBUG_PRINTF("ATA identify: returned %d\r\n", r);
#ifdef WOLFBOOT_ATA_DISK_LOCK
if (r == 0)
r = sata_unlock_disk(drv);
#endif /* WOLFBOOT_ATA_DISK_LOCK */
}
} else {
AHCI_DEBUG_PRINTF("AHCI port %d: device with signature %08x is not supported\r\n",

View File

@ -57,7 +57,13 @@
static int ata_drive_count = -1;
struct ata_async_info{
int in_progress;
int drv;
int slot;
};
static struct ata_async_info ata_async_info;
/**
* @brief This structure holds the necessary information for an ATA drive,
* including AHCI base address, AHCI port number, and sector cache.
@ -264,6 +270,92 @@ static int prepare_cmd_h2d_slot(int drv, const uint8_t *buf, int sz, int w)
return slot;
}
/**
* @brief Check the completion status of an asynchronous ATA command.
*
* This function checks the completion status of an asynchronous ATA command
* that was previously initiated.
*
* @return
* - 0: Asynchronous ATA command completed successfully.
* - ATA_ERR_OP_NOT_IN_PROGRESS: No asynchronous operation in progress.
* - ATA_ERR_BUSY: The ATA operation is still in progress.
* - -1: ATA Task File error.
*/
int ata_cmd_complete_async()
{
struct ata_drive *ata;
int slot;
if (!ata_async_info.in_progress)
return ATA_ERR_OP_NOT_IN_PROGRESS;
ata = &ATA_Drv[ata_async_info.drv];
if (mmio_read32(AHCI_PxIS(ata->ahci_base, ata->ahci_port)) & AHCI_PORT_IS_TFES) {
ata_async_info.in_progress = 0;
return -1;
}
slot = ata_async_info.slot;
if ((mmio_read32(AHCI_PxCI(ata->ahci_base, ata->ahci_port)) & (1 << slot)) != 0)
return ATA_ERR_BUSY;
ata_async_info.in_progress = 0;
return 0;
}
/**
* @brief This static function executes the command in the specified command
* slot for the ATA drive, if async = 0 waits for the command to complete
* otherwise it immediately returns ATA_ERR_BUSY. Software must call
* `ata_cmd_complete_async()` to check for operation completion. Only one
* operation can run at a time, so this function returns ATA_OP_IN_PROGRESS if
* another async operation is already in progress. Software must invoke
* ata_cmd_complete_async() until it returns 0 or -1. Please note that the
* function is NOT thread safe and is NOT safe if ATA functions are supposed to
* interrupt the normal execution flow.
*
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
* @param[in] slot The index of the command slot to execute.
* @param[in] async Flag indicating whether the operation should be asynchronous (1) or synchronous (0).
* @return:
* - -1: if an error occurs during command execution.
* - ATA_ERR_OP_IN_PROGRESS: if async = 1 and another asynchronous operation is already in progress.
* - ATA_ERR_BUSY: If async = 1. To get cmd status invoke `ata_cmd_complete_async()`.
* - 0: success.
*/
static int exec_cmd_slot_ex(int drv, int slot, int async)
{
struct ata_drive *ata = &ATA_Drv[drv];
uint32_t reg;
if (ata_async_info.in_progress)
return ATA_ERR_OP_IN_PROGRESS;
/* Clear IS */
reg = mmio_read32(AHCI_PxIS(ata->ahci_base, ata->ahci_port));
mmio_write32(AHCI_PxIS(ata->ahci_base, ata->ahci_port), reg);
/* Wait until port not busy */
while (mmio_read32(AHCI_PxTFD(ata->ahci_base, ata->ahci_port)) & (ATA_DEV_BUSY | ATA_DEV_DRQ))
;
mmio_write32((AHCI_PxCI(ata->ahci_base, ata->ahci_port)), 1 << slot);
if (async) {
ata_async_info.in_progress = 1;
ata_async_info.drv = drv;
ata_async_info.slot = slot;
return ATA_ERR_BUSY;
}
while ((mmio_read32(AHCI_PxCI(ata->ahci_base, ata->ahci_port)) & (1 << slot)) != 0) {
if (mmio_read32(AHCI_PxIS(ata->ahci_base, ata->ahci_port)) & AHCI_PORT_IS_TFES) {
wolfBoot_printf("ATA: port error\r\n");
return -1;
}
}
return 0;
}
/**
* @brief This static function executes the command in the specified command
@ -276,28 +368,9 @@ static int prepare_cmd_h2d_slot(int drv, const uint8_t *buf, int sz, int w)
*/
static int exec_cmd_slot(int drv, int slot)
{
struct ata_drive *ata = &ATA_Drv[drv];
uint32_t reg;
/* Clear IS */
reg = mmio_read32(AHCI_PxIS(ata->ahci_base, ata->ahci_port));
mmio_write32(AHCI_PxIS(ata->ahci_base, ata->ahci_port), reg);
/* Wait until port not busy */
while (mmio_read32(AHCI_PxTFD(ata->ahci_base, ata->ahci_port)) & (ATA_DEV_BUSY | ATA_DEV_DRQ))
;
mmio_write32((AHCI_PxCI(ata->ahci_base, ata->ahci_port)), 1 << slot);
while ((mmio_read32(AHCI_PxCI(ata->ahci_base, ata->ahci_port)) & (1 << slot)) != 0) {
if (mmio_read32(AHCI_PxIS(ata->ahci_base, ata->ahci_port)) & AHCI_PORT_IS_TFES) {
wolfBoot_printf("ATA: port error\r\n");
return -1;
}
}
return 0;
return exec_cmd_slot_ex(drv, slot, 0);
}
static void invert_buf(uint8_t *src, uint8_t *dst, unsigned len)
{
unsigned i;
@ -375,13 +448,15 @@ static int security_command(int drv, uint8_t ata_cmd)
* @param[in] ata_cmd The ATA command to execute from the ATA security set.
* @param[in] passphrase The passphrase to transmit as argument in the buffer
* entry.
*
* @return 0 on success, or -1 if an error occurs while preparing or executing
* the ATA command.
*
* @param[in] async if the command will be executed in asynchronous mode
* @param[in] master if the passphrase should compare with master
* @return
* - 0: ATA command completed successfully.
* - ATA_ERR_OP_NOT_IN_PROGRESS: If async = 1 but no asynchronous operation in progress.
* - ATA_ERR_BUSY: If async = 1. To get cmd status invoke `ata_cmd_complete_async()`.
*/
static int security_command_passphrase(int drv, uint8_t ata_cmd,
const char *passphrase)
const char *passphrase, int async, int master)
{
struct hba_cmd_header *cmd;
struct hba_cmd_table *tbl;
@ -391,6 +466,8 @@ static int security_command_passphrase(int drv, uint8_t ata_cmd,
int slot = prepare_cmd_h2d_slot(drv, buffer,
ATA_SECURITY_COMMAND_LEN, 1);
memset(buffer, 0, ATA_SECURITY_COMMAND_LEN);
if (master)
buffer[0] = 0x1;
memcpy(buffer + ATA_SECURITY_PASSWORD_OFFSET, passphrase, strlen(passphrase));
if (slot < 0) {
return slot;
@ -403,7 +480,7 @@ static int security_command_passphrase(int drv, uint8_t ata_cmd,
cmdfis->c = 1;
cmdfis->command = ata_cmd;
cmdfis->count = 1;
ret = exec_cmd_slot(drv, slot);
ret = exec_cmd_slot_ex(drv, slot, async);
return ret;
}
@ -439,13 +516,14 @@ int ata_security_erase_prepare(int drv)
* command SECURITY UNLOCK, as defined in specs ATA8-ACS Sec. 7.49
*
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
* @param[in] passphrase The USER passphrase of the disk unit.
* @param[in] passphrase The passphrase of the disk unit.
* @param[in] master if true compare with MASTER otherwise USER
*
* @return 0 on success, or -1 if an error occurred.
*/
int ata_security_unlock_device(int drv, const char *passphrase)
int ata_security_unlock_device(int drv, const char *passphrase, int master)
{
return security_command_passphrase(drv, ATA_CMD_SECURITY_UNLOCK, passphrase);
return security_command_passphrase(drv, ATA_CMD_SECURITY_UNLOCK, passphrase, 0, master);
}
/**
@ -460,7 +538,7 @@ int ata_security_unlock_device(int drv, const char *passphrase)
*/
int ata_security_set_password(int drv, int master, const char *passphrase)
{
return security_command_passphrase(drv, ATA_CMD_SECURITY_SET_PASSWORD, passphrase);
return security_command_passphrase(drv, ATA_CMD_SECURITY_SET_PASSWORD, passphrase, 0, master);
}
/**
@ -470,12 +548,13 @@ int ata_security_set_password(int drv, int master, const char *passphrase)
*
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
* @param[in] passphrase The old USER passphrase for the disk unit to reset.
* @param[in] master if true compare with MASTER otherwise USER
*
* @return 0 on success, or -1 if an error occurred.
*/
int ata_security_disable_password(int drv, const char *passphrase)
int ata_security_disable_password(int drv, const char *passphrase, int master)
{
return security_command_passphrase(drv, ATA_CMD_SECURITY_DISABLE_PASSWORD, passphrase);
return security_command_passphrase(drv, ATA_CMD_SECURITY_DISABLE_PASSWORD, passphrase, 0, master);
}
/**
@ -483,13 +562,16 @@ int ata_security_disable_password(int drv, const char *passphrase)
* in specs ATA8-ACS Sec. 7.46
*
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
* @param[in] passphrase The USER passphrase for the disk unit to erase.
* @param[in] passphrase The USER/MASTER passphrase for the disk unit to erase.
* @param[in] master if 1 compare againts the MASTER password instead of USER
* password
*
* @return 0 on success, or -1 if an error occurred.
*/
int ata_security_erase_unit(int drv, const char *passphrase)
int ata_security_erase_unit(int drv, const char *passphrase, int master)
{
return security_command_passphrase(drv, ATA_CMD_SECURITY_ERASE_UNIT, passphrase);
return security_command_passphrase(drv, ATA_CMD_SECURITY_ERASE_UNIT,
passphrase, 1, master);
}
#endif /* WOLFBOOT_SATA_DISK_LOCK */
@ -712,6 +794,9 @@ int ata_drive_read(int drv, uint64_t start, uint32_t size, uint8_t *buf)
sect_start = start >> ata->sector_size_shift;
sect_off = start - (sect_start << ata->sector_size_shift);
if (drv > ata_drive_count)
return -1;
if (sect_off > 0) {
uint32_t len = MAX_SECTOR_SIZE - sect_off;
if (len > size)

View File

@ -51,6 +51,11 @@
#define NULL 0
#endif
void hlt()
{
__asm__ ("hlt");
}
/**
* @brief Memory-mapped write access to a 32-bit register.
*
@ -265,9 +270,7 @@ void delay(int msec)
*/
void panic()
{
while (1) {
delay(1);
}
hlt();
}
/**

View File

@ -0,0 +1,216 @@
/* exceptions.c
*
* Copyright (C) 2023 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*
*/
#include <x86/common.h>
#include <x86/exceptions.h>
#include <stdint.h>
#define EXCEPTION_NUM 35
#define INTERRUPT_GATE_TYPE (0xe)
#define SEGMENT_SELECTOR (0x18)
#define TYPE_FLAG (INTERRUPT_GATE_TYPE << 8 | 1 << 15)
#define LAPIC_DIV_CONF_REG 0xfee003e0
#define LAPIC_INITIAL_CNT 0xfee00380
#define LAPIC_CURRENT_CNT 0xfee00390
#define LAPIC_LVT_TIMER_REG 0xfee00320
#define LAPIC_EOI 0xfee000b0
#define LAPIC_SVR 0xfee000f0
#define LAPIC_SVR_ENABLE (1 << 8)
#define LAPIC_DIV_CONF_128 (1 << 1 | 1 << 3)
#define TIMER_SPURIOUS_NUMBER (33)
#define TIMER_VECTOR_NUMBER (34)
#define TIMER_CNT 0xffffff
#define IA32_APIC_BASE_MSR (0x1b)
#define IA32_APIC_BASE_MSR_ENABLE (0x800)
#define DEBUG_EXCEPTIONS
#if defined(DEBUG_EXCEPTIONS)
#include <printf.h>
#define EXCEPTIONS_DEBUG_PRINTF(...) wolfBoot_printf(__VA_ARGS__)
#else
#define EXCEPTIONS_DEBUG_PRINTF(...) do {} while(0)
#endif
struct interrupt_gate {
uint16_t offset_0_15;
uint16_t seg_sel;
uint16_t type_flags;
uint16_t offset_31_16;
uint32_t offset_63_32;
uint32_t reserved;
} __attribute__((packed));
struct idt_descriptor {
uint16_t limit;
uint64_t base;
} __attribute__((packed));
static struct interrupt_gate idt_table[EXCEPTION_NUM];
static struct idt_descriptor idt_descriptor;
#define EXCEPTION_TRAMPOLINE(X) \
__attribute__((naked)) void exception_trampoline_##X() { \
asm volatile("cli\r\n" \
"mov %0, %%rdi\r\n" \
"sti\r\n" \
"call common_exception_handler\r\n" \
"iretq\r\n" \
: \
: ""(X)); \
}
static void common_exception_handler(uint64_t vector_number)
{
EXCEPTIONS_DEBUG_PRINTF("CPU exception: %d\r\n", (int)vector_number);
}
EXCEPTION_TRAMPOLINE(0);
EXCEPTION_TRAMPOLINE(1);
EXCEPTION_TRAMPOLINE(2);
EXCEPTION_TRAMPOLINE(3);
EXCEPTION_TRAMPOLINE(4);
EXCEPTION_TRAMPOLINE(5);
EXCEPTION_TRAMPOLINE(6);
EXCEPTION_TRAMPOLINE(7);
EXCEPTION_TRAMPOLINE(8);
EXCEPTION_TRAMPOLINE(9);
EXCEPTION_TRAMPOLINE(10);
EXCEPTION_TRAMPOLINE(11);
EXCEPTION_TRAMPOLINE(12)
EXCEPTION_TRAMPOLINE(13);
EXCEPTION_TRAMPOLINE(14);
EXCEPTION_TRAMPOLINE(15);
EXCEPTION_TRAMPOLINE(16);
EXCEPTION_TRAMPOLINE(17);
EXCEPTION_TRAMPOLINE(18);
EXCEPTION_TRAMPOLINE(19);
EXCEPTION_TRAMPOLINE(20);
EXCEPTION_TRAMPOLINE(21);
EXCEPTION_TRAMPOLINE(22);
EXCEPTION_TRAMPOLINE(23);
EXCEPTION_TRAMPOLINE(24);
EXCEPTION_TRAMPOLINE(25);
EXCEPTION_TRAMPOLINE(26);
EXCEPTION_TRAMPOLINE(27);
EXCEPTION_TRAMPOLINE(28);
EXCEPTION_TRAMPOLINE(29);
EXCEPTION_TRAMPOLINE(30);
EXCEPTION_TRAMPOLINE(31);
EXCEPTION_TRAMPOLINE(32);
/* lapic spurious vector */
EXCEPTION_TRAMPOLINE(33);
int setup_interrupt_gate(int vnum, uintptr_t handler)
{
struct interrupt_gate *ig;
ig = &idt_table[vnum];
ig->offset_0_15 = (uint16_t)(handler & 0xffff);
ig->offset_31_16 = (uint16_t)((handler >> 16) & 0xffff);
ig->offset_63_32 = (uint32_t)((handler) >> 32);
ig->type_flags = TYPE_FLAG;
ig->seg_sel = SEGMENT_SELECTOR;
ig->reserved = 0x0;
}
static void _timer_handler()
{
EXCEPTIONS_DEBUG_PRINTF("In the timer handler\r\n");
}
static void __attribute__((__naked__)) timer_handler() {
asm volatile("cli\r\n"
"call _timer_handler\r\n"
"sti\r\n"
"mov %0, %%eax\r\n"
"movl $0, (%%eax)\r\n"
"iretq\r\n"::""(LAPIC_EOI));
}
static void setup_apic_timer()
{
mmio_write32(LAPIC_SVR, (LAPIC_SVR_ENABLE));
mmio_write32(LAPIC_DIV_CONF_REG, LAPIC_DIV_CONF_128);
setup_interrupt_gate(TIMER_VECTOR_NUMBER, (uintptr_t)timer_handler);
mmio_write32(LAPIC_LVT_TIMER_REG, TIMER_VECTOR_NUMBER);
}
int setup_interrupts()
{
setup_interrupt_gate(0,(uintptr_t) exception_trampoline_0);
setup_interrupt_gate(1,(uintptr_t) exception_trampoline_1);
setup_interrupt_gate(2,(uintptr_t) exception_trampoline_2);
setup_interrupt_gate(3,(uintptr_t) exception_trampoline_3);
setup_interrupt_gate(4,(uintptr_t) exception_trampoline_4);
setup_interrupt_gate(5,(uintptr_t) exception_trampoline_5);
setup_interrupt_gate(6,(uintptr_t) exception_trampoline_6);
setup_interrupt_gate(7,(uintptr_t) exception_trampoline_7);
setup_interrupt_gate(8,(uintptr_t) exception_trampoline_8);
setup_interrupt_gate(9,(uintptr_t) exception_trampoline_9);
setup_interrupt_gate(10,(uintptr_t) exception_trampoline_10);
setup_interrupt_gate(11,(uintptr_t) exception_trampoline_11);
setup_interrupt_gate(12,(uintptr_t) exception_trampoline_12);
setup_interrupt_gate(13,(uintptr_t) exception_trampoline_13);
setup_interrupt_gate(14,(uintptr_t) exception_trampoline_14);
setup_interrupt_gate(15,(uintptr_t) exception_trampoline_15);
setup_interrupt_gate(16,(uintptr_t) exception_trampoline_16);
setup_interrupt_gate(17,(uintptr_t) exception_trampoline_17);
setup_interrupt_gate(18,(uintptr_t) exception_trampoline_18);
setup_interrupt_gate(19,(uintptr_t) exception_trampoline_19);
setup_interrupt_gate(20,(uintptr_t) exception_trampoline_20);
setup_interrupt_gate(21,(uintptr_t) exception_trampoline_21);
setup_interrupt_gate(22,(uintptr_t) exception_trampoline_22);
setup_interrupt_gate(23,(uintptr_t) exception_trampoline_23);
setup_interrupt_gate(24,(uintptr_t) exception_trampoline_24);
setup_interrupt_gate(25,(uintptr_t) exception_trampoline_25);
setup_interrupt_gate(26,(uintptr_t) exception_trampoline_26);
setup_interrupt_gate(27,(uintptr_t) exception_trampoline_27);
setup_interrupt_gate(28,(uintptr_t) exception_trampoline_28);
setup_interrupt_gate(29,(uintptr_t) exception_trampoline_29);
setup_interrupt_gate(30,(uintptr_t) exception_trampoline_30);
setup_interrupt_gate(31,(uintptr_t) exception_trampoline_31);
setup_apic_timer();
idt_descriptor.base = (uintptr_t)&idt_table;
idt_descriptor.limit = sizeof(idt_table) -1;
asm ("lidt %0\r\n" : : "m"(idt_descriptor));
asm ("sti\r\n");
return 0;
}
void deinit_interrupts()
{
idt_descriptor.base = (uintptr_t)NULL;
idt_descriptor.limit = 0xffff;
asm ("cli\r\n");
asm ("lidt %0\r\n" : : "m"(idt_descriptor));
}
void wfi()
{
setup_apic_timer();
mmio_write32(LAPIC_INITIAL_CNT, TIMER_CNT);
hlt();
}

View File

@ -29,6 +29,7 @@
*/
#ifndef GPT_C
#define GPT_C
#include <stdint.h>
#include <x86/common.h>
#include <x86/ahci.h>
#include <x86/ata.h>
@ -45,6 +46,7 @@
#define PTYPE_GPT 0xEE
#define P_ENTRY_START 0x01BE
#define P_BOOTSIG_OFFSET 0x01FE
#define GPT_PART_NAME_SIZE (36)
/**
* @brief This packed structure defines the layout of an MBR partition table entry
@ -92,7 +94,7 @@ struct __attribute__((packed)) guid_part_array
uint64_t first;
uint64_t last;
uint64_t flags;
int16_t name[72];
uint16_t name[GPT_PART_NAME_SIZE];
};
/**
@ -105,6 +107,7 @@ struct disk_partition
int part_no;
uint64_t start;
uint64_t end;
uint16_t name[GPT_PART_NAME_SIZE];
};
/**
@ -125,6 +128,30 @@ struct disk_drive {
*/
static struct disk_drive Drives[MAX_DISKS] = {0};
static int disk_u16_ascii_eq(const uint16_t *utf16, const char *ascii)
{
unsigned int utf16_idx;
unsigned int i;
if (strlen(ascii) > GPT_PART_NAME_SIZE)
return 0;
utf16_idx = 0;
/* skip BOM if present */
if (utf16[utf16_idx] == 0xfeff)
utf16_idx = 1;
for (i = 0; i < strlen(ascii); i++, utf16_idx++) {
/* non-ascii character*/
if (utf16[utf16_idx] != (uint16_t)ascii[i])
return 0;
}
if (utf16_idx < GPT_PART_NAME_SIZE && utf16[utf16_idx] != 0x0)
return 0;
return 1;
}
/**
* @brief Opens a disk drive and initializes its partitions.
*
@ -220,6 +247,7 @@ int disk_open(int drv)
Drives[drv].part[part_count].drv = drv;
Drives[drv].part[part_count].start = pa.first * SECTOR_SIZE;
Drives[drv].part[part_count].end = (pa.last * SECTOR_SIZE - 1);
memcpy(&Drives[drv].part[part_count].name, (uint8_t*)&pa.name, sizeof(pa.name));
wolfBoot_printf("disk%d.p%u ", drv, part_count);
wolfBoot_printf("(%x_%xh", (uint32_t)(size>>32), (uint32_t)size);
wolfBoot_printf("@ %x_%x)\r\n", (uint32_t)((pa.first * SECTOR_SIZE) >> 32),
@ -327,4 +355,23 @@ int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf)
ret = ata_drive_write(drv, p->start + off, len, buf);
return ret;
}
int disk_find_partion_by_label(int drv, const char *label)
{
struct disk_partition *p;
int i;
if ((drv < 0) || (drv > MAX_DISKS))
return -1;
if (Drives[drv].is_open == 0)
return -1;
for (i = 0; i < Drives[drv].n_parts; i++) {
p = open_part(drv, i);
if (disk_u16_ascii_eq(p->name, label) == 1)
return i;
}
return -1;
}
#endif /* GPT_C */

View File

@ -30,7 +30,7 @@
#ifdef WOLFBOOT_FSP
#include <x86/hob.h>
#include <stage1.h>
#include <stage2_params.h>
#endif /* WOLFBOOT_FSP */
#define ENDLINE "\r\n"

View File

@ -25,7 +25,7 @@
#define PAGE_TABLE_PAGE_SIZE (0x1000)
#ifndef PAGE_TABLE_PAGE_NUM
/* 7 pages are enough to identity map al 4GB */
/* 7 pages are enough to identity map all 4GB */
#define PAGE_TABLE_PAGE_NUM 7
#endif /* PAGE_TABLE_PAGE_NUM */
@ -42,7 +42,7 @@
#define PAGE_2MB_SHIFT 21
#if !defined(BUILD_LOADER_STAGE1)
#define WOLFBOOT_PTP_NUM 128
#define WOLFBOOT_PTP_NUM 512
static uint8_t page_table_pages[WOLFBOOT_PTP_NUM * PAGE_TABLE_PAGE_SIZE]
__attribute__((aligned(PAGE_TABLE_PAGE_SIZE)));
static int page_table_page_used;
@ -220,12 +220,6 @@ void x86_paging_dump_info()
(uint32_t)((uintptr_t)page_table_pages >> 32),
(uint32_t)(uintptr_t)page_table_pages);
wolfBoot_printf("page_table_pages used: %d\r\n", page_table_page_used);
wolfBoot_printf("mem start @ %x %xh\r\n",
(uint32_t)((uintptr_t)_mem >> 32),
(uint32_t)(uintptr_t)_mem);
wolfBoot_printf("mem curr @ %x %xh\r\n",
(uint32_t)((uintptr_t)mem >> 32),
(uint32_t)(uintptr_t)mem);
}
#else
void x86_paging_dump_info() {}

View File

@ -25,6 +25,7 @@
#include <x86/hob.h>
#include <uart_drv.h>
#include <x86/ahci.h>
#include <stage2_params.h>
#define FSPM_UPD_SIGNATURE 0x4D5F4450554D4551 /* 'QEMUPD_M' */
#define FSPT_UPD_SIGNATURE 0x545F4450554D4551 /* 'QEMUPD_T' */
@ -115,6 +116,7 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params,
uint32_t mem_base,
uint32_t mem_size)
{
struct stage2_parameter *params;
struct fspm_upd *new_udp;
new_udp = (struct fspm_upd*)default_m_params;
@ -128,3 +130,13 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params,
return 0;
}
int fsp_pre_mem_init_cb(void)
{
return 0;
}
int fsp_pre_silicon_init_cb(void)
{
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,7 @@ $(LSCRIPT_IN): $(WOLFBOOT_ROOT)/hal/$(LSCRIPT_IN).in FORCE
sed -e "s/@FSP_S_BASE@/$(FSP_S_BASE)/g" | \
sed -e "s/@WOLFBOOT_LOAD_BASE@/$(WOLFBOOT_LOAD_BASE)/g" | \
sed -e "s/@UCODE0_BASE@/$(UCODE0_BASE)/g" | \
sed -e "s/@UCODE1_BASE@/$(UCODE1_BASE)/g" | \
sed -e "s/@FSP_S_UPD_DATA_BASE@/$(FSP_S_UPD_DATA_BASE)/g" \
sed -e "s/@UCODE1_BASE@/$(UCODE1_BASE)/g" \
> $@
./boot_x86_fsp_start.o: boot_x86_fsp_start.S
@ -38,17 +37,13 @@ sig_fsp_s.o: fsp_s.o $(SIGN_KEY) ../$(FSP_S_BIN)
$(SIGN_TOOL) $(SIGN_OPTIONS) ../$(FSP_S_BIN) $(SIGN_KEY) 1
@dd if=$(X86FSP_PATH)/fsp_s_v1_signed.bin of=$(X86FSP_PATH)/fsp_s_signature.bin bs=$(IMAGE_HEADER_SIZE) count=1
$(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.sig_fsp_s $(X86FSP_PATH)/fsp_s_signature.bin sig_fsp_s.o
@rm -f $(X86FSP_PATH)/fsp_s_v1_signed.bin $(X86FSP_PATH)/fsp_s_signature.bin
@rm -f $(X86FSP_PATH)/fsp_s_signature.bin
sig_wolfboot_raw.o: wolfboot_raw.bin $(SIGN_KEY)
$(SIGN_TOOL) $(SIGN_OPTIONS) wolfboot_raw.bin $(SIGN_KEY) 1
@dd if=wolfboot_raw_v1_signed.bin of=wolfboot_raw_signature.bin bs=$(IMAGE_HEADER_SIZE) count=1
$(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.sig_wolfboot_raw wolfboot_raw_signature.bin sig_wolfboot_raw.o
fsp_tgl_s_upd.o: ../$(FSP_S_UPD_DATA_BIN)
$(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsps_upd $^ $@
ucode0.o: ../$(UCODE0_BIN)
$(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.ucode0 $^ $@

View File

@ -358,6 +358,12 @@ ifeq ($(TARGET),psoc6)
CFLAGS+=-DCY8C624ABZI_D44
endif
ifeq ($(TARGET),x86_fsp_qemu)
APP_OBJS:=app_$(TARGET).o ../hal/x86_uart.o ../src/x86/common.o ../src/string.o
LSCRIPT_TEMPLATE:=x86_fsp.ld
LDFLAGS=
endif
CFLAGS+=-I../lib/wolfssl

View File

@ -0,0 +1,68 @@
/* app_x86_fsp_qemu.c
*
* Test bare-metal boot application
*
* Copyright (C) 2021 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* 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 2 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef PLATFORM_x86_fsp_qemu
#include <printf.h>
#include <stdint.h>
struct mb2_header {
uint32_t magic;
uint32_t architecture;
uint32_t header_length;
uint32_t checksum;
} __attribute__((__packed__));
struct mb2_tag_info_req {
uint16_t type;
uint16_t flags;
uint32_t size;
uint32_t mbi_tag_types[2];
} __attribute__((__packed__));
struct multiboot_header {
struct mb2_header hdr;
struct mb2_tag_info_req req;
} __attribute__((__packed__));
__attribute__((aligned(8))) struct multiboot_header mbh = {
.hdr.magic = 0xe85250d6,
.hdr.architecture = 0,
.hdr.checksum = 0,
.hdr.header_length = sizeof(struct mb2_header),
.req.type = 1,
.req.flags = 0,
.req.size = sizeof(struct mb2_tag_info_req),
/* basic mem info */
.req.mbi_tag_types[0] = 4,
/* mem map */
.req.mbi_tag_types[1] = 6,
};
void start()
{
wolfBoot_printf("wolfBoot QEMU x86 FSP test app\r\n");
__asm__ ("hlt\r\n");
}
#endif

View File

@ -0,0 +1,26 @@
OUTPUT_FORMAT(elf64-x86-64)
SECTIONS
{
.text :
{
_start_text = .;
*(.text*)
_end_text = .;
}
.data :
{
_start_data = .;
*(.data*)
_end_data = .;
}
.bss (NOLOAD) :
{
_start_bss = .;
*(.bss*)
. = ALIGN(4);
_end_bss = .;
}
}

View File

@ -1,5 +0,0 @@
#!/bin/bash
qemu-system-i386 -m 1G -machine q35 -serial mon:stdio -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk

View File

@ -1,36 +0,0 @@
#!/bin/bash
#
## TPM emulator:
# https://github.com/stefanberger/swtpm
if (test -z $OVMF_PATH); then
if (test -f /usr/share/edk2-ovmf/x64/OVMF.fd); then
OVMF_PATH=/usr/share/edk2-ovmf/x64
elif (test -f /usr/share/qemu/OVMF.fd); then
OVMF_PATH=/usr/share/qemu
else
OVMF_PATH=/
fi
fi
QEMU_TPM_OPTIONS=" \
-chardev socket,id=chrtpm,path=/tmp/swtpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0"
QEMU_OPTIONS=" \
-m 1G -machine q35 -serial mon:stdio -nographic -smp cpus=8,sockets=2,cores=2,threads=2 \
-kernel bzImage -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk"
#killall swtpm
#sleep 1
echo TPM Emulation ON
mkdir -p /tmp/swtpm
swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \
--ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 &
sleep .5
echo Running QEMU...
qemu-system-x86_64 $QEMU_OPTIONS $QEMU_TPM_OPTIONS

View File

@ -1,43 +0,0 @@
#!/bin/bash
#
## TPM emulator:
# https://github.com/stefanberger/swtpm
if (test -z $OVMF_PATH); then
if (test -f /usr/share/edk2-ovmf/x64/OVMF.fd); then
OVMF_PATH=/usr/share/edk2-ovmf/x64
elif (test -f /usr/share/qemu/OVMF.fd); then
OVMF_PATH=/usr/share/qemu
else
OVMF_PATH=/
fi
fi
QEMU_TPM_OPTIONS=" \
-chardev socket,id=chrtpm,path=/tmp/swtpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0"
QEMU_OPTIONS=" \
-m 1G -machine q35 -serial mon:stdio -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk"
QEMU=qemu-system-x86_64
if [ "$DEBUG" = "1" ]; then
QEMU_OPTIONS="${QEMU_OPTIONS} -S -s"
QEMU=qemu-system-i386
fi
killall swtpm
sleep 1
echo TPM Emulation ON
mkdir -p /tmp/swtpm
swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \
--ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 &
sleep .5
echo Running QEMU...
$QEMU $QEMU_OPTIONS $QEMU_TPM_OPTIONS

View File

@ -1,5 +0,0 @@
#!/bin/bash
qemu-system-x86_64 -m 1G -machine q35 -serial mon:stdio -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk

View File

@ -1,5 +0,0 @@
#!/bin/bash
qemu-system-x86_64 -m 1G -machine q35 -serial mon:stdio -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk -S -s

View File

@ -1,6 +0,0 @@
#!/bin/bash
qemu-system-i386 -m 1G -machine q35 -serial mon:stdio -nographic \
-pflash stage1/loader_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk \
-S -s

View File

@ -1,6 +0,0 @@
#!/bin/bash
qemu-system-x86_64 -m 1G -machine q35 -serial mon:stdio -nographic \
-kernel bzImage \
-drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk

View File

@ -1,37 +0,0 @@
#!/bin/bash
#
## TPM emulator:
# https://github.com/stefanberger/swtpm
if (test -z $OVMF_PATH); then
if (test -f /usr/share/edk2-ovmf/x64/OVMF.fd); then
OVMF_PATH=/usr/share/edk2-ovmf/x64
elif (test -f /usr/share/qemu/OVMF.fd); then
OVMF_PATH=/usr/share/qemu
else
OVMF_PATH=/
fi
fi
QEMU_TPM_OPTIONS=" \
-chardev socket,id=chrtpm,path=/tmp/swtpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0"
QEMU_OPTIONS=" \
-m 1G -machine q35 -serial mon:stdio -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk \
-S -gdb tcp::3333"
#killall swtpm
#sleep 1
echo TPM Emulation ON
mkdir -p /tmp/swtpm
swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \
--ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 &
sleep .5
echo Running QEMU...
qemu-system-i386 $QEMU_OPTIONS $QEMU_TPM_OPTIONS

View File

@ -1,15 +0,0 @@
#!/bin/bash
SIGN=${SIGN:-"--ecc256"}
HASH=${HASH:-"--sha256"}
cp /tmp/br-linux-wolfboot/output/images/bzImage .
tools/keytools/sign $SIGN $HASH bzImage wolfboot_signing_private_key.der 8
tools/keytools/sign $SIGN $HASH bzImage wolfboot_signing_private_key.der 2
cp base-part-image app.bin
dd if=bzImage_v8_signed.bin of=app.bin bs=1k seek=1024 conv=notrunc
dd if=bzImage_v2_signed.bin of=app.bin bs=1k seek=17408 conv=notrunc

View File

@ -1,32 +0,0 @@
#!/bin/bash
set -e
#qemu-system-x86_64 -m 256M -machine q35 -serial mon:stdio -nographic -pflash \
# ../wolfBoot/x86_qemu_flash.bin -gdb tcp::3333 -S \
# -drive file=test_img.bin,if=none,id=SATADRV \
# -device ich9-ahci,id=ahci \
# -device ide-hd,drive=SATADRV,bus=ahci.0
# qemu-system-i386 -m 256M -machine q35 -serial mon:stdio -nographic -pflash \
# x86_qemu_flash.bin -S -s \
# -drive file=test_img.bin,if=none,id=SATADRV,format=raw \
# -device ich9-ahci,id=ahci \
# -device ide-hd,drive=SATADRV,bus=ahci.0
# qemu-system-x86_64 -m 1G -machine q35 -serial mon:stdio -nographic \
# -drive id=mydisk,format=raw,file=app.bin,if=none \
# -device ide-hd,drive=mydisk \
# -kernel /home/arch/br-linux-wolfboot/output/images/bzImage \
# -append "acpi=off"
#qemu-system-x86_64 -m 256M -machine q35 -serial mon:stdio -nographic \
qemu-system-x86_64 -m 256M -machine q35 \
-drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk \
-pflash loader.bin
# -kernel /home/arch/br-linux-wolfboot/output/images/bzImage \
# -append "acpi=off loglevel=7 libata.noacpi=1 libata.force=6.0:noncq libata.dma=0" \
# -S -s

View File

@ -0,0 +1,125 @@
"""
Parse IFWI Image to compute initial PCR0 value as obtained by Intel Boot Guard
"""
import struct
import argparse
import hashlib
import os
import re
import subprocess
FLASH_SIZE_IN_MB = 64
def off_to_addr(off: int, image_size : int = FLASH_SIZE_IN_MB*1024*1024) -> int:
"""
convert offset in the image to address in memory
"""
return (4 * 1024 * 1024 * 1024) - (image_size - off)
def addr_to_off(addr:int, image_size : int = FLASH_SIZE_IN_MB*1024*1024) -> int:
"""
convert address in memory to offset in the image
"""
return image_size - ((4 * 1024 * 1024 * 1024) - addr)
def get_sha256_hash(data: bytearray) -> bytearray:
"""
return the sha256 of data
"""
h = hashlib.sha256()
h.update(data)
return h.digest()
def get_config_value(config: str, name):
"""
Parse config to find line of type NAME=value, return value
"""
pattern = rf'^{re.escape(name)}=(.*)$'
matches = re.findall(pattern, config, re.MULTILINE)
if matches:
return matches[0].strip()
return None
def get_sha256_hash_of_wolfboot_image(file_path: str):
"""
Get sha256 hash of wolfboot image at file_path
"""
HDR_OFF = 8
WOLFBOOT_SHA_HDR = 0x03
with open(file_path, 'rb') as f:
data = f.read()
data = data[HDR_OFF:]
while True:
if data[0] == 0xff:
data = data[1:]
continue
t, l = struct.unpack('<HH', data[:4])
if l == 0:
return None
if t == WOLFBOOT_SHA_HDR:
return data[4:4+l]
data = data[4+l:]
def get_keystore_sym_addr() -> int:
"""
get the address of symbol keystore from ELF file image
"""
symbols = subprocess.check_output(['nm', 'stage1/loader_stage1.elf']).split(b'\n')
_start_keystore = int(list(filter(lambda x: b'_start_keystore' in x, symbols))[0].split(b' ')[0], 16)
return _start_keystore
def pcr_extend(pcr: bytearray, data: bytearray) -> bytearray:
"""
get value of extend operation on pcr with data
"""
return get_sha256_hash(pcr + data)
if __name__ == '__main__':
if os.path.exists('.config'):
with open('.config', 'r', encoding='utf-8') as f:
config = f.read()
else:
print("The file .config does not exist.")
parser = argparse.ArgumentParser()
parser.add_argument('image_file', type=str, help='Path to the image file')
parser.add_argument('--target', type=str, choices=['IBG', 'qemu'],
default='IBG', help='Target platform')
args = parser.parse_args()
image = bytes()
with open(args.image_file, 'rb') as f:
image = bytearray(f.read())
pcr0 = bytearray(b'\x00'*32)
if args.target == 'qemu':
keystore_addr = get_keystore_sym_addr()
keystore_off = addr_to_off(keystore_addr, image_size = len(image))
ibb = image[keystore_off:]
h = hashlib.sha256()
h.update(ibb)
pcr0_data_hash = h.digest()
pcr0 = pcr_extend(b'\x00'*32, pcr0_data_hash)
print(f"Initial PCR0: {pcr0.hex()}")
is_stage1_auth_enabled = get_config_value(config, 'STAGE1_AUTH') == '1'
print(f"stage1 auth is {'enabled' if is_stage1_auth_enabled else 'disabled'}")
if is_stage1_auth_enabled:
fsp_s_hash = get_sha256_hash_of_wolfboot_image("src/x86/fsp_s_v1_signed.bin")
pcr0 = pcr_extend(pcr0, fsp_s_hash)
print(f"PCR0 after FSP_S: {pcr0.hex()}")
wb_hash = get_sha256_hash_of_wolfboot_image('stage1/wolfboot_raw_v1_signed.bin')
pcr0 = pcr_extend(pcr0, wb_hash)
print(f"PCR0 after wolfboot: {pcr0.hex()}")
# the pcrdigest needed by policy_sign tool is the hash of the concatenation of all PCRs involved in the policy.
# we have only one PCR here
pcr_digest = get_sha256_hash(pcr0)
print("PCR Policy (use with tpm/policy_sign with -pcrdigest arg)")
print(pcr_digest.hex())

View File

@ -0,0 +1,43 @@
#!/usr/bin/env python
import re
import argparse
pattern = r'^([\w\.]+) +(0x[0-9a-fA-F]+) +(0x[0-9a-fA-F]+)'
def parse_map_file(map_file_path):
components = []
mmap = False
flash_start = 0
with open(map_file_path, 'r') as map_file:
current_component = None
for line in map_file:
if line.startswith('FLASH'):
m = re.match(r'FLASH +(0x[0-9a-fA-F]+)', line)
flash_start = int(m[1], 16)
if line == 'Linker script and memory map\n' or mmap:
mmap = True
else:
continue
# Check for start of a new component
m = re.match(pattern, line)
if m:
c = {'name': m[1], 'address': int(m[2], 16), 'size': int(m[3], 16)}
components.append(c)
return components, flash_start
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("map_file_path", type=str,
help="Path to the map file",
nargs='?',
default='stage1/loader_stage1.map')
args = parser.parse_args()
map_file_path = args.map_file_path
comps, flash = parse_map_file(map_file_path)
comps = filter(lambda x: x['address'] >= flash, comps)
comps = sorted(comps, key=lambda x: x['address'])
print(f'Name:{"":<20}Address:{"":<20}Size:{"":<20}')
for c in comps:
print (f"{c['name']:<20} {hex(c['address']):<20} {hex(c['size']):<20}")
total_sum = sum(map(lambda x: x['size'], comps))
print(f"total sum: {hex(total_sum)} ({total_sum//1024} KB)")

View File

@ -0,0 +1,35 @@
#!/bin/bash
SIGN=${SIGN:-"--ecc256"}
HASH=${HASH:-"--sha256"}
IMAGE=${IMAGE:-"bzImage"}
set -e
dd if=/dev/zero of=app.bin bs=1M count=64
/sbin/fdisk app.bin <<EOF
g
n
1
+16M
n
+16M
x
n
1
OFP_A
n
2
OFP_B
r
w
EOF
cp ${IMAGE} "image.bin"
tools/keytools/sign $SIGN $HASH image.bin wolfboot_signing_private_key.der 1
tools/keytools/sign $SIGN $HASH image.bin wolfboot_signing_private_key.der 2
dd if=image_v1_signed.bin of=app.bin bs=512 seek=2048 conv=notrunc
dd if=image_v2_signed.bin of=app.bin bs=512 seek=34816 conv=notrunc

View File

@ -0,0 +1,122 @@
#!/bin/bash
#By default, the script will run without waiting for GDB. If you use the
# -w parameter, it will wait for GDB to connect.
# Usage:
# For DEBUG_STAGE1 without waiting for GDB: ./qemu.sh -d DEBUG_STAGE1
# For DEBUG_STAGE2 without waiting for GDB (default): ./qemu.sh
# For DEBUG_STAGE1 with waiting for GDB: ./qemu.sh -d DEBUG_STAGE1 -w
# For DEBUG_STAGE2 with waiting for GDB: ./qemu.sh -w
# To DEBUG_STAGE1
# $ gdb stage1/loader_stage1.elf
# target remote :1234
# b start
# c
# To DEBUG_STAGE2
# $ gdb wolfboot.elf
# target remote :1234
# b main
# c
## TPM emulator:
# https://github.com/stefanberger/swtpm
# sudo apt install swtpm
# Default values
DEBUG_STAGE="DEBUG_STAGE2"
WAIT_FOR_GDB=false
echo "Running wolfBoot on QEMU"
set -e
set -x
# Parse command line options
while getopts "d:wpt" opt; do
case "$opt" in
d)
DEBUG_STAGE="$OPTARG"
;;
w)
WAIT_FOR_GDB=true
;;
p)
CREATE_PIPE=true
;;
t) ENABLE_TPM=true
;;
*)
echo "Usage: $0 [-d DEBUG_STAGE1 | DEBUG_STAGE2] [-w] [-p]"
echo "-p : create /tmp/qemu_mon.in and /tmp/qemu_mon.out pipes for monitor qemu"
echo "-w : wait for GDB to connect to the QEMU gdb server"
echo "-t : enable TPM emulation (requires swtpm)"
exit 1
;;
esac
done
if (test -z $OVMF_PATH); then
if (test -f /usr/share/edk2-ovmf/x64/OVMF.fd); then
OVMF_PATH=/usr/share/edk2-ovmf/x64
elif (test -f /usr/share/qemu/OVMF.fd); then
OVMF_PATH=/usr/share/qemu
else
OVMF_PATH=/
fi
fi
QEMU_TPM_OPTIONS=" \
-chardev socket,id=chrtpm,path=/tmp/swtpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0 \
"
QEMU_OPTIONS=" \
-m 1G -machine q35 -nographic \
-pflash wolfboot_stage1.bin -drive id=mydisk,format=raw,file=app.bin,if=none \
-device ide-hd,drive=mydisk \
"
if [ "$CREATE_PIPE" = true ]; then
rm /tmp/qemu_mon.in /tmp/qemu_mon.out || true &> /dev/null
mkfifo /tmp/qemu_mon.in /tmp/qemu_mon.out
QEMU_OPTIONS+="\
-chardev pipe,id=qemu_mon,path=/tmp/qemu_mon \
-mon chardev=qemu_mon \
-serial stdio \
"
fi
# If waiting for GDB is true, append options to QEMU_OPTIONS
if [ "$WAIT_FOR_GDB" = true ]; then
QEMU_OPTIONS="${QEMU_OPTIONS} -S -s"
fi
if [ "$DEBUG_STAGE" = "DEBUG_STAGE1" ]; then
QEMU=qemu-system-i386
else
QEMU=qemu-system-x86_64
fi
if [ "$ENABLE_TPM" = true ]; then
killall swtpm || true
sleep 1
echo TPM Emulation ON
mkdir -p /tmp/swtpm
swtpm socket --tpm2 --tpmstate dir=/tmp/swtpm \
--ctrl type=unixio,path=/tmp/swtpm/swtpm-sock --log level=20 &
sleep .5
QEMU_OPTIONS+=$QEMU_TPM_OPTIONS
fi
echo Running QEMU...
echo "$QEMU $QEMU_OPTIONS"
$QEMU $QEMU_OPTIONS

View File

@ -6,12 +6,17 @@ EDKII_REPO=https://github.com/tianocore/edk2.git
SBL_COMMIT_ID=c80d8d592cf127616daca5df03ac7731e78ffcc1
SBL_PATCH_URL=https://github.com/slimbootloader/slimbootloader/raw/${SBL_COMMIT_ID}/Silicon/QemuSocPkg/FspBin/Patches/0001-Build-QEMU-FSP-2.0-binaries.patch
SCRIPT_DIR=$(readlink -f "$(dirname "$0")")
WOLFBOOT_DIR="${SCRIPT_DIR}/../../.."
WOLFBOOT_DIR="$(pwd)"
FSP_NAME=QEMU_FSP_DEBUG
CONFIG_FILE=${CONFIG_FILE:-"${WOLFBOOT_DIR}/.config"}
set -e
if [ ! -f "${WOLFBOOT_DIR}/arch.mk" ]; then
echo "Error: Current directory is not the root directory of the source tree"
exit 1
fi
if [ ! -d "$WORK_DIR" ]; then
mkdir -p "$WORK_DIR"
fi
@ -27,10 +32,18 @@ else
fi
download_edkii() {
(cd "$WORK_DIR" &&
git clone "${EDKII_REPO}" edk2 &&
cd edk2 &&
git checkout "${EDKII_TAG}")
if [ ! -d "$WORK_DIR/edk2" ]; then
(cd "$WORK_DIR" &&
git clone "${EDKII_REPO}" edk2)
else
(cd "$WORK_DIR/edk2" &&
git stash save --include-untracked "Auto-stashed on $(date)" &&
git clean -fd) # This will remove untracked files/directories
fi
# Now, checkout the desired tag/branch
(cd "$WORK_DIR/edk2" &&
git checkout "${EDKII_TAG}")
}
download_sbl_patch_and_patch_edkii() {

View File

@ -0,0 +1,73 @@
#/bin/bash
set -e
WOLFBOOT_DIR=$(pwd)
# Parse command line options
while getopts "b" opt; do
case "$opt" in
b)
REBUILD_ONLY=true
;;
*)
echo "Usage: $0 [-b]"
echo "-b : rebuild only (skip FSP build, key gen, ecc)"
exit 1
;;
esac
done
if [ "$REBUILD_ONLY" != true ]; then
CONFIG=x86_fsp_qemu_seal.config
make distclean
cp "config/examples/${CONFIG}" .config
./tools/scripts/x86_fsp/qemu/qemu_build_fsp.sh
make keytools
make tpmtools
# generate one key for images and one for the TPM
./tools/keytools/keygen --force --ecc384 -g wolfboot_signing_private_key.der --ecc256 -g tpm_seal_key.key -keystoreDir src/
fi
# manual add ECC256 for TPM
make CFLAGS_EXTRA="-DHAVE_ECC256"
# test-app
make test-app/image.elf
# compute pcr0 value
PCR0=$(python ./tools/scripts/x86_fsp/compute_pcr.py --target qemu wolfboot_stage1.bin | tail -n 1)
echo $PCR0
./tools/tpm/policy_sign -ecc256 -key=tpm_seal_key.key -pcr=0 -pcrdigest=$PCR0
./tools/scripts/x86_fsp/tpm_install_policy.sh policy.bin.sig
IMAGE=test-app/image.elf SIGN=--ecc384 ./tools/scripts/x86_fsp/qemu/make_hd.sh
echo "RUNNING QEMU"
# launch qemu in background
./tools/scripts/x86_fsp/qemu/qemu.sh -t -p | tee /tmp/qemu_output &
echo "WAITING FOR QEMU TO RUN"
sleep 5
# close qemu
timeout 5 echo 'quit' > /tmp/qemu_mon.in
output=$(cat /tmp/qemu_output)
set +e
app=$(echo "$output" | grep -m 1 "wolfBoot QEMU x86 FSP test app")
if [ -n "$app" ]; then
echo "Found 'wolfBoot QEMU x86 FSP test app' in the output."
else
echo -e "\e[31mTEST FAILED\e[0m"
exit 255
fi
disk_unlocked=$(echo "$output" | grep -m 1 "DISK LOCK SECRET:")
if [ -n "$output" ]; then
echo -e "\e[32mTEST OK\e[0m"
exit 0
else
echo "$output"
echo -e "\e[31mTEST FAILED\e[0m"
exit 255
fi

View File

@ -0,0 +1,60 @@
#!/bin/bash
WOLFBOOT_DIR=$(pwd)
# 16 MB
BIOS_REGION_SIZE=16777216
BIOS_REGION_PATH=/tmp/bios.bin
SIGN_OPTIONS="--ecc384 --sha256"
SIGN_KEY=$WOLFBOOT_DIR/wolfboot_signing_private_key.der
SIGN_TOOL=./tools/keytools/sign
set -e
make_keys()
{
make keytools
./tools/keytools/keygen --ecc384 -g wolfboot_signing_private_key.der --ecc256 -g tpm_seal_key.key -keystoreDir src/
}
build_and_sign_image()
{
# compute the size differences between $FLASH_DUMP and "$WOLFBOOT_DIR"/wolfboot_stage1.bin and store it in SIZE
FLASH_DUMP_SIZE=$(stat -c%s "$FLASH_DUMP")
WOLFBOOT_SIZE=$(stat -c%s "$BIOS_REGION_PATH")
SIZE=$((FLASH_DUMP_SIZE - WOLFBOOT_SIZE))
cp "$FLASH_DUMP" "$WOLFBOOT_DIR/temp_image.bin"
truncate -s $SIZE "$WOLFBOOT_DIR/temp_image.bin"
cat "$WOLFBOOT_DIR/temp_image.bin" "$BIOS_REGION_PATH" > "$WOLFBOOT_DIR/final_image.bin"
PCR0=$(python ./tools/scripts/x86_fsp/compute_pcr.py "$WOLFBOOT_DIR"/final_image.bin | tail -n 1)
"$WOLFBOOT_DIR"/tools/tpm/policy_sign -ecc256 -key=tpm_seal_key.key -pcr=0 -pcrdigest=$PCR0
IMAGE_FILE="$WOLFBOOT_DIR"/final_image.bin "$WOLFBOOT_DIR"/tools/scripts/x86_fsp/tpm_install_policy.sh policy.bin.sig
}
assemble()
{
cp $WOLFBOOT_DIR/wolfboot_stage1.bin $BIOS_REGION_PATH
build_and_sign_image
}
# Parse command line options
while getopts "ks:n:m:" opt; do
case "$opt" in
k)
make_keys
exit 0
;;
n)
FLASH_DUMP="$OPTARG"
IBG=0
;;
*)
echo "Usage: $0 [-k] [-s FLASH_DUMP]"
echo "-k: make keys"
echo "-n FLASH_DUMP: assemble an image for being used without IBG"
exit 1
;;
esac
done
assemble

View File

@ -3,18 +3,23 @@
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
FSP_COMMIT_ID=6f5ae9679e662353bc5570a1bc89e137e262155f
FSP_COMMIT_ID=cfdf71ddce304e411e46d88f5ef635c6a515a54d
FSP_URL=https://github.com/intel/FSP/raw/${FSP_COMMIT_ID}/TigerLakeFspBinPkg/TGL_IOT/Fsp.fd
FSP_REPO=https://github.com/intel/FSP.git
UCODE_URL=https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/raw/6f36ebde4519f8a21a047c3433b80a3fb41361e1/intel-ucode/06-8c-01
SCRIPT_DIR=$(readlink -f "$(dirname "$0")")
WOLFBOOT_DIR="${SCRIPT_DIR}/../../.."
WOLFBOOT_DIR="$(pwd)"
FSP_PREFIX=Fsp
CONFIG_FILE=${CONFIG_FILE:-"${WOLFBOOT_DIR}/.config"}
PATCH="${SCRIPT_DIR}/0001-FSP-wolfboot-patch.patch"
set -e
if [ ! -f "${WOLFBOOT_DIR}/arch.mk" ]; then
echo "Error: Current directory is not the root directory of the source tree"
exit 1
fi
if [ ! -d "$WORK_DIR" ]; then
mkdir -p "$WORK_DIR"
fi

View File

@ -205,7 +205,7 @@ static void printHexString(const unsigned char* bin, unsigned long sz,
printf("\t");
for (i = 0; i < sz; i++) {
printf("%02x", bin[i]);
if (((i+1) % maxLine) == 0 && i+1 != sz)
if (maxLine > 0 && ((i+1) % maxLine) == 0 && i+1 != sz)
printf("\n\t");
}
printf("\n");

View File

@ -1,26 +0,0 @@
#!/bin/bash
SIGN=${SIGN:-"--ecc256"}
HASH=${HASH:-"--sha256"}
IMAGE=${IMAGE:-"bzImage"}
set -e
dd if=/dev/zero of=app.bin bs=1M count=64
/sbin/fdisk app.bin <<EOF
g
n
1
+16M
n
+16M
w
EOF
# copy bzImage in the root folder
tools/keytools/sign $SIGN $HASH ${IMAGE} wolfboot_signing_private_key.der 1
tools/keytools/sign $SIGN $HASH ${IMAGE} wolfboot_signing_private_key.der 2
dd if=${IMAGE}_v1_signed.bin of=app.bin bs=512 seek=2048 conv=notrunc
dd if=${IMAGE}_v2_signed.bin of=app.bin bs=512 seek=34816 conv=notrunc