--- /dev/null
+/** @file\r
+ Main SEC phase code. Transitions to PEI.\r
+\r
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiCpuLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/CpuExceptionHandlerLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <Library/PlatformInitLib.h>\r
+\r
+#include <Library/PeilessStartupLib.h>\r
+\r
+#define SEC_IDT_ENTRY_COUNT 34\r
+\r
+typedef struct _SEC_IDT_TABLE {\r
+ EFI_PEI_SERVICES *PeiService;\r
+ IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];\r
+} SEC_IDT_TABLE;\r
+\r
+//\r
+// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
+//\r
+IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {\r
+ { // Bits\r
+ 0xffe4, // OffsetLow\r
+ 0x10, // Selector\r
+ 0x0, // Reserved_0\r
+ IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType\r
+ 0xffff // OffsetHigh\r
+ }\r
+};\r
+\r
+VOID\r
+EFIAPI\r
+SecCoreStartupWithStack (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
+ IN VOID *TopOfCurrentStack\r
+ )\r
+{\r
+ EFI_SEC_PEI_HAND_OFF SecCoreData;\r
+ SEC_IDT_TABLE IdtTableInStack;\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINT32 Index;\r
+ volatile UINT8 *Table;\r
+\r
+ if (TdIsEnabled ()) {\r
+ //\r
+ // For Td guests, the memory map info is in TdHobLib. It should be processed\r
+ // first so that the memory is accepted. Otherwise access to the unaccepted\r
+ // memory will trigger tripple fault.\r
+ //\r
+ if (ProcessTdxHobList () != EFI_SUCCESS) {\r
+ CpuDeadLoop ();\r
+ }\r
+ }\r
+\r
+ //\r
+ // To ensure SMM can't be compromised on S3 resume, we must force re-init of\r
+ // the BaseExtractGuidedSectionLib. Since this is before library contructors\r
+ // are called, we must use a loop rather than SetMem.\r
+ //\r
+ Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);\r
+ for (Index = 0;\r
+ Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);\r
+ ++Index)\r
+ {\r
+ Table[Index] = 0;\r
+ }\r
+\r
+ //\r
+ // Initialize IDT - Since this is before library constructors are called,\r
+ // we use a loop rather than CopyMem.\r
+ //\r
+ IdtTableInStack.PeiService = NULL;\r
+\r
+ for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
+ //\r
+ // Declare the local variables that actually move the data elements as\r
+ // volatile to prevent the optimizer from replacing this function with\r
+ // the intrinsic memcpy()\r
+ //\r
+ CONST UINT8 *Src;\r
+ volatile UINT8 *Dst;\r
+ UINTN Byte;\r
+\r
+ Src = (CONST UINT8 *)&mIdtEntryTemplate;\r
+ Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];\r
+\r
+ for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {\r
+ Dst[Byte] = Src[Byte];\r
+ }\r
+ }\r
+\r
+ IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
+ IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
+\r
+ ProcessLibraryConstructorList (NULL, NULL);\r
+\r
+ //\r
+ // Load the IDTR.\r
+ //\r
+ AsmWriteIdtr (&IdtDescriptor);\r
+\r
+ if (TdIsEnabled ()) {\r
+ //\r
+ // InitializeCpuExceptionHandlers () should be called in Td guests so that\r
+ // #VE exceptions can be handled correctly.\r
+ //\r
+ InitializeCpuExceptionHandlers (NULL);\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
+ (UINT32)(UINTN)BootFv,\r
+ (UINT32)(UINTN)TopOfCurrentStack\r
+ ));\r
+\r
+ //\r
+ // Initialize floating point operating environment\r
+ // to be compliant with UEFI spec.\r
+ //\r
+ InitializeFloatingPointUnits ();\r
+\r
+ //\r
+ // ASSERT that the Page Tables were set by the reset vector code to\r
+ // the address we expect.\r
+ //\r
+ ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));\r
+\r
+ //\r
+ // |-------------| <-- TopOfCurrentStack\r
+ // | Stack | 32k\r
+ // |-------------|\r
+ // | Heap | 32k\r
+ // |-------------| <-- SecCoreData.TemporaryRamBase\r
+ //\r
+\r
+ ASSERT (\r
+ (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
+ PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
+ (UINTN)TopOfCurrentStack\r
+ );\r
+\r
+ //\r
+ // Initialize SEC hand-off state\r
+ //\r
+ SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);\r
+\r
+ SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
+ SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
+\r
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
+ SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+ SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
+ SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+ SecCoreData.BootFirmwareVolumeBase = BootFv;\r
+ SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;\r
+\r
+ //\r
+ // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
+ //\r
+ IoWrite8 (0x21, 0xff);\r
+ IoWrite8 (0xA1, 0xff);\r
+\r
+ //\r
+ // Initialize Local APIC Timer hardware and disable Local APIC Timer\r
+ // interrupts before initializing the Debug Agent and the debug timer is\r
+ // enabled.\r
+ //\r
+ InitializeApicTimer (0, MAX_UINT32, TRUE, 5);\r
+ DisableApicTimerInterrupt ();\r
+\r
+ PeilessStartup (&SecCoreData);\r
+\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+}\r
--- /dev/null
+## @file\r
+# SEC Driver\r
+#\r
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SecMain\r
+ FILE_GUID = 69d96630-eb64-4b33-8491-13a5cf023dcf\r
+ MODULE_TYPE = SEC\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = SecMain\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = X64\r
+#\r
+\r
+[Sources]\r
+ SecMain.c\r
+ X64/SecEntry.nasm\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+ OvmfPkg/OvmfPkg.dec\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ DebugLib\r
+ BaseMemoryLib\r
+ PcdLib\r
+ UefiCpuLib\r
+ DebugAgentLib\r
+ IoLib\r
+ PeCoffLib\r
+ PeCoffGetEntryPointLib\r
+ PeCoffExtraActionLib\r
+ ExtractGuidedSectionLib\r
+ LocalApicLib\r
+ MemEncryptSevLib\r
+ CpuExceptionHandlerLib\r
+ PeilessStartupLib\r
+ PlatformInitLib\r
+\r
+[Pcd]\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize\r
+ gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase\r
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;*\r
+;* Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+;* SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;*\r
+;* CpuAsm.asm\r
+;*\r
+;* Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+#include <Base.h>\r
+%include "TdxCommondefs.inc"\r
+\r
+DEFAULT REL\r
+SECTION .text\r
+\r
+extern ASM_PFX(SecCoreStartupWithStack)\r
+\r
+%macro tdcall 0\r
+ db 0x66, 0x0f, 0x01, 0xcc\r
+%endmacro\r
+\r
+;\r
+; SecCore Entry Point\r
+;\r
+; Processor is in flat protected mode\r
+;\r
+; @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test)\r
+; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor\r
+; @param[in] RBP Pointer to the start of the Boot Firmware Volume\r
+; @param[in] DS Selector allowing flat access to all addresses\r
+; @param[in] ES Selector allowing flat access to all addresses\r
+; @param[in] FS Selector allowing flat access to all addresses\r
+; @param[in] GS Selector allowing flat access to all addresses\r
+; @param[in] SS Selector allowing flat access to all addresses\r
+;\r
+; @return None This routine does not return\r
+;\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+\r
+ ;\r
+ ; Guest type is stored in OVMF_WORK_AREA\r
+ ;\r
+ %define OVMF_WORK_AREA FixedPcdGet32 (PcdOvmfWorkAreaBase)\r
+ %define VM_GUEST_TYPE_TDX 2\r
+ mov eax, OVMF_WORK_AREA\r
+ cmp byte[eax], VM_GUEST_TYPE_TDX\r
+ jne InitStack\r
+\r
+ mov rax, TDCALL_TDINFO\r
+ tdcall\r
+\r
+ ;\r
+ ; R8 [31:0] NUM_VCPUS\r
+ ; [63:32] MAX_VCPUS\r
+ ; R9 [31:0] VCPU_INDEX\r
+ ; Td Guest set the VCPU0 as the BSP, others are the APs\r
+ ; APs jump to spinloop and get released by DXE's MpInitLib\r
+ ;\r
+ mov rax, r9\r
+ and rax, 0xffff\r
+ test rax, rax\r
+ jne ParkAp\r
+\r
+InitStack:\r
+\r
+ ;\r
+ ; Fill the temporary RAM with the initial stack value.\r
+ ; The loop below will seed the heap as well, but that's harmless.\r
+ ;\r
+ mov rax, (FixedPcdGet32 (PcdInitValueInTempStack) << 32) | FixedPcdGet32 (PcdInitValueInTempStack)\r
+ ; qword to store\r
+ mov rdi, FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) ; base address,\r
+ ; relative to\r
+ ; ES\r
+ mov rcx, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 8 ; qword count\r
+ cld ; store from base\r
+ ; up\r
+ rep stosq\r
+\r
+ ;\r
+ ; Load temporary RAM stack based on PCDs\r
+ ;\r
+ %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + \\r
+ FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))\r
+ mov rsp, SEC_TOP_OF_STACK\r
+ nop\r
+\r
+ ;\r
+ ; Setup parameters and call SecCoreStartupWithStack\r
+ ; rcx: BootFirmwareVolumePtr\r
+ ; rdx: TopOfCurrentStack\r
+ ;\r
+ mov rcx, rbp\r
+ mov rdx, rsp\r
+ sub rsp, 0x20\r
+ call ASM_PFX(SecCoreStartupWithStack)\r
+\r
+ ;\r
+ ; Note: BSP never gets here. APs will be unblocked by DXE\r
+ ;\r
+ ; R8 [31:0] NUM_VCPUS\r
+ ; [63:32] MAX_VCPUS\r
+ ; R9 [31:0] VCPU_INDEX\r
+ ;\r
+ParkAp:\r
+\r
+ mov rbp, r9\r
+\r
+.do_wait_loop:\r
+ mov rsp, FixedPcdGet32 (PcdOvmfSecGhcbBackupBase)\r
+\r
+ ;\r
+ ; register itself in [rsp + CpuArrivalOffset]\r
+ ;\r
+ mov rax, 1\r
+ lock xadd dword [rsp + CpuArrivalOffset], eax\r
+ inc eax\r
+\r
+.check_arrival_cnt:\r
+ cmp eax, r8d\r
+ je .check_command\r
+ mov eax, dword[rsp + CpuArrivalOffset]\r
+ jmp .check_arrival_cnt\r
+\r
+.check_command:\r
+ mov eax, dword[rsp + CommandOffset]\r
+ cmp eax, MpProtectedModeWakeupCommandNoop\r
+ je .check_command\r
+\r
+ cmp eax, MpProtectedModeWakeupCommandWakeup\r
+ je .do_wakeup\r
+\r
+ ; Don't support this command, so ignore\r
+ jmp .check_command\r
+\r
+.do_wakeup:\r
+ ;\r
+ ; BSP sets these variables before unblocking APs\r
+ ; RAX: WakeupVectorOffset\r
+ ; RBX: Relocated mailbox address\r
+ ; RBP: vCpuId\r
+ ;\r
+ mov rax, 0\r
+ mov eax, dword[rsp + WakeupVectorOffset]\r
+ mov rbx, [rsp + WakeupArgsRelocatedMailBox]\r
+ nop\r
+ jmp rax\r
+ jmp $\r