]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/SecMain.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / SecMain.c
1 /** @file
2
3 Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include "SecMain.h"
9 #include "SecFsp.h"
10
11 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
12 SecTemporaryRamSupport
13 };
14
15 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
16 {
17 EFI_PEI_PPI_DESCRIPTOR_PPI,
18 &gFspInApiModePpiGuid,
19 NULL
20 },
21 {
22 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
23 &gEfiTemporaryRamSupportPpiGuid,
24 &gSecTemporaryRamSupportPpi
25 }
26 };
27
28 //
29 // These are IDT entries pointing to 08:FFFFFFE4h.
30 //
31 UINT64 mIdtEntryTemplate = 0xffff8e000008ffe4ULL;
32
33 /**
34
35 Entry point to the C language phase of SEC. After the SEC assembly
36 code has initialized some temporary memory and set up the stack,
37 the control is transferred to this function.
38
39
40 @param[in] SizeOfRam Size of the temporary memory available for use.
41 @param[in] TempRamBase Base address of temporary ram
42 @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
43 @param[in] PeiCore PeiCore entry point.
44 @param[in] BootLoaderStack BootLoader stack.
45 @param[in] ApiIdx the index of API.
46
47 @return This function never returns.
48
49 **/
50 VOID
51 EFIAPI
52 SecStartup (
53 IN UINT32 SizeOfRam,
54 IN UINT32 TempRamBase,
55 IN VOID *BootFirmwareVolume,
56 IN PEI_CORE_ENTRY PeiCore,
57 IN UINTN BootLoaderStack,
58 IN UINT32 ApiIdx
59 )
60 {
61 EFI_SEC_PEI_HAND_OFF SecCoreData;
62 IA32_DESCRIPTOR IdtDescriptor;
63 SEC_IDT_TABLE IdtTableInStack;
64 UINT32 Index;
65 FSP_GLOBAL_DATA PeiFspData;
66 IA32_IDT_GATE_DESCRIPTOR ExceptionHandler;
67 UINTN IdtSize;
68
69 //
70 // Process all libraries constructor function linked to SecCore.
71 //
72 ProcessLibraryConstructorList ();
73
74 //
75 // Initialize floating point operating environment
76 // to be compliant with UEFI spec.
77 //
78 InitializeFloatingPointUnits ();
79
80 //
81 // Scenario 1 memory map when running on bootloader stack
82 //
83 // |-------------------|---->
84 // |Idt Table |
85 // |-------------------|
86 // |PeiService Pointer |
87 // |-------------------|
88 // | |
89 // | |
90 // | Heap |
91 // | |
92 // | |
93 // |-------------------|----> TempRamBase
94 //
95 //
96 // |-------------------|
97 // |Bootloader stack |----> somewhere in memory, FSP will share this stack.
98 // |-------------------|
99
100 //
101 // Scenario 2 memory map when running FSP on a separate stack
102 //
103 // |-------------------|---->
104 // |Idt Table |
105 // |-------------------|
106 // |PeiService Pointer | PeiStackSize
107 // |-------------------|
108 // | |
109 // | Stack |
110 // |-------------------|---->
111 // | |
112 // | |
113 // | Heap | PeiTemporaryRamSize
114 // | |
115 // | |
116 // |-------------------|----> TempRamBase
117 IdtTableInStack.PeiService = 0;
118 AsmReadIdtr (&IdtDescriptor);
119 if (IdtDescriptor.Base == 0) {
120 ExceptionHandler = FspGetExceptionHandler (mIdtEntryTemplate);
121 for (Index = 0; Index < FixedPcdGet8 (PcdFspMaxInterruptSupported); Index++) {
122 CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&ExceptionHandler, sizeof (IA32_IDT_GATE_DESCRIPTOR));
123 }
124
125 IdtSize = sizeof (IdtTableInStack.IdtTable);
126 } else {
127 IdtSize = IdtDescriptor.Limit + 1;
128 if (IdtSize > sizeof (IdtTableInStack.IdtTable)) {
129 //
130 // ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
131 //
132 CpuDeadLoop ();
133 } else {
134 CopyMem ((VOID *)(UINTN)&IdtTableInStack.IdtTable, (VOID *)IdtDescriptor.Base, IdtSize);
135 }
136 }
137
138 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
139 IdtDescriptor.Limit = (UINT16)(IdtSize - 1);
140
141 AsmWriteIdtr (&IdtDescriptor);
142
143 //
144 // Initialize the global FSP data region
145 //
146 FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx);
147
148 //
149 // Update the base address and length of Pei temporary memory
150 //
151 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
152 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
153 SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
154
155 //
156 // Support FSP reserved temporary memory from the whole temporary memory provided by bootloader.
157 // FSP reserved temporary memory will not be given to PeiCore.
158 //
159 SecCoreData.TemporaryRamBase = (UINT8 *)(UINTN)TempRamBase + PcdGet32 (PcdFspPrivateTemporaryRamSize);
160 SecCoreData.TemporaryRamSize = SizeOfRam - PcdGet32 (PcdFspPrivateTemporaryRamSize);
161 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
162 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
163 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize;
164 SecCoreData.StackBase = (VOID *)GetFspEntryStack (); // Share the same boot loader stack
165 SecCoreData.StackSize = 0;
166 } else {
167 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
168 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
169 SecCoreData.StackBase = (VOID *)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
170 SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize;
171 }
172
173 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
174 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
175 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase));
176 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize));
177 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
178 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
179 DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase));
180 DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize));
181
182 //
183 // Call PeiCore Entry
184 //
185 PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
186
187 //
188 // Should never be here
189 //
190 CpuDeadLoop ();
191 }
192
193 /**
194 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
195 permanent memory.
196
197 @param[in] PeiServices Pointer to the PEI Services Table.
198 @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
199 Temporary RAM contents.
200 @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
201 Temporary RAM contents.
202 @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
203
204 @retval EFI_SUCCESS The data was successfully returned.
205 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
206 TemporaryMemoryBase > PermanentMemoryBase.
207
208 **/
209 EFI_STATUS
210 EFIAPI
211 SecTemporaryRamSupport (
212 IN CONST EFI_PEI_SERVICES **PeiServices,
213 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
214 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
215 IN UINTN CopySize
216 )
217 {
218 IA32_DESCRIPTOR IdtDescriptor;
219 VOID *OldHeap;
220 VOID *NewHeap;
221 VOID *OldStack;
222 VOID *NewStack;
223 UINTN HeapSize;
224 UINTN StackSize;
225
226 UINTN CurrentStack;
227 UINTN FspStackBase;
228
229 //
230 // Override OnSeparateStack to 1 because this function will switch stack to permanent memory
231 // which makes FSP running on different stack from bootloader temporary ram stack.
232 //
233 GetFspGlobalDataPointer ()->OnSeparateStack = 1;
234
235 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
236 CurrentStack = AsmReadStackPointer ();
237 FspStackBase = (UINTN)GetFspEntryStack ();
238
239 StackSize = FspStackBase - CurrentStack;
240 HeapSize = CopySize;
241
242 OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
243 NewHeap = (VOID *)((UINTN)PermanentMemoryBase);
244
245 OldStack = (VOID *)CurrentStack;
246 //
247 // The old stack is copied at the end of the stack region because stack grows down.
248 //
249 NewStack = (VOID *)((UINTN)PermanentMemoryBase - StackSize);
250 } else {
251 HeapSize = CopySize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
252 StackSize = CopySize - HeapSize;
253
254 OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
255 NewHeap = (VOID *)((UINTN)PermanentMemoryBase + StackSize);
256
257 OldStack = (VOID *)((UINTN)TemporaryMemoryBase + HeapSize);
258 NewStack = (VOID *)(UINTN)PermanentMemoryBase;
259 }
260
261 //
262 // Migrate Heap
263 //
264 CopyMem (NewHeap, OldHeap, HeapSize);
265
266 //
267 // Migrate Stack
268 //
269 CopyMem (NewStack, OldStack, StackSize);
270
271 //
272 // We need *not* fix the return address because currently,
273 // The PeiCore is executed in flash.
274 //
275
276 //
277 // Rebase IDT table in permanent memory
278 //
279 AsmReadIdtr (&IdtDescriptor);
280 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
281
282 AsmWriteIdtr (&IdtDescriptor);
283
284 //
285 // Fixed the FSP data pointer
286 //
287 FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
288
289 //
290 // SecSwitchStack function must be invoked after the memory migration
291 // immediately, also we need fixup the stack change caused by new call into
292 // permanent memory.
293 //
294 SecSwitchStack (
295 (UINTN)OldStack,
296 (UINTN)NewStack
297 );
298
299 return EFI_SUCCESS;
300 }