From aa9272c92bcba34baa11bb6ad83094bbb41c5150 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Tue, 10 Sep 2024 17:34:28 +0200 Subject: [PATCH 1/7] x86: add support for gdt table in C --- arch.mk | 1 + hal/kontron_vx3060_s2.c | 3 ++ hal/x86_fsp_qemu.c | 7 +-- include/x86/gdt.h | 32 ++++++++++++++ src/x86/gdt.c | 96 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 include/x86/gdt.h create mode 100644 src/x86/gdt.c diff --git a/arch.mk b/arch.mk index b517062f35..4ba2bab7bd 100644 --- a/arch.mk +++ b/arch.mk @@ -1012,6 +1012,7 @@ ifeq ("${FSP}", "1") OBJS += src/x86/mptable.o OBJS += src/stage2_params.o OBJS += src/x86/exceptions.o + OBJS += src/x86/gdt.o UPDATE_OBJS := src/update_disk.o CFLAGS+=-DWOLFBOOT_UPDATE_DISK ifeq ($(64BIT),1) diff --git a/hal/kontron_vx3060_s2.c b/hal/kontron_vx3060_s2.c index b642cad6c7..426853c03b 100644 --- a/hal/kontron_vx3060_s2.c +++ b/hal/kontron_vx3060_s2.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef __WOLFBOOT @@ -85,6 +86,8 @@ int tgl_lock_bios_region() void hal_init(void) { + gdt_setup_table(); + gdt_update_segments(); } void hal_prepare_boot(void) diff --git a/hal/x86_fsp_qemu.c b/hal/x86_fsp_qemu.c index c6618752ed..bb84be6200 100644 --- a/hal/x86_fsp_qemu.c +++ b/hal/x86_fsp_qemu.c @@ -26,14 +26,15 @@ #ifdef __WOLFBOOT #include -#include -#include #include -#include +#include +#include #include void hal_init(void) { + gdt_setup_table(); + gdt_update_segments(); } void hal_prepare_boot(void) diff --git a/include/x86/gdt.h b/include/x86/gdt.h new file mode 100644 index 0000000000..96fd9d978c --- /dev/null +++ b/include/x86/gdt.h @@ -0,0 +1,32 @@ +/* gdt.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 GDT_H +#define GDT_H + +#define GDT_DS (0x08) +#define GDT_CS_32BIT (0x10) +#define GDT_CS_64BIT (0x18) +#define GDT_CS_32BIT_COMPAT (0x20) + +int gdt_setup_table(void); +int gdt_update_segments(void); + +#endif /* GDT_H */ diff --git a/src/x86/gdt.c b/src/x86/gdt.c new file mode 100644 index 0000000000..7e3fc82765 --- /dev/null +++ b/src/x86/gdt.c @@ -0,0 +1,96 @@ +/* gdt.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 +#include + +struct segment_descriptor { + uint16_t seg_limit_15_0; + uint16_t base_addr_15_0; + uint8_t base_addr_23_16; + uint8_t type_s_dpl_p; + uint8_t seg_limt_19_16_avl_flags; + uint8_t base_addr_31_24; +} __attribute__((packed)); + +struct gdtr_32 { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + +struct gdtr_64 { + uint16_t limit; + uint64_t base; +} __attribute__((packed)); + +#define SEGMENT_DESCRIPTOR_INIT(base, limit, type, s, dpl, p, avl, l, db, g) { \ + .seg_limit_15_0 = (limit) & 0xffff, \ + .base_addr_15_0 = (base) & 0xffff, \ + .base_addr_23_16 = (((base) >> 16) & 0xff), \ + .type_s_dpl_p = ((type & 0xf) | ((s & 0x1) << 4) | ((dpl & 0x3) << 5) | ((p & 0x1) << 7)), \ + .seg_limt_19_16_avl_flags = ((((limit) >> 16) & 0xf) | ((avl & 0x1) << 4) | ((l & 0x1) << 5) | ((db & 0x1) << 6) | ((g & 0x1) << 7)), \ + .base_addr_31_24 = ((base) >> 24) & 0xff, \ +} + +#define GDT_NUM_ENTRIES 5 + +struct segment_descriptor gdt[GDT_NUM_ENTRIES] = { + /* NULL */ + SEGMENT_DESCRIPTOR_INIT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + /* Data */ + SEGMENT_DESCRIPTOR_INIT(0, 0xffffffff, 0x3, 1, 0, 1, 0, 0, 1, 1), + /* Code (32bit) */ + SEGMENT_DESCRIPTOR_INIT(0, 0xffffffff, 0xb, 1, 0, 1, 0, 0, 1, 1), + /* Code (64bit) */ + SEGMENT_DESCRIPTOR_INIT(0, 0xffffffff, 0xb, 1, 0, 1, 0, 1, 0, 1), + /* Code (64bit) compat mode */ + SEGMENT_DESCRIPTOR_INIT(0, 0xffffffff, 0xb, 1, 0, 1, 0, 0, 1, 1), +}; + +int gdt_setup_table(void) +{ + struct gdtr_64 gdtr; + gdtr.limit = sizeof(gdt) - 1; + gdtr.base = (uint64_t)(uintptr_t)gdt; + __asm__ volatile ("lgdt %0" : : "m" (gdtr)); + return 0; +} + +int gdt_update_segments(void) +{ + __asm__ volatile ( + "mov %0, %%ax\r\n" + "mov %%ax, %%ds\r\n" + "mov %%ax, %%es\r\n" + "mov %%ax, %%fs\r\n" + "mov %%ax, %%gs\r\n" + "mov %%ax, %%ss\r\n" + "push %1\r\n" + "lea (seg_cs), %%rax\r\n" + "push %%rax\r\n" + "retfq\r\n" + "seg_cs:\r\n" + : + : "i"(GDT_DS), "i" (GDT_CS_64BIT) + : "rax" + ); + return 0; +} From 6f9e2923dbe35904edd9ad8c6d4e5c6b10258bf0 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Tue, 10 Sep 2024 18:45:25 +0200 Subject: [PATCH 2/7] x86: add wrapper to run 32bit code in 64bit long mode --- include/x86/common.h | 1 + src/x86/common.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/include/x86/common.h b/include/x86/common.h index 78ed9159dc..7e80b36028 100644 --- a/include/x86/common.h +++ b/include/x86/common.h @@ -68,4 +68,5 @@ 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(); +int x86_run_fsp_32bit(void* api, void* arg); #endif /* COMMON_H */ diff --git a/src/x86/common.c b/src/x86/common.c index 9ce09de040..2443037070 100644 --- a/src/x86/common.c +++ b/src/x86/common.c @@ -35,6 +35,7 @@ #include #include +#include #define barrier() __asm__ __volatile__ ("":::"memory"); @@ -371,4 +372,89 @@ void x86_log_memory_load(uint32_t start, uint32_t end, const char *name) { wolfBoot_printf("mem: [ 0x%x, 0x%x ] - %s (0x%x) \n\r", start, end, name, end - start); } + +#if !defined(BUILD_LOADER_STAGE1) +int x86_run_fsp_32bit(void* api, void* arg) +{ + uint32_t status; + __asm__ volatile ( + /* arg on the stack, will be used as arg */ + "mov %[arg], %%rax\n" + "shl $32, %%rax\n" + "or %[api], %%rax\n" + "push %%rax\n" + "push %[SEG_COMP]\n" + "lea (1f), %%rax\n" + "push %%rax\n" + "retfq\n" + "1:\n" + /* we are now in compatibility mode */ + ".code32\n" + /* disable paging */ + "mov %%cr0, %%eax\n" + "mov %[PG], %%edx\n" + "not %%edx\n" + "and %%edx, %%eax\n" + "mov %%eax, %%cr0\n" + /* disable EFER.LME */ + "mov $0xc0000080, %%ecx\n" + "rdmsr\n" + "mov %[LME], %%ecx\n" + "not %%ecx\n" + "and %%ecx, %%eax\n" + "mov $0xc0000080, %%ecx\n" + "wrmsr\n" + /* disable PAE */ + "mov %%cr4, %%eax\n" + "mov %[PAE], %%edx\n" + "not %%edx\n" + "and %%edx, %%eax\n" + "mov %%eax, %%cr4\n" + /* get api from stack */ + "pop %%eax\n" + "call *%%eax\n" + /* remove parameter from the stack */ + "add $4, %%esp\n" + /* save status to ebx */ + "mov %%eax, %%ebx\n" + /* enable PAE */ + "mov %%cr4, %%eax\n" + "or %[PAE], %%eax\n" + "mov %%eax, %%cr4\n" + /* enable EFER_LME */ + "mov $0xc0000080, %%ecx\n" + "rdmsr\n" + "or %[LME], %%eax\n" + "mov $0xc0000080, %%ecx\n" + "wrmsr\n" + /* setup far pointer on the stack */ + "push %[SEG_LONG]\n" + "push $2f\n" + /* enable paging */ + "mov %%cr0, %%eax\n" + "or %[PG], %%eax\n" + "mov %%eax, %%cr0\n" + "retf\n" + "2:\n" + /* back in long mode */ + ".code64\n" + /* save status */ + "mov %%ebx, %[status]\n" + :[status]"=m"(status) + :[SEG_COMP]"i"(GDT_CS_32BIT_COMPAT), + [SEG_LONG]"i"(GDT_CS_64BIT), + [PG]"i"(CR0_PG_BIT), + [LME]"i"(IA32_EFER_LME), + [PAE]"i"(CR4_PAE_BIT), + [api]"r"(api), + [arg]"r"(arg) + : "rax", "rbx", "rcx", "rdx"); + return status; +} +#else +int x86_run_fsp_32bit(void* api, void* arg) +{ + return 0; +} +#endif /* !STAGE1 */ #endif /* COMMON_H_ */ From 7f48d4b5fa5e2906812808ba49ea28fd8b727519 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Wed, 11 Sep 2024 16:11:23 +0200 Subject: [PATCH 3/7] fsp: refactor out common fsp routines --- arch.mk | 2 + include/x86/fsp.h | 31 +++++++++++++++ src/boot_x86_fsp.c | 60 +---------------------------- src/x86/fsp.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 59 deletions(-) create mode 100644 include/x86/fsp.h create mode 100644 src/x86/fsp.c diff --git a/arch.mk b/arch.mk index 4ba2bab7bd..42a3f00243 100644 --- a/arch.mk +++ b/arch.mk @@ -968,6 +968,7 @@ ifeq ("${FSP}", "1") OBJS += hal/x86_uart.o OBJS += src/string.o OBJS += src/stage2_params.o + OBJS += src/x86/fsp.o ifeq ($(filter-out $(STAGE1_AUTH),1),) OBJS += src/libwolfboot.o OBJS += src/image.o @@ -1013,6 +1014,7 @@ ifeq ("${FSP}", "1") OBJS += src/stage2_params.o OBJS += src/x86/exceptions.o OBJS += src/x86/gdt.o + OBJS += src/x86/fsp.o UPDATE_OBJS := src/update_disk.o CFLAGS+=-DWOLFBOOT_UPDATE_DISK ifeq ($(64BIT),1) diff --git a/include/x86/fsp.h b/include/x86/fsp.h new file mode 100644 index 0000000000..b825d427f2 --- /dev/null +++ b/include/x86/fsp.h @@ -0,0 +1,31 @@ +/* fsp.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 FSP_H +#define FSP_H + +#include + +int fsp_info_header_is_ok(struct fsp_info_header *hdr); +int fsp_get_image_revision(struct fsp_info_header *h, int *build, + int *rev, int *maj, int *min); +void print_fsp_image_revision(struct fsp_info_header *h); + +#endif /* FSP_H */ diff --git a/src/boot_x86_fsp.c b/src/boot_x86_fsp.c index 4718f28d55..b19ca3e559 100644 --- a/src/boot_x86_fsp.c +++ b/src/boot_x86_fsp.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -351,65 +352,6 @@ 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) { diff --git a/src/x86/fsp.c b/src/x86/fsp.c new file mode 100644 index 0000000000..f5e5e1b067 --- /dev/null +++ b/src/x86/fsp.c @@ -0,0 +1,96 @@ +/* fsp_tgl.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 +#include +#include +#include +#include + +#define FSP_INFO_HEADER_OFFSET 0x94 +#define EFI_SUCCESS 0x0 + +#ifndef FSP_S_PARAM_SIZE +#define FSP_S_PARAM_SIZE 0xee0 +#endif + +#define PCI_DEVICE_CONTROLLER_TO_PEX 0x6 + + +int fsp_machine_update_s_parameters(uint8_t *default_s_params); +int fsp_pre_silicon_init_cb(void); +/*! + * \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 1j if the FSP info header is valid, 0 otherwise. + */ +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; +} + +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; +} + +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); +} From 291e822fab32a0cd610dd52f05dd8acd8aac3d82 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Tue, 17 Dec 2024 17:05:13 +0000 Subject: [PATCH 4/7] fsp: minor: remove unused parameter from jump_into_wolfboot --- src/boot_x86_fsp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/boot_x86_fsp.c b/src/boot_x86_fsp.c index b19ca3e559..0e559f5801 100644 --- a/src/boot_x86_fsp.c +++ b/src/boot_x86_fsp.c @@ -252,7 +252,6 @@ static void load_fsp_s_to_ram(void) static void jump_into_wolfboot(void) { struct stage2_parameter *params; - uint32_t cr3; int ret; params = stage2_get_parameters(); From f3d215043fe157f4470862d66ce4e6950f8bada3 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Wed, 11 Sep 2024 17:00:31 +0200 Subject: [PATCH 5/7] fsp: move TempRamInitExit and later APIs in stage2 To avoid using Flash memory after TempRamInitExit. This protects against malicious modification/injection of the flash after Cache-As-RAM is disabled. --- Makefile | 6 +- arch.mk | 12 +- config/examples/x86_fsp_qemu_seal.config | 1 - hal/kontron_vx3060_s2.c | 2 + hal/x86_fsp_qemu.c | 2 + hal/x86_fsp_qemu.ld.in | 13 +- hal/x86_fsp_qemu_stage1.ld.in | 10 -- hal/x86_fsp_tgl.ld.in | 11 ++ hal/x86_fsp_tgl_stage1.ld.in | 10 -- include/x86/fsp.h | 1 + src/boot_x86_fsp.c | 203 +---------------------- src/x86/fsp.c | 90 ++++++++++ src/x86/tgl_fsp.c | 7 +- stage1/x86_fsp.mk | 8 - tools/scripts/x86_fsp/compute_pcr.py | 4 - 15 files changed, 144 insertions(+), 236 deletions(-) diff --git a/Makefile b/Makefile index cf9fdec2d0..be8d577c3b 100644 --- a/Makefile +++ b/Makefile @@ -315,7 +315,8 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE sed -e "s/@WOLFBOOT_STAGE1_BASE_ADDR@/$(WOLFBOOT_STAGE1_BASE_ADDR)/g" | \ sed -e "s/@WOLFBOOT_LOAD_BASE@/$(WOLFBOOT_LOAD_BASE)/g" | \ sed -e "s/@BOOTLOADER_START@/$(BOOTLOADER_START)/g" | \ - sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" \ + sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \ + sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" \ > $@ hex: wolfboot.hex @@ -447,6 +448,9 @@ secondary: $(SECONDARY_PRIVATE_KEY) @echo "\t[AS-$(ARCH)] $@" $(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^ +src/x86/fsp_s.o: $(FSP_S_BIN) + $(OBJCOPY) -I binary -O elf64-x86-64 -B i386 --rename-section .data=.fsp_s $^ $@ + FORCE: .PHONY: FORCE clean keytool_check diff --git a/arch.mk b/arch.mk index 42a3f00243..24f0d3ad50 100644 --- a/arch.mk +++ b/arch.mk @@ -930,9 +930,7 @@ ifeq ($(filter $(TARGET),x86_fsp_qemu kontron_vx3060_s2),$(TARGET)) endif ifeq ($(TARGET),x86_fsp_qemu) - ifeq ($(filter-out $(STAGE1),1),) OBJS+=src/x86/qemu_fsp.o - endif endif # x86-64 FSP targets @@ -958,7 +956,6 @@ ifeq ("${FSP}", "1") OBJS += src/boot_x86_fsp.o OBJS += src/boot_x86_fsp_start.o OBJS += src/fsp_m.o - OBJS += src/fsp_s.o OBJS += src/fsp_t.o OBJS += src/wolfboot_raw.o OBJS += src/x86/common.o @@ -974,7 +971,6 @@ ifeq ("${FSP}", "1") OBJS += src/image.o OBJS += src/keystore.o OBJS += src/sig_wolfboot_raw.o - OBJS += src/sig_fsp_s.o ifeq ($(TARGET), kontron_vx3060_s2) OBJS += hal/kontron_vx3060_s2_loader.o endif @@ -983,6 +979,7 @@ ifeq ("${FSP}", "1") endif CFLAGS += -fno-stack-protector -m32 -fno-PIC -fno-pie -mno-mmx -mno-sse -DDEBUG_UART + CFLAGS += -DFSP_M_BASE=$(FSP_M_BASE) ifeq ($(FSP_TGL), 1) OBJS+=src/x86/tgl_fsp.o OBJS+=src/ucode0.o @@ -1000,6 +997,7 @@ ifeq ("${FSP}", "1") endif 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 + CFLAGS += -DFSP_M_BASE=$(FSP_M_BASE) OBJS += hal/x86_fsp_tgl.o OBJS += hal/x86_uart.o OBJS += src/boot_x86_fsp_payload.o @@ -1015,6 +1013,7 @@ ifeq ("${FSP}", "1") OBJS += src/x86/exceptions.o OBJS += src/x86/gdt.o OBJS += src/x86/fsp.o + OBJS += src/x86/fsp_s.o UPDATE_OBJS := src/update_disk.o CFLAGS+=-DWOLFBOOT_UPDATE_DISK ifeq ($(64BIT),1) @@ -1023,7 +1022,10 @@ ifeq ("${FSP}", "1") else CFLAGS += -m32 LDFLAGS += -m elf_i386 --oformat elf32-i386 - endif + endif + ifeq ($(FSP_TGL), 1) + OBJS+=src/x86/tgl_fsp.o + endif endif ifeq ($(64BIT),1) OBJS += src/x86/paging.o diff --git a/config/examples/x86_fsp_qemu_seal.config b/config/examples/x86_fsp_qemu_seal.config index ab1bbca937..fdf5d7c927 100644 --- a/config/examples/x86_fsp_qemu_seal.config +++ b/config/examples/x86_fsp_qemu_seal.config @@ -24,7 +24,6 @@ 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=0xfff80000 diff --git a/hal/kontron_vx3060_s2.c b/hal/kontron_vx3060_s2.c index 426853c03b..bedb31d14e 100644 --- a/hal/kontron_vx3060_s2.c +++ b/hal/kontron_vx3060_s2.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef __WOLFBOOT @@ -88,6 +89,7 @@ void hal_init(void) { gdt_setup_table(); gdt_update_segments(); + fsp_init_silicon(); } void hal_prepare_boot(void) diff --git a/hal/x86_fsp_qemu.c b/hal/x86_fsp_qemu.c index bb84be6200..7ca5df9401 100644 --- a/hal/x86_fsp_qemu.c +++ b/hal/x86_fsp_qemu.c @@ -29,12 +29,14 @@ #include #include #include +#include #include void hal_init(void) { gdt_setup_table(); gdt_update_segments(); + fsp_init_silicon(); } void hal_prepare_boot(void) diff --git a/hal/x86_fsp_qemu.ld.in b/hal/x86_fsp_qemu.ld.in index 1ba33161ff..cfecbbfcb5 100644 --- a/hal/x86_fsp_qemu.ld.in +++ b/hal/x86_fsp_qemu.ld.in @@ -1,5 +1,6 @@ MEM_SIZE = 536870912; WOLFBOOT_LOAD_BASE = @WOLFBOOT_LOAD_BASE@; +FSP_S_LOAD_BASE = @FSP_S_LOAD_BASE@; MEMORY { @@ -16,11 +17,15 @@ SECTIONS *(.rodata*) *(.keystore*) *(.data*) + _start_fsp_s = .; + KEEP(*(.fsp_s)) + _end_fsp_s = .; . = ALIGN(4); _end_text = .; _end_wolfboot = .; - } + } > RAM + _fsp_size = _end_fsp_s - _start_fsp_s; .bss WOLFBOOT_LOAD_BASE + SIZEOF(.text) (NOLOAD): { _start_bss = .; @@ -31,5 +36,11 @@ SECTIONS _end_bss = .; __bss_end__ = .; _end_wb = .; + } > RAM + + .fsp_s_base FSP_S_LOAD_BASE (NOLOAD) : + { + _fsp_s_base_start = .; + . += _fsp_size; } } diff --git a/hal/x86_fsp_qemu_stage1.ld.in b/hal/x86_fsp_qemu_stage1.ld.in index c0e0e6a579..962cd8f09b 100644 --- a/hal/x86_fsp_qemu_stage1.ld.in +++ b/hal/x86_fsp_qemu_stage1.ld.in @@ -5,7 +5,6 @@ RESETVECTOR_START = 0xffffffec; KEYSTORE_START = 0xffffe000; FSP_T_ORIGIN = @FSP_T_BASE@; /* default base:size 0xFFFFF000:0x3000 [0xfffff000:0x100002000] */ FSP_M_ORIGIN = @FSP_M_BASE@; /* default base:size 0xfffdd000:0x22000 [0xfffdd000:0xfffff000] */ -FSP_S_ORIGIN = @FSP_S_BASE@; /* default base:size 0xfffc8000:0x15000 [0xfffdd000:0xfffdd000] */ WOLFBOOT_ORIGIN = @WOLFBOOT_ORIGIN@; DATA_MEM_START = 0x800000; /* 8 MB */ MAX_POLICY_SIZE = 512; @@ -92,15 +91,6 @@ SECTIONS KEEP(*(.fsp_t)) } - .fsp_s FSP_S_ORIGIN : - { - _fsp_s_hdr = .; - KEEP(*(.sig_fsp_s*)) - _start_fsp_s = .; - KEEP(*(.fsp_s)) - _end_fsp_s = .; - } - .fsp_m FSP_M_ORIGIN : { _start_fsp_m = .; diff --git a/hal/x86_fsp_tgl.ld.in b/hal/x86_fsp_tgl.ld.in index 1ba33161ff..1ec85c53f1 100644 --- a/hal/x86_fsp_tgl.ld.in +++ b/hal/x86_fsp_tgl.ld.in @@ -1,5 +1,6 @@ MEM_SIZE = 536870912; WOLFBOOT_LOAD_BASE = @WOLFBOOT_LOAD_BASE@; +FSP_S_LOAD_BASE = @FSP_S_LOAD_BASE@; MEMORY { @@ -16,11 +17,15 @@ SECTIONS *(.rodata*) *(.keystore*) *(.data*) + _start_fsp_s = .; + KEEP(*(.fsp_s)) + _end_fsp_s = .; . = ALIGN(4); _end_text = .; _end_wolfboot = .; } + _fsp_size = _end_fsp_s - _start_fsp_s; .bss WOLFBOOT_LOAD_BASE + SIZEOF(.text) (NOLOAD): { _start_bss = .; @@ -32,4 +37,10 @@ SECTIONS __bss_end__ = .; _end_wb = .; } + + .fsp_s_base FSP_S_LOAD_BASE (NOLOAD) : + { + _fsp_s_base_start = .; + . = . + _fsp_size; + } } diff --git a/hal/x86_fsp_tgl_stage1.ld.in b/hal/x86_fsp_tgl_stage1.ld.in index 0d9b6f316e..4b7c0ca7bd 100644 --- a/hal/x86_fsp_tgl_stage1.ld.in +++ b/hal/x86_fsp_tgl_stage1.ld.in @@ -2,7 +2,6 @@ FLASH_SIZE = @BOOTLOADER_PARTITION_SIZE@; FLASH_START = 0x100000000 - @BOOTLOADER_PARTITION_SIZE@; UCODE0_BASE = @UCODE0_BASE@; FIT_TABLE = 0xffe00000; -FSP_S_ORIGIN = @FSP_S_BASE@; WOLFBOOT_ORIGIN = @WOLFBOOT_ORIGIN@; FSP_T_ORIGIN = @FSP_T_BASE@; FSP_M_ORIGIN = @FSP_M_BASE@; @@ -52,15 +51,6 @@ SECTIONS . = ALIGN(256*1024); } - .fsp_s FSP_S_ORIGIN : - { - _fsp_s_hdr = .; - KEEP(*(.sig_fsp_s*)) - _start_fsp_s = .; - KEEP(*(.fsp_s)) - _end_fsp_s = .; - } > FLASH - .bootloader WOLFBOOT_ORIGIN : { KEEP(./tgl_fsp.o(.boot)) diff --git a/include/x86/fsp.h b/include/x86/fsp.h index b825d427f2..c994d3f4ea 100644 --- a/include/x86/fsp.h +++ b/include/x86/fsp.h @@ -27,5 +27,6 @@ int fsp_info_header_is_ok(struct fsp_info_header *hdr); int fsp_get_image_revision(struct fsp_info_header *h, int *build, int *rev, int *maj, int *min); void print_fsp_image_revision(struct fsp_info_header *h); +void fsp_init_silicon(void); #endif /* FSP_H */ diff --git a/src/boot_x86_fsp.c b/src/boot_x86_fsp.c index 0e559f5801..4eda60e656 100644 --- a/src/boot_x86_fsp.c +++ b/src/boot_x86_fsp.c @@ -68,9 +68,6 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw"))) #define FSP_M_UDP_MAX_SIZE 0x978 #endif -#ifndef FSP_S_PARAM_SIZE -#define FSP_S_PARAM_SIZE 0xee0 -#endif /* Amount of car memory to provide to FSP-M, machine dependent, find the value * in the integration guide */ @@ -86,22 +83,14 @@ 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) /* compile time alignment checks */ #define ALIGN_CHECK(value, alignment) ((value) & ((alignment)-1)) == 0 -#if !ALIGN_CHECK(FSP_S_LOAD_BASE - IMAGE_HEADER_SIZE, 16) -#error "FSP_S_LOAD_BASE must be aligned on a 16 bytes boundary" -#endif #if !ALIGN_CHECK(WOLFBOOT_LOAD_BASE - IMAGE_HEADER_SIZE, 16) #error "WOLFBOOT_LOAD_BASE must be aligned on a 16 bytes boundary" #endif 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); -typedef uint32_t (*notify_phase_cb)(NOTIFY_PHASE_PARAMS *p); /* need to be implemented by machine dependent code */ int fsp_machine_update_m_parameters(uint8_t *default_m_params, @@ -114,9 +103,7 @@ 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[]; -extern uint8_t _end_fsp_s[]; extern uint8_t _wolfboot_flash_start[]; extern uint8_t _wolfboot_flash_end[]; extern uint8_t wb_end_bss[], wb_start_bss[]; @@ -232,16 +219,6 @@ static void load_wolfboot(void) wolfBoot_printf("load wolfboot end" ENDLINE); } -static void load_fsp_s_to_ram(void) -{ - size_t fsp_s_size; - uint32_t fsp_start; - fsp_start = FSP_S_LOAD_BASE - IMAGE_HEADER_SIZE; - fsp_s_size = _end_fsp_s - _fsp_s_hdr; - x86_log_memory_load(fsp_start, fsp_start + fsp_s_size, "FSPS"); - memcpy((uint8_t*)fsp_start, _fsp_s_hdr, fsp_s_size); -} - #ifdef WOLFBOOT_64BIT /*! * \brief Jump into the WolfBoot bootloader. @@ -372,124 +349,6 @@ static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun, 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 - * - * Setpu the parameters and call FSP Silicon Initialization. - * - * \param fsp_info FSP information header - * \param fsp_s_base the area in RAM where FSP_S has been loaded and verified - * \return EFI_SUCCESS in case of success, -1 otherwise - */ -static int fsp_silicon_init(struct fsp_info_header *fsp_info, uint8_t *fsp_s_base) -{ - uint8_t silicon_init_parameter[FSP_S_PARAM_SIZE]; - silicon_init_cb SiliconInit; - notify_phase_cb notifyPhase; - NOTIFY_PHASE_PARAMS param; - uint32_t status; - unsigned int i; - int ret; - - memcpy(silicon_init_parameter, fsp_s_base + fsp_info->CfgRegionOffset, - FSP_S_PARAM_SIZE); - status = fsp_machine_update_s_parameters(silicon_init_parameter); - if (status != 0) - panic(); - 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) { - wolfBoot_printf("failed %x\n", status); - 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; - status = notifyPhase(¶m); - if (status != EFI_SUCCESS) { - wolfBoot_printf("failed %d: %x\n", __LINE__, status); - return -1; - } - param.Phase = EnumInitPhaseReadyToBoot; - status = notifyPhase(¶m); - if (status != EFI_SUCCESS) { - wolfBoot_printf("failed %d: %x\n", __LINE__, status); - return -1; - } - param.Phase = EnumInitPhaseEndOfFirmware; - status = notifyPhase(¶m); - if (status != EFI_SUCCESS) { - wolfBoot_printf("failed %d: %x\n", __LINE__, status); - return -1; - } - return EFI_SUCCESS; -} #if defined(TARGET_x86_fsp_qemu) && defined(WOLFBOOT_MEASURED_BOOT) /*! @@ -536,31 +395,16 @@ static int self_extend_pcr(void) * memory initialization is completed and the stack has been remapped. * */ -static void memory_ready_entry(void) +static void memory_ready_entry(uint32_t new_stack) { struct fsp_info_header *fsp_info; - temp_ram_exit_cb TempRamExit; uint8_t *fsp_s_base; uint8_t *fsp_m_base; 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 */ - fsp_s_base = (uint8_t *)(FSP_S_LOAD_BASE); - fsp_info = - (struct fsp_info_header *)(fsp_m_base + FSP_INFO_HEADER_OFFSET); - TempRamExit = (temp_ram_exit_cb)(fsp_m_base + - fsp_info->TempRamExitEntryOffset); - status = TempRamExit(NULL); - if (status != EFI_SUCCESS) { - wolfBoot_printf("temp ram exit failed" ENDLINE); - panic(); - } /* Confirmed memory initialization complete. - * TempRamExit was successful. * * Copy .data section to RAM and initialize .bss */ @@ -588,35 +432,6 @@ static void memory_ready_entry(void) wolfBoot_printf("fail to extend PCR" ENDLINE); #endif - /* Load FSP_S to RAM */ - load_fsp_s_to_ram(); -#ifdef STAGE1_AUTH - /* Verify FSP_S */ - wolfBoot_printf("Authenticating FSP_S at %x..." ENDLINE, - fsp_s_base - IMAGE_HEADER_SIZE); - - if (verify_payload(fsp_s_base - IMAGE_HEADER_SIZE) == 0) - wolfBoot_printf("FSP_S: verified OK." ENDLINE); - else { - panic(); - } -#endif - -#if defined(WOLFBOOT_MEASURED_BOOT) - ret = wolfBoot_image_measure((uint8_t*)fsp_s_base - IMAGE_HEADER_SIZE); - if (ret != 0) { - wolfBoot_printf("Fail to measure FSP_S image\r\n"); - panic(); - } -#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 */ cpuid(0, &cpu_info[0], &cpu_info[1], &cpu_info[2], NULL); wolfBoot_printf("CPUID(0):%x %x %x\r\n", cpu_info[0], cpu_info[1], cpu_info[2]); @@ -646,8 +461,12 @@ static void memory_ready_entry(void) (defined(STAGE1_AUTH) && defined (WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_VERIFY)) wolfBoot_tpm2_deinit(); #endif - /* Finalize staging to stage2 */ - jump_into_wolfboot(); + /* change_stack_and_invoke() never returns. + * + * Execution here is eventually transferred to jump_into_wolfboot, that + * will transfer the execution to stage2 after the stack has been remapped. + */ + change_stack_and_invoke(new_stack, jump_into_wolfboot); } static void print_ucode_revision(void) @@ -831,15 +650,9 @@ void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp, 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); + memory_ready_entry(new_stack); /* Returning from change_stack_and_invoke() implies a fatal error - * while attempting to remap the stack. */ wolfBoot_printf("FAIL" ENDLINE); panic(); diff --git a/src/x86/fsp.c b/src/x86/fsp.c index f5e5e1b067..1a557ed59f 100644 --- a/src/x86/fsp.c +++ b/src/x86/fsp.c @@ -23,6 +23,7 @@ #include #include #include +#include #define FSP_INFO_HEADER_OFFSET 0x94 #define EFI_SUCCESS 0x0 @@ -33,6 +34,9 @@ #define PCI_DEVICE_CONTROLLER_TO_PEX 0x6 +static uint8_t *_start_fsp_m = (uint8_t*)FSP_M_BASE; +extern uint8_t _start_fsp_s[], _end_fsp_s[]; +extern uint8_t _fsp_s_base_start[]; int fsp_machine_update_s_parameters(uint8_t *default_s_params); int fsp_pre_silicon_init_cb(void); @@ -94,3 +98,89 @@ void print_fsp_image_revision(struct fsp_info_header *h) } wolfBoot_printf("%x.%x.%x build %x\r\n", maj, min, rev, build); } + +void fsp_init_silicon(void) +{ + uint8_t silicon_init_parameter[FSP_S_PARAM_SIZE]; + struct fsp_info_header *fsp_m_hdr; + struct fsp_info_header *fsp_s_hdr; + NOTIFY_PHASE_PARAMS param; + uint32_t tmp_ram_exit_off; + uint32_t silicon_init_off; + uint32_t notify_phase_off; + uint8_t *tmp_ram_exit; + uint8_t *silicon_init; + uint8_t *notify_phase; + uint32_t status; + + fsp_m_hdr = (struct fsp_info_header*)(_start_fsp_m + FSP_INFO_HEADER_OFFSET); + if (!fsp_info_header_is_ok(fsp_m_hdr)) { + wolfBoot_printf("invalid FSP_INFO_HEADER"); + panic(); + } + tmp_ram_exit_off = fsp_m_hdr->TempRamExitEntryOffset; + if (tmp_ram_exit_off == 0) { + wolfBoot_printf("temp ram offset wrong"); + panic(); + } + tmp_ram_exit = _start_fsp_m + tmp_ram_exit_off; + wolfBoot_printf("call temp ram exit..."); + status = x86_run_fsp_32bit(tmp_ram_exit, NULL); + if (status != EFI_SUCCESS) { + wolfBoot_printf("temp ram exit failed"); + panic(); + } + wolfBoot_printf("success"); + memcpy(_fsp_s_base_start, _start_fsp_s, _end_fsp_s - _start_fsp_s); + fsp_s_hdr = (struct fsp_info_header*)(_fsp_s_base_start + FSP_INFO_HEADER_OFFSET); + silicon_init_off = fsp_s_hdr->FspSiliconInitEntryOffset; + if (silicon_init_off == 0) { + wolfBoot_printf("temp ram offset wrong"); + panic(); + } + memcpy(silicon_init_parameter, _fsp_s_base_start + fsp_s_hdr->CfgRegionOffset, + FSP_S_PARAM_SIZE); + status = fsp_machine_update_s_parameters(silicon_init_parameter); + if (status != 0) + panic(); + status = fsp_pre_silicon_init_cb(); + if (status != 0) { + wolfBoot_printf("Pre silicon init cb returns %d", status); + panic(); + } + print_fsp_image_revision((struct fsp_info_header *)fsp_s_hdr); + wolfBoot_printf("call silicon..."); + silicon_init = _fsp_s_base_start + silicon_init_off; + status = x86_run_fsp_32bit(silicon_init, silicon_init_parameter); + if (status != EFI_SUCCESS) { + wolfBoot_printf("silicon init failed returned %d\n", status); + panic(); + } + wolfBoot_printf("success"); + pci_enum_do(); + pci_dump_config_space(); + notify_phase_off = fsp_s_hdr->NotifyPhaseEntryOffset; + if (notify_phase_off == 0) { + wolfBoot_printf("notify_phase offset wrong"); + panic(); + } + notify_phase = _start_fsp_s + notify_phase_off; + param.Phase = EnumInitPhaseAfterPciEnumeration; + status = x86_run_fsp_32bit(notify_phase, ¶m); + if (status != EFI_SUCCESS) { + wolfBoot_printf("notify phase failed %d\n", status); + panic(); + } + param.Phase = EnumInitPhaseReadyToBoot; + status = x86_run_fsp_32bit(notify_phase, ¶m); + if (status != EFI_SUCCESS) { + wolfBoot_printf("notify phase failed %d\n", status); + panic(); + } + param.Phase = EnumInitPhaseEndOfFirmware; + status = x86_run_fsp_32bit(notify_phase, ¶m); + if (status != EFI_SUCCESS) { + wolfBoot_printf("notify phase failed %d\n", status); + panic(); + } +} diff --git a/src/x86/tgl_fsp.c b/src/x86/tgl_fsp.c index 2e8a3dcff0..9c8a082329 100644 --- a/src/x86/tgl_fsp.c +++ b/src/x86/tgl_fsp.c @@ -158,6 +158,7 @@ SI_PCH_DEVICE_INTERRUPT_CONFIG mPchHDevIntConfig[] = { {30, 0, SiPchIntA, 16}, }; +#if defined(BUILD_LOADER_STAGE1) #define FIT_NUM_ENTRIES 2 __attribute__((__section__(".boot"))) const struct fit_table_entry fit_table[FIT_NUM_ENTRIES] = { @@ -462,6 +463,7 @@ static int fsp_set_memory_cfg(FSPM_UPD *udp) mem_cfg->PcieRefPllSsc = 0; return 0; } +#endif /* BUILD_LOADER_STAGE1 */ static int disable_watchdog_tco() { @@ -935,7 +937,8 @@ int fsp_machine_update_s_parameters(uint8_t *default_s_params) upd->MicrocodeRegionBase = 0x0; upd->MicrocodeRegionSize = 0x0; - upd->DevIntConfigPtr = (uint32_t)mPchHDevIntConfig; + /* we can assume that is under 4gb */ + upd->DevIntConfigPtr = (uint32_t)(uintptr_t)mPchHDevIntConfig; upd->NumOfDevIntConfig = sizeof(mPchHDevIntConfig)/sizeof(mPchHDevIntConfig[0]); upd->SataEnable = 1; upd->SataMode = 0; @@ -1641,6 +1644,7 @@ int post_temp_ram_init_cb(void) return 0; } +#if defined(BUILD_LOADER_STAGE1) /** * @brief Update M parameters in FSPM_UPD structure. * @@ -1683,6 +1687,7 @@ int fsp_pre_mem_init_cb(void) return 0; } +#endif /* BUILD_LOADER_STAGE1 */ int fsp_pre_silicon_init_cb(void) { diff --git a/stage1/x86_fsp.mk b/stage1/x86_fsp.mk index cfa7e2ed27..f367679ea4 100644 --- a/stage1/x86_fsp.mk +++ b/stage1/x86_fsp.mk @@ -24,8 +24,6 @@ fsp_t.o: ../$(FSP_T_BIN) fsp_m.o: ../$(FSP_M_BIN) $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsp_m $^ $@ -fsp_s.o: ../$(FSP_S_BIN) - $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.fsp_s $^ $@ wolfboot_raw.bin: ../wolfboot.elf $(Q)$(OBJCOPY) -j .text -O binary $^ $@ @@ -33,12 +31,6 @@ wolfboot_raw.bin: ../wolfboot.elf wolfboot_raw.o: wolfboot_raw.bin $(OBJCOPY) -I binary -O elf32-i386 -B i386 --rename-section .data=.wolfboot $^ $@ -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_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 diff --git a/tools/scripts/x86_fsp/compute_pcr.py b/tools/scripts/x86_fsp/compute_pcr.py index 2f5b07362d..db3af5012b 100644 --- a/tools/scripts/x86_fsp/compute_pcr.py +++ b/tools/scripts/x86_fsp/compute_pcr.py @@ -109,10 +109,6 @@ def pcr_extend(pcr: bytearray, data: bytearray) -> bytearray: 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()}") From edeee1bbf174bdd81ae2f380d5dc8523041912cb Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 19 Dec 2024 16:43:44 +0000 Subject: [PATCH 6/7] gpt: fix spelling error --- include/x86/gpt.h | 2 +- src/x86/gpt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/x86/gpt.h b/include/x86/gpt.h index 7656bef95c..faa34298e0 100644 --- a/include/x86/gpt.h +++ b/include/x86/gpt.h @@ -24,5 +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); +int disk_find_partition_by_label(int drv, const char *label); #endif diff --git a/src/x86/gpt.c b/src/x86/gpt.c index 0cd66b7b08..096e38e643 100644 --- a/src/x86/gpt.c +++ b/src/x86/gpt.c @@ -358,7 +358,7 @@ int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf) return ret; } -int disk_find_partion_by_label(int drv, const char *label) +int disk_find_partition_by_label(int drv, const char *label) { struct disk_partition *p; int i; From 0f983867852372ff346ec5ca72245a472ac7f7fe Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Thu, 19 Dec 2024 16:44:17 +0000 Subject: [PATCH 7/7] kontron-vx3060-s2: simplify example, add build test, improve docs --- .../test-build-kontron-vx3060-s2.yml | 25 +++++ config/examples/kontron_vx3060_s2.config | 19 +--- docs/Targets.md | 94 +++++++++++++++++-- tools/scripts/x86_fsp/tgl/assemble_image.sh | 27 ++---- 4 files changed, 118 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/test-build-kontron-vx3060-s2.yml diff --git a/.github/workflows/test-build-kontron-vx3060-s2.yml b/.github/workflows/test-build-kontron-vx3060-s2.yml new file mode 100644 index 0000000000..08e3395d5f --- /dev/null +++ b/.github/workflows/test-build-kontron-vx3060-s2.yml @@ -0,0 +1,25 @@ +name: kontron_vx3060_s2 build 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 + - name: setup git + run: | + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + - name: run test + run: | + cp config/examples/kontron_vx3060_s2.config .config + ./tools/scripts/x86_fsp/tgl/tgl_download_fsp.sh + make diff --git a/config/examples/kontron_vx3060_s2.config b/config/examples/kontron_vx3060_s2.config index 45305c9a0a..8fcab216f8 100644 --- a/config/examples/kontron_vx3060_s2.config +++ b/config/examples/kontron_vx3060_s2.config @@ -1,7 +1,7 @@ ARCH=x86_64 TARGET=kontron_vx3060_s2 WOLFBOOT_SMALL_STACK=0 -SIGN=ECC384 +SIGN=ECC256 HASH=SHA256 DEBUG=0 SPMATH=1 @@ -21,16 +21,12 @@ WOLFBOOT_LOAD_BASE=0x58000200 WOLFBOOT_SECTOR_SIZE?=0x1000 WOLFBOOT_DATA_ADDRESS=0x1000000 - -FSP_S_BASE=0xffea0000 FSP_T_BASE=0xfff59000 FSP_M_BASE=0xfff60000 WOLFBOOT_ORIGIN=0xfff00000 -# 4 MB +# 6 MB BOOTLOADER_PARTITION_SIZE=0x600000 -# 12 MB -BIOS_REGION_SIZE=0xc00000 UCODE0_BASE=0xffd90000 UCODE0_BIN=src/x86/ucode0.bin @@ -38,30 +34,19 @@ UCODE0_BIN=src/x86/ucode0.bin FSP_T_BIN=./src/x86/fsp_t.bin FSP_M_BIN=./src/x86/fsp_m.bin FSP_S_BIN=./src/x86/fsp_s.bin -FSP_S_UPD_DATA_BIN=./src/x86/fsp_s_upd_data.bin X86_UART_BASE=0xFE032000 X86_UART_REG_WIDTH=4 X86_UART_MMIO=1 - PCH_PCR_BASE=0xFD000000 PCI_ECAM_BASE=0xC0000000 - PCI_USE_ECAM=1 PCH_HAS_PCR=1 - 64BIT=1 ELF=1 DEBUG_ELF=0 MULTIBOOT2=1 - FSP_S_LOAD_BASE=0x0FED5F00 STAGE1_AUTH=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 DEBUG_SYMBOLS=1 diff --git a/docs/Targets.md b/docs/Targets.md index 435088b572..a2bc8f3e3f 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -9,6 +9,7 @@ This README describes configuration of supported targets. * [Cypress PSoC-6](#cypress-psoc-6) * [Infineon AURIX TC3xx](#infineon-aurix-tc3xx) * [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support) +* [Kontron VX3060-S2](#kontron-vx3060-s2) * [Microchip SAMA5D3](#microchip-sama5d3) * [Microchip SAME51](#microchip-same51) * [Nordic nRF52840](#nordic-nrf52840) @@ -3199,24 +3200,97 @@ IMAGE=test-app/image.elf SIGN=--ecc384 tools/scripts/x86_fsp/qemu/make_hd.sh 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 +## 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: +wolfBoot supports Kontron VX3060-S2 board using Intel Firmware Support Package +(FSP). You can find more details about the wolfBoot support with Intel FSP in +the above [section](#intel-x86_64-with-intel-fsp-support). A minimal +configuration example is provided in +[config/examples/kontron_vx3060_s2.config](config/examples/kontron_vx3060_s2.config). +In order to produce a flashable flash image, a dump of the original flash is +required. To build wolfBoot, follow 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" +make ./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. +After running the above commands, you should find a file named `final_image.bin` in the root folder of the repository. The image can be flashed directly into the board. +By default wolfBoot tries to read a wolfBoot image from the SATA drive. +The drive should be partitioned with a GPT table, wolfBoot tries to load an image saved in the 5th or the 6th partition. +You can find more details in `src/update_disk.c`. wolfBoot doesn't try to read from a filesystem and the images need to be written directly into the partition. +This is an example boot log: +``` +Press any key within 2 seconds to toogle BIOS flash chip +Cache-as-RAM initialized +FSP-T:A.0.7E build 70 +FSP-M:A.0.7E build 70 +microcode revision: AA, date: 12-28-2022 +machine_update_m_params +calling FspMemInit... +warm reset required +Press any key within 2 seconds to toogle BIOS flash chip +Cache-as-RAM initialized +FSP-T:A.0.7E build 70 +FSP-M:A.0.7E build 70 +microcode revision: AA, date: 12-28-2022 +machine_update_m_params +calling FspMemInit... +success +top reserved 0_78C50000h +mem: [ 0x78C40000, 0x78C50000 ] - stack (0x10000) +mem: [ 0x78C3FFF4, 0x78C40000 ] - stage2 parameter (0xC) +hoblist@0x78C90000 +mem: [ 0x78C38000, 0x78C3FFF4 ] - page tables (0x7FF4) +page table @ 0x78C38000 [length: 7000] +mem: [ 0x78C37FF8, 0x78C38000 ] - stage2 ptr holder (0x8) +TOLUM: 0x78C37FF8 +mem: [ 0x100000, 0x100014 ] - stage1 .data (0x14) +mem: [ 0x100020, 0x100040 ] - stage1 .bss (0x20) +CPUID(0):1B 756E6547 6C65746E +mem: [ 0x58000100, 0x5806196C ] - wolfboot (0x6186C) +mem: [ 0x5806196C, 0x58282000 ] - wolfboot .bss (0x220694) +load wolfboot end +Authenticating wolfboot at 58000200... +Boot partition: 0x58000100 (sz 399212, ver 0x1, type 0x201) +verify_payload: image open successfully. +verify_payload: integrity OK. Checking signature. +wolfBoot: verified OK. +starting wolfboot 64bit +call temp ram exit...successA.0.7E build 70 +call silicon...successcap a 2268409840 +ddt disabled 0 +device enable: 172049 +device enable: 172049 +AHCI port 0: Disk detected (det: 04 ipm: 00) +AHCI port 1: Disk detected (det: 03 ipm: 01) +SATA disk drive detected on AHCI port 1 +Reading MBR... +Found GPT PTE at sector 1 +Found valid boot signature in MBR +Valid GPT partition table +Current LBA: 0x1 +Backup LBA: 0x6FCCF2F +Max number of partitions: 128 +Software limited: only allowing up to 16 partitions per disk. +Disk size: 1107095552 +disk0.p0 (0_8000000h@ 0_100000) +disk0.p1 (0_20000000h@ 0_8100000) +disk0.p2 (4_0h@ 0_28100000) +disk0.p3 (4_0h@ 4_28100000) +disk0.p4 (1_0h@ 8_28100000) +disk0.p5 (0_80000000h@ 9_28100000) +disk0.p6 (0_80000000h@ 9_A8100000) +Total partitions on disk0: 7 +Checking primary OS image in 0,5... +Checking secondary OS image in 0,6... +Versions, A:1 B:1 +Load address 0x58282000 +Attempting boot from partition A +``` +At this point, the kernel image in partition "A" is verified and staged and you should be seeing the log messages of your OS booting. ## Infineon AURIX TC3xx diff --git a/tools/scripts/x86_fsp/tgl/assemble_image.sh b/tools/scripts/x86_fsp/tgl/assemble_image.sh index adbe6e10f5..50cad1ec51 100755 --- a/tools/scripts/x86_fsp/tgl/assemble_image.sh +++ b/tools/scripts/x86_fsp/tgl/assemble_image.sh @@ -3,20 +3,10 @@ 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 @@ -26,27 +16,24 @@ build_and_sign_image() 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 + if grep -q '^WOLFBOOT_TPM_SEAL=1$' .config; then + 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 + fi } assemble() { - cp $WOLFBOOT_DIR/wolfboot_stage1.bin $BIOS_REGION_PATH + cp "$WOLFBOOT_DIR/wolfboot_stage1.bin" $BIOS_REGION_PATH build_and_sign_image } # Parse command line options -while getopts "ks:n:m:" opt; do +while getopts "s: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]"