]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/SecMain.c
540571187af171648272ffc49b11444b506cf7f6
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / SecMain.c
1 /** @file
2
3 Copyright (c) 2014 - 2021, 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 //
154 // Support FSP reserved temporary memory from the whole temporary memory provided by bootloader.
155 // FSP reserved temporary memory will not be given to PeiCore.
156 //
157 SecCoreData.TemporaryRamBase = (UINT8 *)(UINTN) TempRamBase + PcdGet32 (PcdFspPrivateTemporaryRamSize);
158 SecCoreData.TemporaryRamSize = SizeOfRam - PcdGet32 (PcdFspPrivateTemporaryRamSize);
159 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
160 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
161 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize;
162 SecCoreData.StackBase = (VOID *)GetFspEntryStack(); // Share the same boot loader stack
163 SecCoreData.StackSize = 0;
164 } else {
165 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
166 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
167 SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
168 SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize;
169 }
170
171 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
172 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
173 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase));
174 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize));
175 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
176 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
177 DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase));
178 DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize));
179
180 //
181 // Call PeiCore Entry
182 //
183 PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
184
185 //
186 // Should never be here
187 //
188 CpuDeadLoop ();
189 }
190
191 /**
192 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
193 permanent memory.
194
195 @param[in] PeiServices Pointer to the PEI Services Table.
196 @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
197 Temporary RAM contents.
198 @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
199 Temporary RAM contents.
200 @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
201
202 @retval EFI_SUCCESS The data was successfully returned.
203 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
204 TemporaryMemoryBase > PermanentMemoryBase.
205
206 **/
207 EFI_STATUS
208 EFIAPI
209 SecTemporaryRamSupport (
210 IN CONST EFI_PEI_SERVICES **PeiServices,
211 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
212 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
213 IN UINTN CopySize
214 )
215 {
216 IA32_DESCRIPTOR IdtDescriptor;
217 VOID* OldHeap;
218 VOID* NewHeap;
219 VOID* OldStack;
220 VOID* NewStack;
221 UINTN HeapSize;
222 UINTN StackSize;
223
224 UINTN CurrentStack;
225 UINTN FspStackBase;
226
227 //
228 // Override OnSeparateStack to 1 because this function will switch stack to permanent memory
229 // which makes FSP running on different stack from bootloader temporary ram stack.
230 //
231 GetFspGlobalDataPointer ()->OnSeparateStack = 1;
232
233 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
234
235 CurrentStack = AsmReadEsp();
236 FspStackBase = (UINTN)GetFspEntryStack();
237
238 StackSize = FspStackBase - CurrentStack;
239 HeapSize = CopySize;
240
241 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
242 NewHeap = (VOID*)((UINTN)PermanentMemoryBase);
243
244 OldStack = (VOID*)CurrentStack;
245 //
246 //The old stack is copied at the end of the stack region because stack grows down.
247 //
248 NewStack = (VOID*)((UINTN)PermanentMemoryBase - StackSize);
249
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 //
273 // We need *not* fix the return address because currently,
274 // The PeiCore is executed in flash.
275 //
276
277 //
278 // Rebase IDT table in permanent memory
279 //
280 AsmReadIdtr (&IdtDescriptor);
281 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
282
283 AsmWriteIdtr (&IdtDescriptor);
284
285 //
286 // Fixed the FSP data pointer
287 //
288 FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
289
290 //
291 // SecSwitchStack function must be invoked after the memory migration
292 // immediately, also we need fixup the stack change caused by new call into
293 // permanent memory.
294 //
295 SecSwitchStack (
296 (UINT32) (UINTN) OldStack,
297 (UINT32) (UINTN) NewStack
298 );
299
300 return EFI_SUCCESS;
301 }