From d7e3dde6bc781447de03eb6da84beb836298a64e Mon Sep 17 00:00:00 2001 From: haowx Date: Fri, 18 Mar 2022 01:36:20 +0800 Subject: [PATCH] td-shim: Migration build ResetVector.bin Signed-off-by: haowx --- td-shim/.gitignore | 7 + td-shim/Cargo.toml | 58 ++++ td-shim/ResetVector/.gitignore | 4 + td-shim/ResetVector/CommonMacros.inc | 204 ++++++++++++ td-shim/ResetVector/DebugDisabled.asm | 19 ++ td-shim/ResetVector/Ia32/Flat32ToFlat64.asm | 52 +++ td-shim/ResetVector/Ia32/ReloadFlat32.asm | 151 +++++++++ td-shim/ResetVector/Ia32/ResetVectorVtf0.asm | 55 ++++ td-shim/ResetVector/Ia32/ValidateBfvBase.asm | 67 ++++ td-shim/ResetVector/Main.asm | 316 +++++++++++++++++++ td-shim/ResetVector/Port80Debug.asm | 21 ++ td-shim/ResetVector/PostCodes.inc | 18 ++ td-shim/ResetVector/ResetVector.nasm | 34 ++ td-shim/ResetVector/SerialDebug.asm | 125 ++++++++ td-shim/ResetVector/X64/PageTables.asm | 47 +++ td-shim/ResetVector/X64/TestHob.asm | 56 ++++ td-shim/build.rs | 251 +++++++++++++++ td-shim/src/lib.rs | 5 + 18 files changed, 1490 insertions(+) create mode 100644 td-shim/.gitignore create mode 100644 td-shim/Cargo.toml create mode 100644 td-shim/ResetVector/.gitignore create mode 100644 td-shim/ResetVector/CommonMacros.inc create mode 100644 td-shim/ResetVector/DebugDisabled.asm create mode 100644 td-shim/ResetVector/Ia32/Flat32ToFlat64.asm create mode 100644 td-shim/ResetVector/Ia32/ReloadFlat32.asm create mode 100644 td-shim/ResetVector/Ia32/ResetVectorVtf0.asm create mode 100644 td-shim/ResetVector/Ia32/ValidateBfvBase.asm create mode 100644 td-shim/ResetVector/Main.asm create mode 100644 td-shim/ResetVector/Port80Debug.asm create mode 100644 td-shim/ResetVector/PostCodes.inc create mode 100644 td-shim/ResetVector/ResetVector.nasm create mode 100644 td-shim/ResetVector/SerialDebug.asm create mode 100644 td-shim/ResetVector/X64/PageTables.asm create mode 100644 td-shim/ResetVector/X64/TestHob.asm create mode 100644 td-shim/build.rs create mode 100644 td-shim/src/lib.rs diff --git a/td-shim/.gitignore b/td-shim/.gitignore new file mode 100644 index 00000000..46966d59 --- /dev/null +++ b/td-shim/.gitignore @@ -0,0 +1,7 @@ +*~ + +# Cargo Junk +Cargo.lock +target/ +*.bin +*.obj diff --git a/td-shim/Cargo.toml b/td-shim/Cargo.toml new file mode 100644 index 00000000..f4201952 --- /dev/null +++ b/td-shim/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "td-shim" +version = "0.1.0" +edition = "2018" + +# add build process +build = "build.rs" + +[build-dependencies] +anyhow = "1.0.55" +cc = { git = "https://github.com/jyao1/cc-rs.git", branch = "uefi_support" } +td-layout = { path = "../td-layout" } +tdx-tdcall = { path = "../tdx-tdcall" } +which = "4.2.4" + +[dependencies] +lazy_static = { version = "1.4.0", features = ["spin_no_std"] } +log = "0.4.13" +r-efi = "3.2.0" +scroll = { version = "0.10", default-features = false, features = ["derive"] } +td-layout = { path = "../td-layout" } +td-uefi-pi = { path = "../td-uefi-pi" } +zerocopy = "0.6.0" + +td-loader = { path = "../td-loader", optional = true } +linked_list_allocator = { version = "0.9.0", optional = true } +ring = { git = "https://github.com/jyao1/ring.git", branch = "uefi_support", default-features = false, features = ["alloc"], optional = true } +spin = { version = "0.9.2", optional = true } +td-exception = { path = "../td-exception", features = ["tdx"], optional = true } +td-logger = { path = "../td-logger", optional = true } +td-paging = { path = "../td-paging", optional = true } +x86 = { version ="0.44.0", optional = true } +# Lock down to 0.44, otherwise it depends on inline asm +x86_64 = { version = "=0.14.6", optional = true } + +# secure boot +der = {version = "0.4.5", features = ["derive", "alloc"], optional = true} + +# TDX +tdx-tdcall = { path = "../tdx-tdcall", optional = true } + +[features] +default = ["boot-kernel", "cet-ss", "secure-boot"] +boot-kernel = ["td-layout/boot-kernel"] +cet-ss = [] +secure-boot = ["der"] +tdx = ["tdx-tdcall", "td-exception/tdx", "td-logger/tdx", "x86"] +main = [ + "td-loader", + "linked_list_allocator", + "ring", + "spin", + "td-exception", + "td-logger", + "td-paging", + "x86", + "x86_64", +] diff --git a/td-shim/ResetVector/.gitignore b/td-shim/ResetVector/.gitignore new file mode 100644 index 00000000..66256226 --- /dev/null +++ b/td-shim/ResetVector/.gitignore @@ -0,0 +1,4 @@ +*~ + +# Bin Junk +*.bin diff --git a/td-shim/ResetVector/CommonMacros.inc b/td-shim/ResetVector/CommonMacros.inc new file mode 100644 index 00000000..a7b00c63 --- /dev/null +++ b/td-shim/ResetVector/CommonMacros.inc @@ -0,0 +1,204 @@ +;------------------------------------------------------------------------------ +; @file +; Common macros used in the ResetVector VTF module. +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +%macro tdcall 0 +%if (USE_TDX_EMULATION != 0) + vmcall +%else + db 0x66,0x0f,0x01,0xcc +%endif +%endmacro + + +%define ADDR16_OF(x) (0x10000 - fourGigabytes + x) +%define ADDR_OF(x) (0x100000000 - fourGigabytes + x) + +%macro OneTimeCall 1 + jmp %1 +%1 %+ OneTimerCallReturn: +%endmacro + +%macro OneTimeCallRet 1 + jmp %1 %+ OneTimerCallReturn +%endmacro + + +CommandOffset equ 00h +ApicidOffset equ 04h +WakeupVectorOffset equ 08h +OSArgsOffset equ 10h +FirmwareArgsOffset equ 800h +WakeupArgsRelocatedMailBox equ 800h +ApWorkingStackStart equ 800h +CpuArrivalOffset equ 900h +CpusExitingOffset equ 0a00h +TalliesOffset equ 0a08h + +MpProtectedModeWakeupCommandNoop equ 0 +MpProtectedModeWakeupCommandWakeup equ 1 +MpProtectedModeWakeupCommandSleep equ 2 +MpProtectedModeWakeupCommandAssignWork equ 3 +MpProtectedModeWakeupCommandCheck equ 4 + +MailboxApicIdInvalid equ 0xffffffff +MailboxApicidBroadcast equ 0xfffffffe + +%macro simple_spinlock 3 + mov edx, %1 + mov eax, 0 + mov ebx, 1 +%%testlock: + lock cmpxchg [edx], ebx + jnz %3 + mov eax, 0 + mov ebx, 1 + lock cmpxchg [edx+4], ebx + jnz %2 +%%firstone: + pause +%endmacro + +%macro simple_releaselock 3 +%2: + mov eax, 1 + mov edx, %1 + jmp %%testlock +%3: + pause + mov eax, 0 +%%testlock: + mov ebx, 0 + lock cmpxchg [edx], ebx + jnz %3 +%endmacro + + +%define PAGE_PRESENT 0x01 +%define PAGE_READ_WRITE 0x02 +%define PAGE_USER_SUPERVISOR 0x04 +%define PAGE_WRITE_THROUGH 0x08 +%define PAGE_CACHE_DISABLE 0x010 +%define PAGE_ACCESSED 0x020 +%define PAGE_DIRTY 0x040 +%define PAGE_PAT 0x080 +%define PAGE_GLOBAL 0x0100 +%define PAGE_2M_MBO 0x080 +%define PAGE_2M_PAT 0x01000 + +%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \ + PAGE_ACCESSED + \ + PAGE_DIRTY + \ + PAGE_READ_WRITE + \ + PAGE_PRESENT) + +%define PAGE_PDP_ATTR (PAGE_ACCESSED + \ + PAGE_READ_WRITE + \ + PAGE_PRESENT) + +%define PT_ADDR(Base,Offset) ((Base) + (Offset)) + +%macro clear_pagetables 1 + mov ecx, 6 * 0x1000 / 4 + xor eax, eax +%%clearloop: + mov dword[ecx * 4 + PT_ADDR (%1,0) - 4], eax + loop %%clearloop +%endmacro + +%macro init_l4_l3_page_tables 2 + ; + ; Top level Page Directory Pointers (1 * 512GB entry) + ; + mov dword[PT_ADDR (%1,0)], PT_ADDR (%1,0x1000) + PAGE_PDP_ATTR + mov dword[PT_ADDR (%1,4)], %2 + + ; + ; Next level Page Directory Pointers (4 * 1GB entries => 4GB) + ; + mov dword[PT_ADDR (%1,0x1000)], PT_ADDR (%1,0x2000) + PAGE_PDP_ATTR + mov dword[PT_ADDR (%1,0x1004)], %2 + mov dword[PT_ADDR (%1,0x1008)], PT_ADDR (%1,0x3000) + PAGE_PDP_ATTR + mov dword[PT_ADDR (%1,0x100C)], %2 + mov dword[PT_ADDR (%1,0x1010)], PT_ADDR (%1,0x4000) + PAGE_PDP_ATTR + mov dword[PT_ADDR (%1,0x1014)], %2 + mov dword[PT_ADDR (%1,0x1018)], PT_ADDR (%1,0x5000) + PAGE_PDP_ATTR + mov dword[PT_ADDR (%1,0x101C)], %2 +%endmacro + +%macro init_l2_page_tables 2 + ; + ; Page Table Entries (2048 * 2MB entries => 4GB) + ; + mov ecx, 0x800 +%%loop: + mov eax, ecx + dec eax + shl eax, 21 + add eax, PAGE_2M_PDE_ATTR + mov [ecx * 8 + PT_ADDR (%1,0x2000 - 8)], eax + mov dword[(ecx * 8 + PT_ADDR (%1,0x2000 - 8)) + 4], %2 + loop %%loop +%endmacro + +%macro initialize_page_tables 2 + clear_pagetables %1 + init_l4_l3_page_tables %1,%2 + init_l2_page_tables %1,%2 +%endmacro + + +%define EFI_HOB_TYPE_HANDOFF 0x0001 +%define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 +%define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 +%define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 +%define EFI_HOB_TYPE_FV 0x0005 +%define EFI_HOB_TYPE_CPU 0x0006 +%define EFI_HOB_TYPE_MEMORY_POOL 0x0007 +%define EFI_HOB_TYPE_FV2 0x0009 +%define EFI_HOB_TYPE_LOAD_PEIM_UNUSED 0x000A +%define EFI_HOB_TYPE_UEFI_CAPSULE 0x000B +%define EFI_HOB_TYPE_FV3 0x000C +%define EFI_HOB_TYPE_UNUSED 0xFFFE +%define EFI_HOB_TYPE_END_OF_HOB_LIST 0xFFFF + +%define EFI_RESOURCE_SYSTEM_MEMORY 0x00000000 +%define EFI_RESOURCE_MEMORY_MAPPED_IO 0x00000001 +%define EFI_RESOURCE_IO 0x00000002 +%define EFI_RESOURCE_FIRMWARE_DEVICE 0x00000003 +%define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004 +%define EFI_RESOURCE_MEMORY_RESERVED 0x00000005 +%define EFI_RESOURCE_IO_RESERVED 0x00000006 +%define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000007 + +%define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +%define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +%define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +%define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 + +%define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 +%define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 +%define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 +%define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 + + +%define EFI_IO_ATTR (EFI_RESOURCE_ATTRIBUTE_PRESENT + \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED + \ + EFI_RESOURCE_ATTRIBUTE_TESTED + \ + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE) + +%define EFI_LOW_MEM_ATTR (EFI_RESOURCE_ATTRIBUTE_PRESENT + \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED + \ + EFI_RESOURCE_ATTRIBUTE_TESTED + \ + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE + \ + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE + \ + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + \ + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE) + +%define TDCALL_TDINFO 0x1 +%define TDCALL_TDACCEPTPAGE 0x6 diff --git a/td-shim/ResetVector/DebugDisabled.asm b/td-shim/ResetVector/DebugDisabled.asm new file mode 100644 index 00000000..f1afdfcc --- /dev/null +++ b/td-shim/ResetVector/DebugDisabled.asm @@ -0,0 +1,19 @@ +;------------------------------------------------------------------------------ +; @file +; Debug disabled +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 16 + +%macro debugInitialize 0 + ; + ; No initialization is required + ; +%endmacro + +%macro debugShowPostCode 1 +%endmacro diff --git a/td-shim/ResetVector/Ia32/Flat32ToFlat64.asm b/td-shim/ResetVector/Ia32/Flat32ToFlat64.asm new file mode 100644 index 00000000..99d2b26d --- /dev/null +++ b/td-shim/ResetVector/Ia32/Flat32ToFlat64.asm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; @file +; Transition from 32 bit flat protected mode into 64 bit flat protected mode +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 32 + +; +; Modified: EAX. ECX +; +Transition32FlatTo64Flat: + + mov eax, cr4 + bts eax, 5 ; enable PAE + + ; + ; esp [6:0] holds gpaw, if it is at least 52 bits, need to set + ; LA57 and use 5-level paging + ; + mov ecx, esp + and ecx, 0x2f + cmp ecx, 52 + jl .set_cr4 + bts eax, 12 +.set_cr4: + mov cr4, eax + + mov ecx, ADDR_OF(TopLevelPageDirectory) + ; + ; if we just set la57, we are ok, if using 4-level paging, adjust top-level page directory + ; + bt eax, 12 + jc .set_cr3 + add ecx, 0x1000 +.set_cr3: + mov cr3, ecx + + mov eax, cr0 + bts eax, 31 ; set PG + mov cr0, eax ; enable paging + + jmp LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere) +BITS 64 +jumpTo64BitAndLandHere: + + debugShowPostCode POSTCODE_64BIT_MODE + + OneTimeCallRet Transition32FlatTo64Flat diff --git a/td-shim/ResetVector/Ia32/ReloadFlat32.asm b/td-shim/ResetVector/Ia32/ReloadFlat32.asm new file mode 100644 index 00000000..929b55f9 --- /dev/null +++ b/td-shim/ResetVector/Ia32/ReloadFlat32.asm @@ -0,0 +1,151 @@ +;------------------------------------------------------------------------------ +; @file +; Transition from 16 bit real mode into 32 bit flat protected mode +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +%define SEC_DEFAULT_CR0 0x00000023 +%define SEC_DEFAULT_CR4 0x640 + +BITS 32 + +; +; Modified: EAX, EBX +; +ReloadFlat32: + + debugShowPostCode POSTCODE_16BIT_MODE + + cli + mov ebx, ADDR_OF(gdtr) + lgdt [ebx] + + mov eax, SEC_DEFAULT_CR0 + mov cr0, eax + + jmp LINEAR_CODE_SEL:dword ADDR_OF(jumpTo32BitAndLandHere) +BITS 32 +jumpTo32BitAndLandHere: + + mov eax, SEC_DEFAULT_CR4 + mov cr4, eax + + debugShowPostCode POSTCODE_32BIT_MODE + + mov ax, LINEAR_SEL + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + OneTimeCallRet ReloadFlat32 + +ALIGN 2 + +gdtr: + dw GDT_END - GDT_BASE - 1 ; GDT limit + dd ADDR_OF(GDT_BASE) + +ALIGN 16 + +; +; Macros for GDT entries +; + +%define PRESENT_FLAG(p) (p << 7) +%define DPL(dpl) (dpl << 5) +%define SYSTEM_FLAG(s) (s << 4) +%define DESC_TYPE(t) (t) + +; Type: data, expand-up, writable, accessed +%define DATA32_TYPE 3 + +; Type: execute, readable, expand-up, accessed +%define CODE32_TYPE 0xb + +; Type: execute, readable, expand-up, accessed +%define CODE64_TYPE 0xb + +%define GRANULARITY_FLAG(g) (g << 7) +%define DEFAULT_SIZE32(d) (d << 6) +%define CODE64_FLAG(l) (l << 5) +%define UPPER_LIMIT(l) (l) + +; +; The Global Descriptor Table (GDT) +; + +GDT_BASE: +; null descriptor +NULL_SEL equ $-GDT_BASE + DW 0 ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB 0 ; sys flag, dpl, type + DB 0 ; limit 19:16, flags + DB 0 ; base 31:24 + +; linear data segment descriptor +LINEAR_SEL equ $-GDT_BASE + DW 0xffff ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE) + DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf) + DB 0 ; base 31:24 + +; linear code segment descriptor +LINEAR_CODE_SEL equ $-GDT_BASE + DW 0xffff ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE) + DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf) + DB 0 ; base 31:24 + +%ifdef ARCH_X64 + +NULL_SEL1 equ $-GDT_BASE + DW 0 ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB 0 ; sys flag, dpl, type + DB 0 ; limit 19:16, flags + DB 0 ; base 31:24 +NULL_SEL2 equ $-GDT_BASE + DW 0 ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB 0 ; sys flag, dpl, type + DB 0 ; limit 19:16, flags + DB 0 ; base 31:24 +NULL_SEL3 equ $-GDT_BASE + DW 0 ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB 0 ; sys flag, dpl, type + DB 0 ; limit 19:16, flags + DB 0 ; base 31:24 +NULL_SEL4 equ $-GDT_BASE + DW 0 ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB 0 ; sys flag, dpl, type + DB 0 ; limit 19:16, flags + DB 0 ; base 31:24 + +; linear code (64-bit) segment descriptor +LINEAR_CODE64_SEL equ $-GDT_BASE + DW 0xffff ; limit 15:0 + DW 0 ; base 15:0 + DB 0 ; base 23:16 + DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE) + DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf) + DB 0 ; base 31:24 +%endif + +GDT_END: diff --git a/td-shim/ResetVector/Ia32/ResetVectorVtf0.asm b/td-shim/ResetVector/Ia32/ResetVectorVtf0.asm new file mode 100644 index 00000000..179067dc --- /dev/null +++ b/td-shim/ResetVector/Ia32/ResetVectorVtf0.asm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; @file +; First code executed by processor after resetting. +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 32 + +ALIGN 16 + +; +; Pad the image size to 4k when page tables are in VTF0 +; +; If the VTF0 image has page tables built in, then we need to make +; sure the end of VTF0 is 4k above where the page tables end. +; +; This is required so the page tables will be 4k aligned when VTF0 is +; located just below 0x100000000 (4GB) in the firmware device. +; + TIMES (0x1000 - ($ - EndOfPageTables) - 0x20) DB 0 + +dummy: + jmp $ + +ALIGN 8 + + DD 0 + +; +; The VTF signature +; +; VTF-0 means that the VTF (Volume Top File) code does not require +; any fixups. +; +vtfSignature: + DB 'V', 'T', 'F', 0 + +ALIGN 16 + +resetVector: +; +; Reset Vector +; +; This is where the processor will begin execution +; + nop + nop + jmp Main32 + +ALIGN 16 + +fourGigabytes: diff --git a/td-shim/ResetVector/Ia32/ValidateBfvBase.asm b/td-shim/ResetVector/Ia32/ValidateBfvBase.asm new file mode 100644 index 00000000..c2adaa74 --- /dev/null +++ b/td-shim/ResetVector/Ia32/ValidateBfvBase.asm @@ -0,0 +1,67 @@ +;------------------------------------------------------------------------------ +; @file +; Validates the Boot Firmware Volume (BFV) base address +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ +; { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } } +%define FFS_GUID_DWORD0 0x8c8ce578 +%define FFS_GUID_DWORD1 0x4f1c8a3d +%define FFS_GUID_DWORD2 0x61893599 +%define FFS_GUID_DWORD3 0xd32dc385 + +BITS 32 + +; +; Modified: EAX +; Preserved: EDI, ESP +; +; @param[out] EBP Address of Boot Firmware Volume (BFV) +; +Flat32ValidateBfv: + + mov eax, TOP_OF_BFV + ; + ; Check FFS GUID + ; + cmp dword [eax + 0x10], FFS_GUID_DWORD0 + jne BfvHeaderNotFound + cmp dword [eax + 0x14], FFS_GUID_DWORD1 + jne BfvHeaderNotFound + cmp dword [eax + 0x18], FFS_GUID_DWORD2 + jne BfvHeaderNotFound + cmp dword [eax + 0x1c], FFS_GUID_DWORD3 + jne BfvHeaderNotFound + + ; + ; Check FV Length + ; + cmp dword [eax + 0x24], 0 + jne BfvHeaderNotFound + + ; + ; Return BFV in ebp + ; + mov ebp, eax + + debugShowPostCode POSTCODE_BFV_FOUND + + OneTimeCallRet Flat32ValidateBfv + +BfvHeaderNotFound: + ; + ; Hang if the SEC entry point was not found + ; + debugShowPostCode POSTCODE_BFV_NOT_FOUND + + ; + ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed + ; for debugging purposes. + ; + mov eax, 0xBFBFBFBF + mov ebp, eax + jmp $ diff --git a/td-shim/ResetVector/Main.asm b/td-shim/ResetVector/Main.asm new file mode 100644 index 00000000..30265233 --- /dev/null +++ b/td-shim/ResetVector/Main.asm @@ -0,0 +1,316 @@ +;------------------------------------------------------------------------------ +; @file +; Main routine of the pre-SEC code up through the jump into SEC +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + + +BITS 32 + +; +; Modified: EBX, ECX, EDX, EBP, EDI, ESP +; +; @param[in,out] RAX/EAX 0 +; @param[in] RFLAGS 2 +; @param[in] RCX [31:0] TDINITVP - Untrusted Configuration +; [63:32] 0 +; @param[in] RDX [31:0] VCPUID +; [63:32] 0 +; @param[in] RBX [6:0] CPU supported GPA width +; [7:7] 5 level page table support +; [63:8] 0 +; @param[in] RSI [31:0] VCPU_Index +; [63:32] 0 +; @param[in] RDI/EDI 0 +; @param[in] RBP/EBP 0 +; @param[in/out] R8 Same as RCX +; @param[out] R9 [6:0] CPU supported GPA width +; [7:7] 5 level page table support +; [23:16] VCPUID +; [32:24] VCPU_Index +; @param[out] R12,R13 SEC Core base (new), SEC Core size (new) +; @param[out] RBP/EBP Address of Boot Firmware Volume (BFV) +; @param[out] DS Selector allowing flat access to all addresses +; @param[out] ES Selector allowing flat access to all addresses +; @param[out] FS Selector allowing flat access to all addresses +; @param[out] GS Selector allowing flat access to all addresses +; @param[out] SS Selector allowing flat access to all addresses +; +; @return None This routine jumps to SEC and does not return +; +Main32: + ; We need to preserve rdx and ebx information + ; We are ok with rcx getting modified because copy is in r8, but will save in edi for now + ; Save ecx in edi + mov edi, ecx + + ; Save ebx to esp + mov esp, ebx + + ; We need to store vcpuid/vcpu_index, we will use upper bits of ebx + shl esi, 16 + or esp, esi + + ; + ; Transition the processor from protected to 32-bit flat mode + ; + OneTimeCall ReloadFlat32 + + ; + ; Validate the Boot Firmware Volume (BFV) + ; + OneTimeCall Flat32ValidateBfv + + ; + ; EBP - Start of BFV + ; + + ; + ; The SEC entry point + + mov edi, dword [TD_SHIM_RESET_SEC_CORE_BASE_ADDR] + mov ebx, dword [TD_SHIM_RESET_SEC_CORE_SIZE_ADDR] + mov esi, dword [TD_SHIM_RESET_SEC_CORE_ENTRY_POINT_ADDR] + add esi, edi + + ; + ; ESI - SEC Core entry point + ; EBP - Start of BFV + ; EDI - SEC Core base (new) + ; EBX - SEC Core size (new) + ; + + ; + ; Transition the processor from 32-bit flat mode to 64-bit flat mode + ; + OneTimeCall Transition32FlatTo64Flat + +BITS 64 + ; Save + ; EDI - SEC Core base (new) + ; EBX - SEC Core size (new) + ; to R12 R13 + xor r12, r12 + xor r13, r13 + mov r12d, edi + mov r13d, ebx + + mov r9, rsp + ; + ; Some values were calculated in 32-bit mode. Make sure the upper + ; 32-bits of 64-bit registers are zero for these values. + ; + mov rax, 0x00000000ffffffff + and rsi, rax + and rbp, rax + and rsp, rax + + ; + ; RSI - SEC Core entry point + ; RBP - Start of BFV + ; + + ; + ; Restore initial EAX value into the RAX register + ; + mov rax, 0 + + ; + ; Jump to the 64-bit SEC entry point + ; + ; jmp rsi + +; @param[in] R8 [31:0] TDINITVP - Untrusted Configuration +; [63:32] 0 +; @param[in] R9 [6:0] CPU supported GPA width +; [7:7] 5 level page table support +; [23:16] VCPUID +; [32:24] VCPU_Index +; @param[in] RBP Pointer to the start of the Boot Firmware Volume + + ; + ; Get vcpuid from r9, and determine if BSP + ; APs jump to spinloop and get released by DXE's mpinitlib + ; + mov rax, r9 + shr rax, 16 + and rax, 0xff + test rax, rax + jne ParkAp + + ; Fill the temporary RAM with the initial stack value (0x5AA55AA5). + ; The loop below will seed the heap as well, but that's harmless. + ; + mov rax, (0x5AA55AA5 << 32) | 0x5AA55AA5 + ; qword to store + mov rdi, TEMP_STACK_BASE ; base address + mov rcx, TEMP_STACK_SIZE / 8 ; qword count + cld ; store from base + ; up + rep stosq + + ; + ; Load temporary RAM stack based on PCDs + ; + %define SEC_TOP_OF_STACK (TEMP_STACK_BASE + TEMP_STACK_SIZE) + mov rsp, SEC_TOP_OF_STACK + + ; 1) Accept [1M, 1M + SEC Core Size] + + + ; rcx = Accept address + ; rdx = 0 + ; r8 = 0 + ;mov rax, TDCALL_TDACCEPTPAGE + ;tdcall + + mov r14, 0x0 ; start address + mov r15, 0x800000 ; end address TBD + +.accept_pages_for_sec_core_loop + mov r8, 0 + mov rdx, 0 + mov rcx, r14 + mov rax, TDCALL_TDACCEPTPAGE + tdcall + + add r14, 0x1000 + cmp r14, r15 + jne .accept_pages_for_sec_core_loop + + + ; 2) Copy [SEC Core Base, SEC Core Base+Size] to [1M, 1M + SEC Core Size] + mov rcx, r12 + mov rdx, r12 + add rdx, r13 + mov r14, 0x100000 + +.copy_sec_core_loop + mov rax, qword [rcx] + mov qword [r14], rax + add r14, 0x8 + add rcx, 0x8 + cmp rcx, rdx + jne .copy_sec_core_loop + + ; 3) Fix RSI = RSI - SEC Core Base + 1M + ; mov r14, rsi + ; sub r14, r12 + ; add r14, 0x100000 + ; mov r12, r14 + sub rsi, r12 + add rsi, 0x100000 + nop + + ; + ; Enable SSE and Write Protection + ; + mov rax, cr0 + and rax, 0xfffffffffffffffb ; clear EM + or rax, 0x0000000000010002 ; set MP and Write Protection bit + mov cr0, rax + mov rax, cr4 + or rax, 0x600 ; set OSFXSR, OSXMMEXCPT + mov cr4, rax + + ; + ; Setup parameters and call SecCoreStartupWithStack + ; rcx: BootFirmwareVolumePtr + ; rdx: TopOfCurrentStack + ; r8: TdInitVp + ; r9: gpaw/5-level-paging/vcpuid/vcpu_index + ; + mov rcx, rbp + mov rdx, rsp + sub rsp, 0x20 + call rsi + + ; + ; Note, BSP never gets here, APs will be unblocked in DXE + ; +ParkAp: + + ; + ; Get vcpuid in rbp + mov rbp, rax + + mov rax, TDCALL_TDINFO + tdcall + + ; + ; R8 [31:0] NUM_VCPUS + ; [63:32] MAX_VCPUS + ; R9 [31:0] VCPU_INDEX + + mov rsp, TD_MAILBOX_BASE ; base address + +.check_apicid: + ; Determine if this is a broadcast or directly for my apic-id, if not, ignore + cmp dword[rsp + ApicidOffset], MailboxApicidBroadcast + je .mailbox_process_command + cmp dword[rsp + ApicidOffset], r9d + jne .check_apicid + +.mailbox_process_command: + mov eax, dword[rsp + CommandOffset] + cmp eax, MpProtectedModeWakeupCommandNoop + je .check_apicid + + cmp eax, MpProtectedModeWakeupCommandWakeup + je .do_wakeup + + ; + ; Check if the AP is available + cmp eax, MpProtectedModeWakeupCommandCheck + je .check_avalible + + cmp eax, MpProtectedModeWakeupCommandAssignWork + je .set_ap_stack + + jmp .check_apicid + +.check_avalible + ; + ; Set the ApicId to be invalid to show the AP is available + mov dword[rsp + ApicidOffset], MailboxApicIdInvalid + jmp .check_apicid + +.set_ap_stack + ; + ; Read the function address which will be called + mov eax, dword[rsp + WakeupVectorOffset] + ; + ; Read the stack address from arguments and set the rsp + mov rsi, [rsp + ApWorkingStackStart] + ; + ; Set the ApicId to be invalid to show the AP has been waked up + mov dword[rsp + ApicidOffset], MailboxApicIdInvalid + + mov rsp, rsi + ; + ; CPU index as the first parameter + mov ecx, r9d + + ; + ; r9d contains cpu index, which needs to be saved + push r9 + call rax + pop r9 + + ; + ;Set rsp back to TD_MAILBOX_BASE + mov rsp, TD_MAILBOX_BASE ; base address + jmp .check_apicid + +.do_wakeup: + ; + ; BSP sets these variables before unblocking APs + mov rax, 0 + mov eax, dword[rsp + WakeupVectorOffset] + mov rbx, [rsp + WakeupArgsRelocatedMailBox] + nop + jmp rax + jmp $ diff --git a/td-shim/ResetVector/Port80Debug.asm b/td-shim/ResetVector/Port80Debug.asm new file mode 100644 index 00000000..2005f4e0 --- /dev/null +++ b/td-shim/ResetVector/Port80Debug.asm @@ -0,0 +1,21 @@ +;------------------------------------------------------------------------------ +; @file +; Port 0x80 debug support macros +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 16 + +%macro debugInitialize 0 + ; + ; No initialization is required + ; +%endmacro + +%macro debugShowPostCode 1 + mov al, %1 + out 0x80, al +%endmacro diff --git a/td-shim/ResetVector/PostCodes.inc b/td-shim/ResetVector/PostCodes.inc new file mode 100644 index 00000000..040e43b0 --- /dev/null +++ b/td-shim/ResetVector/PostCodes.inc @@ -0,0 +1,18 @@ +;------------------------------------------------------------------------------ +; @file +; Definitions of POST CODES for the reset vector module +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +%define POSTCODE_16BIT_MODE 0x16 +%define POSTCODE_32BIT_MODE 0x32 +%define POSTCODE_64BIT_MODE 0x64 + +%define POSTCODE_BFV_NOT_FOUND 0xb0 +%define POSTCODE_BFV_FOUND 0xb1 + +%define POSTCODE_SEC_NOT_FOUND 0xf0 +%define POSTCODE_SEC_FOUND 0xf1 diff --git a/td-shim/ResetVector/ResetVector.nasm b/td-shim/ResetVector/ResetVector.nasm new file mode 100644 index 00000000..08153924 --- /dev/null +++ b/td-shim/ResetVector/ResetVector.nasm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; @file +; This file includes all other code files to assemble the reset vector code +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +%define ARCH_X64 + +%include "CommonMacros.inc" + +StartOfResetVectorCode: + +%define ADDR_OF_START_OF_RESET_CODE ADDR_OF(StartOfResetVectorCode) + +%include "PostCodes.inc" +%include "X64/PageTables.asm" + +%ifdef DEBUG_PORT80 + %include "Port80Debug.asm" +%elifdef DEBUG_SERIAL + %include "SerialDebug.asm" +%else + %include "DebugDisabled.asm" +%endif + +%include "Ia32/ValidateBfvBase.asm" + +%include "Ia32/Flat32ToFlat64.asm" +%include "Ia32/ReloadFlat32.asm" +%include "Main.asm" +%include "Ia32/ResetVectorVtf0.asm" diff --git a/td-shim/ResetVector/SerialDebug.asm b/td-shim/ResetVector/SerialDebug.asm new file mode 100644 index 00000000..70edf62d --- /dev/null +++ b/td-shim/ResetVector/SerialDebug.asm @@ -0,0 +1,125 @@ +;------------------------------------------------------------------------------ +; @file +; Serial port debug support macros +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +;//--------------------------------------------- +;// UART Register Offsets +;//--------------------------------------------- +%define BAUD_LOW_OFFSET 0x00 +%define BAUD_HIGH_OFFSET 0x01 +%define IER_OFFSET 0x01 +%define LCR_SHADOW_OFFSET 0x01 +%define FCR_SHADOW_OFFSET 0x02 +%define IR_CONTROL_OFFSET 0x02 +%define FCR_OFFSET 0x02 +%define EIR_OFFSET 0x02 +%define BSR_OFFSET 0x03 +%define LCR_OFFSET 0x03 +%define MCR_OFFSET 0x04 +%define LSR_OFFSET 0x05 +%define MSR_OFFSET 0x06 + +;//--------------------------------------------- +;// UART Register Bit Defines +;//--------------------------------------------- +%define LSR_TXRDY 0x20 +%define LSR_RXDA 0x01 +%define DLAB 0x01 + +; UINT16 gComBase = 0x3f8; +; UINTN gBps = 115200; +; UINT8 gData = 8; +; UINT8 gStop = 1; +; UINT8 gParity = 0; +; UINT8 gBreakSet = 0; + +%define DEFAULT_COM_BASE 0x3f8 +%define DEFAULT_BPS 115200 +%define DEFAULT_DATA 8 +%define DEFAULT_STOP 1 +%define DEFAULT_PARITY 0 +%define DEFAULT_BREAK_SET 0 + +%define SERIAL_DEFAULT_LCR ( \ + (DEFAULT_BREAK_SET << 6) | \ + (DEFAULT_PARITY << 3) | \ + (DEFAULT_STOP << 2) | \ + (DEFAULT_DATA - 5) \ + ) + +%define SERIAL_PORT_IO_BASE_ADDRESS DEFAULT_COM_BASE + +%macro inFromSerialPort 1 + mov dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1) + in al, dx +%endmacro + +%macro waitForSerialTxReady 0 + +%%waitingForTx: + inFromSerialPort LSR_OFFSET + test al, LSR_TXRDY + jz %%waitingForTx + +%endmacro + +%macro outToSerialPort 2 + mov dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1) + mov al, %2 + out dx, al +%endmacro + +%macro debugShowCharacter 1 + waitForSerialTxReady + outToSerialPort 0, %1 +%endmacro + +%macro debugShowHexDigit 1 + %if (%1 < 0xa) + debugShowCharacter BYTE ('0' + (%1)) + %else + debugShowCharacter BYTE ('a' + ((%1) - 0xa)) + %endif +%endmacro + +%macro debugNewline 0 + debugShowCharacter `\r` + debugShowCharacter `\n` +%endmacro + +%macro debugShowPostCode 1 + debugShowHexDigit (((%1) >> 4) & 0xf) + debugShowHexDigit ((%1) & 0xf) + debugNewline +%endmacro + +BITS 16 + +%macro debugInitialize 0 + jmp real16InitDebug +real16InitDebugReturn: +%endmacro + +real16InitDebug: + ; + ; Set communications format + ; + outToSerialPort LCR_OFFSET, ((DLAB << 7) | SERIAL_DEFAULT_LCR) + + ; + ; Configure baud rate + ; + outToSerialPort BAUD_HIGH_OFFSET, ((115200 / DEFAULT_BPS) >> 8) + outToSerialPort BAUD_LOW_OFFSET, ((115200 / DEFAULT_BPS) & 0xff) + + ; + ; Switch back to bank 0 + ; + outToSerialPort LCR_OFFSET, SERIAL_DEFAULT_LCR + + jmp real16InitDebugReturn diff --git a/td-shim/ResetVector/X64/PageTables.asm b/td-shim/ResetVector/X64/PageTables.asm new file mode 100644 index 00000000..2a798cc5 --- /dev/null +++ b/td-shim/ResetVector/X64/PageTables.asm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; @file +; Emits Page Tables for 1:1 mapping of the addresses 0 - 0x100000000 (4GB) +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 64 + +%define PGTBLS_OFFSET(x) ((x) - TopLevelPageDirectory) +%define PGTBLS_ADDR(x) (ADDR_OF(TopLevelPageDirectory) + (x)) +%define PDP(offset) (ADDR_OF(TopLevelPageDirectory) + (offset) + PAGE_PDP_ATTR) + +%define PTE_2MB(x) ((x << 21) + PAGE_2M_PDE_ATTR) + +TopLevelPageDirectory: + + ; + ; Top level Page Directory Pointers (1 * 512GB entry) + ; + DQ PDP(0x1000) + ; + ; Next level Page Directory Pointers (4 * 1GB entries => 4GB) + ; + TIMES 511 DQ 0 + + DQ PDP(0x2000) + TIMES 511 DQ 0 + DQ PDP(0x3000) + DQ PDP(0x4000) + DQ PDP(0x5000) + DQ PDP(0x6000) + + ; + ; Page Table Entries (2048 * 2MB entries => 4GB) + ; + TIMES 508 DQ 0 + +%assign i 0 +%rep 0x800 + DQ PTE_2MB(i) + %assign i i+1 +%endrep + +EndOfPageTables: diff --git a/td-shim/ResetVector/X64/TestHob.asm b/td-shim/ResetVector/X64/TestHob.asm new file mode 100644 index 00000000..572c5408 --- /dev/null +++ b/td-shim/ResetVector/X64/TestHob.asm @@ -0,0 +1,56 @@ +;------------------------------------------------------------------------------ +; @file +; Emits Page Tables for 1:1 mapping of the addresses 0 - 0x100000000 (4GB) +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +KvmTestHob: + DW EFI_HOB_TYPE_HANDOFF + DW 0x38 + DD 0 + DD 9 + DD 0 ; boot-mode + DQ 0 + DQ 0 + DQ 0 + DQ 0 + DQ ADDR_OF(KvmTestHobEnd) + DW EFI_HOB_TYPE_GUID_EXTENSION + DW 0x1c + DD 0 + ; 0xc4a567a3, 0xc8a5, 0x44ea, 0xac, 0x78, 0xa4, 0xc3, 0x8b, 0x85, 0x49, 0xd0 Name + DD 0xc4a567a3 + DW 0xc8a5, 0x44ea + DB 0xac, 0x78, 0xa4, 0xc3, 0x8b, 0x85, 0x49, 0xd0 + DD 0 ; Feature + DW EFI_HOB_TYPE_RESOURCE_DESCRIPTOR + DW 0x30 + DD 0 + TIMES 16 DB 0 ; Owner + DD EFI_RESOURCE_SYSTEM_MEMORY ; ResourceType + DD EFI_LOW_MEM_ATTR ; ResourceAttribute + DQ 0x100000 ; PhysicalStart + DQ 0x7FF00000 ; ResourceLength + DW EFI_HOB_TYPE_RESOURCE_DESCRIPTOR + DW 0x30 + DD 0 + TIMES 16 DB 0 ; Owner + DD EFI_RESOURCE_SYSTEM_MEMORY ; ResourceType + DD EFI_LOW_MEM_ATTR ; ResourceAttribute + DQ 0x0 ; PhysicalStart + DQ 0xa0000 ; ResourceLength + DW EFI_HOB_TYPE_RESOURCE_DESCRIPTOR + DW 0x30 + DD 0 + TIMES 16 DB 0 ; Owner + DD EFI_RESOURCE_SYSTEM_MEMORY ; ResourceType + DD EFI_LOW_MEM_ATTR ; ResourceAttribute + DQ 0x1a00000000 ; PhysicalStart + DQ 0x80000000 ; ResourceLength + DW EFI_HOB_TYPE_END_OF_HOB_LIST + DW 0x08 + DD 0 +KvmTestHobEnd: diff --git a/td-shim/build.rs b/td-shim/build.rs new file mode 100644 index 00000000..ff1ae7a4 --- /dev/null +++ b/td-shim/build.rs @@ -0,0 +1,251 @@ +// Copyright (c) 2020 Intel Corporation +// +// SPDX-License-Identifier: BSD-2-Clause-Patent + +use anyhow::Result; +use std::{ + env, format, + path::{Path, PathBuf}, + process::{exit, Command}, +}; +use td_layout::build_time; + +fn nasm(file: &Path, arch: &str, out_file: &Path, args: &[&str]) -> Command { + let oformat = match arch { + "x86_64" => ("win64"), + "x86" => ("win32"), + "bin" => ("bin"), + _ => panic!("unsupported arch: {}", arch), + }; + let mut c = Command::new("nasm"); + let _ = c + .arg("-o") + .arg(out_file.to_str().expect("Invalid path")) + .arg("-f") + .arg(oformat) + .arg(file); + for arg in args { + let _ = c.arg(*arg); + } + c +} + +fn run_command(mut cmd: Command) { + eprintln!("running {:?}", cmd); + let status = cmd.status().unwrap_or_else(|e| { + panic!("failed to execute [{:?}]: {}", cmd, e); + }); + if !status.success() { + panic!("execution failed"); + } +} + +#[cfg(target = "x86_64-unknown-uefi")] +// clang is only required when building ring with the x86_64-unknown-uefi target. #109 +fn check_environment() -> Result<()> { + use anyhow::anyhow; + use which::which; + const CC_ENV_VAR: &str = "CC_x86_64_unknown_uefi"; + const AS_ENV_VAR: &str = "AS"; + const AR_ENV_VAR: &str = "AR_x86_64_unknown_uefi"; + + // Defaults to 'cc' but also honours the CC_ENV_VAR environment variable. + let cfg = cc::Build::new().try_get_compiler()?; + + // GCC cannot be used as it fails to link. + let required_compiler = "clang"; + + let required_assembler = "nasm"; + let required_archiver = "llvm-ar"; + + let cc_path = cfg.path().to_path_buf(); + let as_path = + PathBuf::from(env::var(AS_ENV_VAR).unwrap_or_else(|_| required_assembler.to_string())); + let ar_path = + PathBuf::from(env::var(AR_ENV_VAR).unwrap_or_else(|_| required_archiver.to_string())); + + struct BuildDependency<'a> { + path: PathBuf, + description: &'a str, + env_var: &'a str, + required_cmd: &'a str, + } + + // List is not sorted alphabetically to help the user on error: the + // compiler name is more commonly known than the archiver name, so if + // that's missing, show it first. + // + // Also installing the missing compiler will probably install the archiver + // as a dependency. + let cmds = &[ + BuildDependency { + path: as_path, + description: "assembler", + env_var: AS_ENV_VAR, + required_cmd: required_assembler, + }, + BuildDependency { + path: cc_path, + description: "compiler", + env_var: CC_ENV_VAR, + required_cmd: required_compiler, + }, + BuildDependency { + path: ar_path, + description: "archiver", + env_var: AR_ENV_VAR, + required_cmd: required_archiver, + }, + ]; + + for cmd in cmds { + let BuildDependency { + path, + description, + env_var, + required_cmd, + } = cmd; + + println!("cargo:rerun-if-env-changed={}", env_var); + + let resolved_path = which(path) + .map_err(|e| { + anyhow!( + "cannot find {:} command {:?}: {:?} (expected {:?})", + description, + path, + e, + required_cmd + ) + })? + .canonicalize() + .map_err(|e| { + anyhow!( + "cannot resolve {:} command {:?}: {:?}", + description, + path, + e + ) + })?; + + if !resolved_path + .to_str() + .ok_or("cannot convert path to string") + .map_err(|e| anyhow!("{:?}", e))? + .contains(required_cmd) + { + return Err(anyhow!( + "{:} command {:?} is not {:?} - do you need to set ${:}?", + description, + path, + required_cmd, + env_var + )); + } + } + + Ok(()) +} + +fn real_main() -> Result<()> { + // tell cargo when to re-run the script + println!("cargo:rerun-if-changed=build.rs"); + + #[cfg(target = "x86_64-unknown-uefi")] + check_environment()?; + + println!( + "cargo:rerun-if-changed={}", + Path::new("ResetVector/ResetVector.asm").to_str().unwrap() + ); + + let reset_vector_src_dir = get_cargo_manifest_dir().join("ResetVector"); + let reset_vector_bin_file = get_target_output_dir().join("ResetVector.bin"); + + let use_tdx_emulation_arg = format!( + "-DUSE_TDX_EMULATION={}", + if tdx_tdcall::USE_TDX_EMULATION { + 1u8 + } else { + 0u8 + } + ); + let td_shim_ipl_base_arg = format!("-DTOP_OF_BFV=0x{:X}", build_time::TD_SHIM_IPL_BASE); + let td_mailbox_base_arg = format!("-DTD_MAILBOX_BASE=0x{:X}", build_time::TD_SHIM_MAILBOX_BASE); + let td_mailbox_size_arg = format!("-DTD_MAILBOX_SIZE=0x{:X}", build_time::TD_SHIM_MAILBOX_SIZE); + let td_shim_hob_base_arg = format!("-DTD_HOB_BASE=0x{:X}", build_time::TD_SHIM_HOB_BASE); + let td_shim_hob_size_arg = format!("-DTD_HOB_SIZE=0x{:X}", build_time::TD_SHIM_HOB_SIZE); + let td_shim_tmp_stack_base_arg = format!( + "-DTEMP_STACK_BASE=0x{:X}", + build_time::TD_SHIM_TEMP_STACK_BASE + ); + let td_shim_tmp_stack_size_arg = format!( + "-DTEMP_STACK_SIZE=0x{:X}", + build_time::TD_SHIM_TEMP_STACK_SIZE + ); + let td_shim_tmp_heap_base_arg = + format!("-DTEMP_RAM_BASE=0x{:X}", build_time::TD_SHIM_TEMP_HEAP_BASE); + let td_shim_tmp_heap_size_arg = + format!("-DTEMP_RAM_SIZE=0x{:X}", build_time::TD_SHIM_TEMP_HEAP_SIZE); + + let loaded_sec_entrypoint_base = format!( + "-DTD_SHIM_RESET_SEC_CORE_ENTRY_POINT_ADDR=0x{:X}", + build_time::TD_SHIM_RESET_SEC_CORE_ENTRY_POINT_ADDR + ); + let loaded_sec_core_base = format!( + "-DTD_SHIM_RESET_SEC_CORE_BASE_ADDR=0x{:X}", + build_time::TD_SHIM_RESET_SEC_CORE_BASE_ADDR + ); + let loaded_sec_core_size = format!( + "-DTD_SHIM_RESET_SEC_CORE_SIZE_ADDR=0x{:X}", + build_time::TD_SHIM_RESET_SEC_CORE_SIZE_ADDR + ); + + let _ = env::set_current_dir(reset_vector_src_dir.as_path()); + run_command(nasm( + Path::new("ResetVector.nasm"), + "bin", + reset_vector_bin_file.as_path(), + &[ + &use_tdx_emulation_arg, + &td_shim_ipl_base_arg, + &td_mailbox_base_arg, + &td_mailbox_size_arg, + &td_shim_hob_base_arg, + &td_shim_hob_size_arg, + &td_shim_tmp_stack_base_arg, + &td_shim_tmp_stack_size_arg, + &td_shim_tmp_heap_base_arg, + &td_shim_tmp_heap_size_arg, + &loaded_sec_entrypoint_base, + &loaded_sec_core_base, + &loaded_sec_core_size, + ], + )); + + Ok(()) +} + +fn get_target_output_dir() -> PathBuf { + // In build script, this is set to the folder + // where the build script should place its output. + let out_dir = env::var("OUT_DIR").unwrap(); + let path = PathBuf::from(out_dir); + + // Build script outputs relative to target outputs. + // Therefore we get target outputs path. + path.join("../../..") +} + +fn get_cargo_manifest_dir() -> PathBuf { + // Environment variables Cargo sets for crates + // The directory containing the manifest of your package. + PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()) +} + +fn main() { + if let Err(e) = real_main() { + eprintln!("ERROR: {:#}", e); + exit(1); + } +} diff --git a/td-shim/src/lib.rs b/td-shim/src/lib.rs new file mode 100644 index 00000000..4b470e46 --- /dev/null +++ b/td-shim/src/lib.rs @@ -0,0 +1,5 @@ +// Copyright (c) 2022 Alibaba Cloud +// +// SPDX-License-Identifier: BSD-2-Clause-Patent + +#![no_std]