]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/SecMain.c
cd3ab46ce2401c291d5d9c964986e68153e2d24f
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / SecMain.c
1 /** @file
2
3 Copyright (c) 2014 - 2019, 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 | PeiTemporayRamSize
114 // | |
115 // | |
116 // |-------------------|----> TempRamBase
117 IdtTableInStack.PeiService = NULL;
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 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
225
226 CurrentStack = AsmReadEsp();
227 FspStackBase = (UINTN)GetFspEntryStack();
228
229 StackSize = FspStackBase - CurrentStack;
230 HeapSize = CopySize;
231
232 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
233 NewHeap = (VOID*)((UINTN)PermanentMemoryBase);
234
235 OldStack = (VOID*)CurrentStack;
236 //
237 //The old stack is copied at the end of the stack region because stack grows down.
238 //
239 NewStack = (VOID*)((UINTN)PermanentMemoryBase - StackSize);
240
241 } else {
242 HeapSize = CopySize * PcdGet8 (PcdFspHeapSizePercentage) / 100 ;
243 StackSize = CopySize - HeapSize;
244
245 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
246 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + StackSize);
247
248 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
249 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
250
251 }
252 //
253 // Migrate Heap
254 //
255 CopyMem (NewHeap, OldHeap, HeapSize);
256
257 //
258 // Migrate Stack
259 //
260 CopyMem (NewStack, OldStack, StackSize);
261
262
263 //
264 // We need *not* fix the return address because currently,
265 // The PeiCore is executed in flash.
266 //
267
268 //
269 // Rebase IDT table in permanent memory
270 //
271 AsmReadIdtr (&IdtDescriptor);
272 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
273
274 AsmWriteIdtr (&IdtDescriptor);
275
276 //
277 // Fixed the FSP data pointer
278 //
279 FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
280
281 //
282 // SecSwitchStack function must be invoked after the memory migration
283 // immediately, also we need fixup the stack change caused by new call into
284 // permanent memory.
285 //
286 SecSwitchStack (
287 (UINT32) (UINTN) OldStack,
288 (UINT32) (UINTN) NewStack
289 );
290
291 return EFI_SUCCESS;
292 }