]> 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 - 2020, 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 UINT32 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 UINT64 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 (UINT64));
123 }
124 IdtSize = sizeof (IdtTableInStack.IdtTable);
125 } else {
126 IdtSize = IdtDescriptor.Limit + 1;
127 if (IdtSize > sizeof (IdtTableInStack.IdtTable)) {
128 //
129 // ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
130 //
131 CpuDeadLoop();
132 } else {
133 CopyMem ((VOID *) (UINTN) &IdtTableInStack.IdtTable, (VOID *) IdtDescriptor.Base, IdtSize);
134 }
135 }
136 IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
137 IdtDescriptor.Limit = (UINT16)(IdtSize - 1);
138
139 AsmWriteIdtr (&IdtDescriptor);
140
141 //
142 // Initialize the global FSP data region
143 //
144 FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx);
145
146 //
147 // Update the base address and length of Pei temporary memory
148 //
149 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
150 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
151 SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
152
153 SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
154 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
155 SecCoreData.TemporaryRamSize = SizeOfRam; // stack size that is going to be copied to the permanent memory
156 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
157 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize;
158 SecCoreData.StackBase = (VOID *)GetFspEntryStack(); // Share the same boot loader stack
159 SecCoreData.StackSize = 0;
160 } else {
161 SecCoreData.TemporaryRamSize = SizeOfRam;
162 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
163 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
164 SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
165 SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize;
166 }
167
168 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
169 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
170 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase));
171 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize));
172 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
173 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
174 DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase));
175 DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize));
176
177 //
178 // Call PeiCore Entry
179 //
180 PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
181
182 //
183 // Should never be here
184 //
185 CpuDeadLoop ();
186 }
187
188 /**
189 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
190 permanent memory.
191
192 @param[in] PeiServices Pointer to the PEI Services Table.
193 @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
194 Temporary RAM contents.
195 @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
196 Temporary RAM contents.
197 @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
198
199 @retval EFI_SUCCESS The data was successfully returned.
200 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
201 TemporaryMemoryBase > PermanentMemoryBase.
202
203 **/
204 EFI_STATUS
205 EFIAPI
206 SecTemporaryRamSupport (
207 IN CONST EFI_PEI_SERVICES **PeiServices,
208 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
209 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
210 IN UINTN CopySize
211 )
212 {
213 IA32_DESCRIPTOR IdtDescriptor;
214 VOID* OldHeap;
215 VOID* NewHeap;
216 VOID* OldStack;
217 VOID* NewStack;
218 UINTN HeapSize;
219 UINTN StackSize;
220
221 UINTN CurrentStack;
222 UINTN FspStackBase;
223
224 //
225 // Override OnSeparateStack to 1 because this function will switch stack to permanent memory
226 // which makes FSP running on different stack from bootloader temporary ram stack.
227 //
228 GetFspGlobalDataPointer ()->OnSeparateStack = 1;
229
230 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
231
232 CurrentStack = AsmReadEsp();
233 FspStackBase = (UINTN)GetFspEntryStack();
234
235 StackSize = FspStackBase - CurrentStack;
236 HeapSize = CopySize;
237
238 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
239 NewHeap = (VOID*)((UINTN)PermanentMemoryBase);
240
241 OldStack = (VOID*)CurrentStack;
242 //
243 //The old stack is copied at the end of the stack region because stack grows down.
244 //
245 NewStack = (VOID*)((UINTN)PermanentMemoryBase - StackSize);
246
247 } else {
248 HeapSize = CopySize * PcdGet8 (PcdFspHeapSizePercentage) / 100 ;
249 StackSize = CopySize - HeapSize;
250
251 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
252 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + StackSize);
253
254 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
255 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
256
257 }
258 //
259 // Migrate Heap
260 //
261 CopyMem (NewHeap, OldHeap, HeapSize);
262
263 //
264 // Migrate Stack
265 //
266 CopyMem (NewStack, OldStack, StackSize);
267
268
269 //
270 // We need *not* fix the return address because currently,
271 // The PeiCore is executed in flash.
272 //
273
274 //
275 // Rebase IDT table in permanent memory
276 //
277 AsmReadIdtr (&IdtDescriptor);
278 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
279
280 AsmWriteIdtr (&IdtDescriptor);
281
282 //
283 // Fixed the FSP data pointer
284 //
285 FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
286
287 //
288 // SecSwitchStack function must be invoked after the memory migration
289 // immediately, also we need fixup the stack change caused by new call into
290 // permanent memory.
291 //
292 SecSwitchStack (
293 (UINT32) (UINTN) OldStack,
294 (UINT32) (UINTN) NewStack
295 );
296
297 return EFI_SUCCESS;
298 }