]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/SecMain.c
c7caa3e7f927d23fb0284eaad0c2c6a501d30e75
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / SecMain.c
1 /** @file
2
3 Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #include "SecMain.h"
15 #include "SecFsp.h"
16
17 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
18 SecTemporaryRamSupport
19 };
20
21 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
22 {
23 EFI_PEI_PPI_DESCRIPTOR_PPI,
24 &gFspInApiModePpiGuid,
25 NULL
26 },
27 {
28 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
29 &gEfiTemporaryRamSupportPpiGuid,
30 &gSecTemporaryRamSupportPpi
31 }
32 };
33
34 //
35 // These are IDT entries pointing to 08:FFFFFFE4h.
36 //
37 UINT64 mIdtEntryTemplate = 0xffff8e000008ffe4ULL;
38
39 /**
40
41 Entry point to the C language phase of SEC. After the SEC assembly
42 code has initialized some temporary memory and set up the stack,
43 the control is transferred to this function.
44
45
46 @param[in] SizeOfRam Size of the temporary memory available for use.
47 @param[in] TempRamBase Base address of temporary ram
48 @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
49 @param[in] PeiCore PeiCore entry point.
50 @param[in] BootLoaderStack BootLoader stack.
51 @param[in] ApiIdx the index of API.
52
53 @return This function never returns.
54
55 **/
56 VOID
57 EFIAPI
58 SecStartup (
59 IN UINT32 SizeOfRam,
60 IN UINT32 TempRamBase,
61 IN VOID *BootFirmwareVolume,
62 IN PEI_CORE_ENTRY PeiCore,
63 IN UINT32 BootLoaderStack,
64 IN UINT32 ApiIdx
65 )
66 {
67 EFI_SEC_PEI_HAND_OFF SecCoreData;
68 IA32_DESCRIPTOR IdtDescriptor;
69 SEC_IDT_TABLE IdtTableInStack;
70 UINT32 Index;
71 FSP_GLOBAL_DATA PeiFspData;
72 UINT64 ExceptionHandler;
73 UINTN IdtSize;
74
75 //
76 // Process all libraries constructor function linked to SecCore.
77 //
78 ProcessLibraryConstructorList ();
79
80 //
81 // Initialize floating point operating environment
82 // to be compliant with UEFI spec.
83 //
84 InitializeFloatingPointUnits ();
85
86 //
87 // Scenario 1 memory map when running on bootloader stack
88 //
89 // |-------------------|---->
90 // |Idt Table |
91 // |-------------------|
92 // |PeiService Pointer |
93 // |-------------------|
94 // | |
95 // | |
96 // | Heap |
97 // | |
98 // | |
99 // |-------------------|----> TempRamBase
100 //
101 //
102 // |-------------------|
103 // |Bootloader stack |----> somewhere in memory, FSP will share this stack.
104 // |-------------------|
105
106 //
107 // Scenario 2 memory map when running FSP on a separate stack
108 //
109 // |-------------------|---->
110 // |Idt Table |
111 // |-------------------|
112 // |PeiService Pointer | PeiStackSize
113 // |-------------------|
114 // | |
115 // | Stack |
116 // |-------------------|---->
117 // | |
118 // | |
119 // | Heap | PeiTemporayRamSize
120 // | |
121 // | |
122 // |-------------------|----> TempRamBase
123 IdtTableInStack.PeiService = NULL;
124 AsmReadIdtr (&IdtDescriptor);
125 if (IdtDescriptor.Base == 0) {
126 ExceptionHandler = FspGetExceptionHandler(mIdtEntryTemplate);
127 for (Index = 0; Index < FixedPcdGet8(PcdFspMaxInterruptSupported); Index ++) {
128 CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&ExceptionHandler, sizeof (UINT64));
129 }
130 IdtSize = sizeof (IdtTableInStack.IdtTable);
131 } else {
132 IdtSize = IdtDescriptor.Limit + 1;
133 if (IdtSize > sizeof (IdtTableInStack.IdtTable)) {
134 //
135 // ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
136 //
137 CpuDeadLoop();
138 } else {
139 CopyMem ((VOID *) (UINTN) &IdtTableInStack.IdtTable, (VOID *) IdtDescriptor.Base, IdtSize);
140 }
141 }
142 IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
143 IdtDescriptor.Limit = (UINT16)(IdtSize - 1);
144
145 AsmWriteIdtr (&IdtDescriptor);
146
147 //
148 // Initialize the global FSP data region
149 //
150 FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx);
151
152 //
153 // Update the base address and length of Pei temporary memory
154 //
155 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
156 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
157 SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
158
159 SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
160 if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
161 SecCoreData.TemporaryRamSize = SizeOfRam; // stack size that is going to be copied to the permanent memory
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.TemporaryRamSize = SizeOfRam;
168 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
169 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
170 SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
171 SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize;
172 }
173
174 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
175 DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
176 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase));
177 DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize));
178 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
179 DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
180 DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase));
181 DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize));
182
183 //
184 // Call PeiCore Entry
185 //
186 PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
187
188 //
189 // Should never be here
190 //
191 CpuDeadLoop ();
192 }
193
194 /**
195 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
196 permanent memory.
197
198 @param[in] PeiServices Pointer to the PEI Services Table.
199 @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
200 Temporary RAM contents.
201 @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
202 Temporary RAM contents.
203 @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
204
205 @retval EFI_SUCCESS The data was successfully returned.
206 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
207 TemporaryMemoryBase > PermanentMemoryBase.
208
209 **/
210 EFI_STATUS
211 EFIAPI
212 SecTemporaryRamSupport (
213 IN CONST EFI_PEI_SERVICES **PeiServices,
214 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
215 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
216 IN UINTN CopySize
217 )
218 {
219 IA32_DESCRIPTOR IdtDescriptor;
220 VOID* OldHeap;
221 VOID* NewHeap;
222 VOID* OldStack;
223 VOID* NewStack;
224 UINTN HeapSize;
225 UINTN StackSize;
226
227 UINTN CurrentStack;
228 UINTN FspStackBase;
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 }