]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/IntelTdx/Sec/SecMain.c
ab01ec9ab19c796738d41a0eb2b5754b4c7d890c
[mirror_edk2.git] / OvmfPkg / IntelTdx / Sec / SecMain.c
1 /** @file
2 Main SEC phase code. Transitions to PEI.
3
4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <PiPei.h>
13
14 #include <Library/PeimEntryPoint.h>
15 #include <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/UefiCpuLib.h>
20 #include <Library/DebugAgentLib.h>
21 #include <Library/IoLib.h>
22 #include <Library/PeCoffLib.h>
23 #include <Library/PeCoffGetEntryPointLib.h>
24 #include <Library/LocalApicLib.h>
25 #include <Library/CpuExceptionHandlerLib.h>
26 #include <IndustryStandard/Tdx.h>
27 #include <Library/PlatformInitLib.h>
28 #include <Library/CcProbeLib.h>
29 #include <Library/PeilessStartupLib.h>
30
31 #define SEC_IDT_ENTRY_COUNT 34
32
33 typedef struct _SEC_IDT_TABLE {
34 EFI_PEI_SERVICES *PeiService;
35 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
36 } SEC_IDT_TABLE;
37
38 //
39 // Template of an IDT entry pointing to 10:FFFFFFE4h.
40 //
41 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {
42 { // Bits
43 0xffe4, // OffsetLow
44 0x10, // Selector
45 0x0, // Reserved_0
46 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType
47 0xffff // OffsetHigh
48 }
49 };
50
51 VOID
52 EFIAPI
53 SecCoreStartupWithStack (
54 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
55 IN VOID *TopOfCurrentStack
56 )
57 {
58 EFI_SEC_PEI_HAND_OFF SecCoreData;
59 SEC_IDT_TABLE IdtTableInStack;
60 IA32_DESCRIPTOR IdtDescriptor;
61 UINT32 Index;
62 volatile UINT8 *Table;
63
64 if (CcProbe () == CcGuestTypeIntelTdx) {
65 //
66 // For Td guests, the memory map info is in TdHobLib. It should be processed
67 // first so that the memory is accepted. Otherwise access to the unaccepted
68 // memory will trigger tripple fault.
69 //
70 if (ProcessTdxHobList () != EFI_SUCCESS) {
71 CpuDeadLoop ();
72 }
73 }
74
75 //
76 // To ensure SMM can't be compromised on S3 resume, we must force re-init of
77 // the BaseExtractGuidedSectionLib. Since this is before library contructors
78 // are called, we must use a loop rather than SetMem.
79 //
80 Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
81 for (Index = 0;
82 Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
83 ++Index)
84 {
85 Table[Index] = 0;
86 }
87
88 //
89 // Initialize IDT - Since this is before library constructors are called,
90 // we use a loop rather than CopyMem.
91 //
92 IdtTableInStack.PeiService = NULL;
93
94 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {
95 //
96 // Declare the local variables that actually move the data elements as
97 // volatile to prevent the optimizer from replacing this function with
98 // the intrinsic memcpy()
99 //
100 CONST UINT8 *Src;
101 volatile UINT8 *Dst;
102 UINTN Byte;
103
104 Src = (CONST UINT8 *)&mIdtEntryTemplate;
105 Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];
106
107 for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {
108 Dst[Byte] = Src[Byte];
109 }
110 }
111
112 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
113 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
114
115 ProcessLibraryConstructorList (NULL, NULL);
116
117 //
118 // Load the IDTR.
119 //
120 AsmWriteIdtr (&IdtDescriptor);
121
122 if (CcProbe () == CcGuestTypeIntelTdx) {
123 //
124 // InitializeCpuExceptionHandlers () should be called in Td guests so that
125 // #VE exceptions can be handled correctly.
126 //
127 InitializeCpuExceptionHandlers (NULL);
128 }
129
130 DEBUG ((
131 DEBUG_INFO,
132 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
133 (UINT32)(UINTN)BootFv,
134 (UINT32)(UINTN)TopOfCurrentStack
135 ));
136
137 //
138 // Initialize floating point operating environment
139 // to be compliant with UEFI spec.
140 //
141 InitializeFloatingPointUnits ();
142
143 //
144 // ASSERT that the Page Tables were set by the reset vector code to
145 // the address we expect.
146 //
147 ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));
148
149 //
150 // |-------------| <-- TopOfCurrentStack
151 // | Stack | 32k
152 // |-------------|
153 // | Heap | 32k
154 // |-------------| <-- SecCoreData.TemporaryRamBase
155 //
156
157 ASSERT (
158 (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +
159 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
160 (UINTN)TopOfCurrentStack
161 );
162
163 //
164 // Initialize SEC hand-off state
165 //
166 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
167
168 SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);
169 SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
170
171 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
172 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
173
174 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
175 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
176
177 SecCoreData.BootFirmwareVolumeBase = BootFv;
178 SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
179
180 //
181 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
182 //
183 IoWrite8 (0x21, 0xff);
184 IoWrite8 (0xA1, 0xff);
185
186 //
187 // Initialize Local APIC Timer hardware and disable Local APIC Timer
188 // interrupts before initializing the Debug Agent and the debug timer is
189 // enabled.
190 //
191 InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
192 DisableApicTimerInterrupt ();
193
194 PeilessStartup (&SecCoreData);
195
196 ASSERT (FALSE);
197 CpuDeadLoop ();
198 }