]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/SecCore/SecMain.c
UefiCpuPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiCpuPkg / SecCore / SecMain.c
CommitLineData
1921695e
MK
1/** @file\r
2 C functions in SEC\r
3\r
373c2c5b 4 Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1921695e
MK
6\r
7**/\r
8\r
9#include "SecMain.h"\r
10\r
053e878b 11EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi = {\r
1921695e
MK
12 SecTemporaryRamDone\r
13};\r
14\r
15EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };\r
16\r
053e878b 17EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {\r
f2e70629
SZ
18 {\r
19 //\r
20 // SecPerformance PPI notify descriptor.\r
21 //\r
22 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
23 &gPeiSecPerformancePpiGuid,\r
053e878b 24 (VOID *)(UINTN)SecPerformancePpiCallBack\r
f2e70629 25 },\r
1921695e
MK
26 {\r
27 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
28 &gEfiTemporaryRamDonePpiGuid,\r
29 &gSecTemporaryRamDonePpi\r
30 },\r
31 {\r
32 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
33 &gEfiSecPlatformInformationPpiGuid,\r
34 &mSecPlatformInformationPpi\r
35 }\r
36};\r
37\r
f6ec1dd3
GJ
38/**\r
39 Migrates the Global Descriptor Table (GDT) to permanent memory.\r
40\r
41 @retval EFI_SUCCESS The GDT was migrated successfully.\r
42 @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.\r
43\r
44**/\r
45EFI_STATUS\r
46MigrateGdt (\r
47 VOID\r
48 )\r
49{\r
053e878b
MK
50 EFI_STATUS Status;\r
51 UINTN GdtBufferSize;\r
52 IA32_DESCRIPTOR Gdtr;\r
53 VOID *GdtBuffer;\r
f6ec1dd3 54\r
053e878b 55 AsmReadGdtr ((IA32_DESCRIPTOR *)&Gdtr);\r
f6ec1dd3
GJ
56 GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1;\r
57\r
58 Status = PeiServicesAllocatePool (\r
59 GdtBufferSize,\r
60 &GdtBuffer\r
61 );\r
62 ASSERT (GdtBuffer != NULL);\r
63 if (EFI_ERROR (Status)) {\r
64 return EFI_OUT_OF_RESOURCES;\r
65 }\r
66\r
67 GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR));\r
053e878b
MK
68 CopyMem (GdtBuffer, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
69 Gdtr.Base = (UINTN)GdtBuffer;\r
f6ec1dd3
GJ
70 AsmWriteGdtr (&Gdtr);\r
71\r
72 return EFI_SUCCESS;\r
73}\r
74\r
1921695e
MK
75//\r
76// These are IDT entries pointing to 10:FFFFFFE4h.\r
77//\r
78UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;\r
79\r
80/**\r
81 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
82\r
83 Entry point to the C language phase of SEC. After the SEC assembly\r
84 code has initialized some temporary memory and set up the stack,\r
85 the control is transferred to this function.\r
86\r
87 @param[in] Context The first input parameter of InitializeDebugAgent().\r
88\r
89**/\r
90VOID\r
61257251 91NORETURN\r
1921695e 92EFIAPI\r
053e878b
MK
93SecStartupPhase2 (\r
94 IN VOID *Context\r
1921695e
MK
95 );\r
96\r
f2e70629
SZ
97/**\r
98 Entry point of the notification callback function itself within the PEIM.\r
99 It is to get SEC performance data and build HOB to convey the SEC performance\r
100 data to DXE phase.\r
101\r
102 @param PeiServices Indirect reference to the PEI Services Table.\r
103 @param NotifyDescriptor Address of the notification descriptor data structure.\r
104 @param Ppi Address of the PPI that was installed.\r
105\r
106 @return Status of the notification.\r
107 The status code returned from this function is ignored.\r
108**/\r
109EFI_STATUS\r
110EFIAPI\r
111SecPerformancePpiCallBack (\r
112 IN EFI_PEI_SERVICES **PeiServices,\r
113 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
114 IN VOID *Ppi\r
115 )\r
116{\r
053e878b
MK
117 EFI_STATUS Status;\r
118 PEI_SEC_PERFORMANCE_PPI *SecPerf;\r
119 FIRMWARE_SEC_PERFORMANCE Performance;\r
f2e70629 120\r
053e878b
MK
121 SecPerf = (PEI_SEC_PERFORMANCE_PPI *)Ppi;\r
122 Status = SecPerf->GetPerformance ((CONST EFI_PEI_SERVICES **)PeiServices, SecPerf, &Performance);\r
f2e70629
SZ
123 if (!EFI_ERROR (Status)) {\r
124 BuildGuidDataHob (\r
125 &gEfiFirmwarePerformanceGuid,\r
126 &Performance,\r
127 sizeof (FIRMWARE_SEC_PERFORMANCE)\r
053e878b 128 );\r
f2e70629
SZ
129 DEBUG ((DEBUG_INFO, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance.ResetEnd));\r
130 }\r
131\r
132 return Status;\r
133}\r
134\r
1921695e
MK
135/**\r
136\r
137 Entry point to the C language phase of SEC. After the SEC assembly\r
138 code has initialized some temporary memory and set up the stack,\r
139 the control is transferred to this function.\r
140\r
141\r
142 @param SizeOfRam Size of the temporary memory available for use.\r
143 @param TempRamBase Base address of temporary ram\r
144 @param BootFirmwareVolume Base address of the Boot Firmware Volume.\r
145**/\r
146VOID\r
7cd8a575 147NORETURN\r
1921695e
MK
148EFIAPI\r
149SecStartup (\r
053e878b
MK
150 IN UINT32 SizeOfRam,\r
151 IN UINT32 TempRamBase,\r
152 IN VOID *BootFirmwareVolume\r
1921695e
MK
153 )\r
154{\r
053e878b
MK
155 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
156 IA32_DESCRIPTOR IdtDescriptor;\r
157 SEC_IDT_TABLE IdtTableInStack;\r
158 UINT32 Index;\r
159 UINT32 PeiStackSize;\r
160 EFI_STATUS Status;\r
1921695e
MK
161\r
162 //\r
163 // Report Status Code to indicate entering SEC core\r
164 //\r
165 REPORT_STATUS_CODE (\r
166 EFI_PROGRESS_CODE,\r
167 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT\r
168 );\r
169\r
170 PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);\r
171 if (PeiStackSize == 0) {\r
172 PeiStackSize = (SizeOfRam >> 1);\r
173 }\r
174\r
175 ASSERT (PeiStackSize < SizeOfRam);\r
176\r
177 //\r
178 // Process all libraries constructor function linked to SecCore.\r
179 //\r
180 ProcessLibraryConstructorList ();\r
181\r
182 //\r
183 // Initialize floating point operating environment\r
184 // to be compliant with UEFI spec.\r
185 //\r
186 InitializeFloatingPointUnits ();\r
187\r
188 // |-------------------|---->\r
189 // |IDT Table |\r
190 // |-------------------|\r
191 // |PeiService Pointer | PeiStackSize\r
192 // |-------------------|\r
193 // | |\r
194 // | Stack |\r
195 // |-------------------|---->\r
196 // | |\r
197 // | |\r
198 // | Heap | PeiTemporayRamSize\r
199 // | |\r
200 // | |\r
201 // |-------------------|----> TempRamBase\r
202\r
203 IdtTableInStack.PeiService = 0;\r
053e878b
MK
204 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
205 CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&mIdtEntryTemplate, sizeof (UINT64));\r
1921695e
MK
206 }\r
207\r
053e878b 208 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
1921695e
MK
209 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
210\r
211 AsmWriteIdtr (&IdtDescriptor);\r
212\r
213 //\r
214 // Setup the default exception handlers\r
215 //\r
216 Status = InitializeCpuExceptionHandlers (NULL);\r
217 ASSERT_EFI_ERROR (Status);\r
218\r
219 //\r
220 // Update the base address and length of Pei temporary memory\r
221 //\r
053e878b 222 SecCoreData.DataSize = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF);\r
1921695e 223 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;\r
053e878b
MK
224 SecCoreData.BootFirmwareVolumeSize = (UINTN)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;\r
225 SecCoreData.TemporaryRamBase = (VOID *)(UINTN)TempRamBase;\r
1921695e
MK
226 SecCoreData.TemporaryRamSize = SizeOfRam;\r
227 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
228 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;\r
053e878b 229 SecCoreData.StackBase = (VOID *)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);\r
1921695e
MK
230 SecCoreData.StackSize = PeiStackSize;\r
231\r
232 //\r
233 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
234 //\r
235 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
7cd8a575
MH
236\r
237 //\r
238 // Should not come here.\r
239 //\r
240 UNREACHABLE ();\r
1921695e
MK
241}\r
242\r
243/**\r
244 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
245\r
246 Entry point to the C language phase of SEC. After the SEC assembly\r
247 code has initialized some temporary memory and set up the stack,\r
248 the control is transferred to this function.\r
249\r
250 @param[in] Context The first input parameter of InitializeDebugAgent().\r
251\r
252**/\r
253VOID\r
61257251 254NORETURN\r
1921695e 255EFIAPI\r
053e878b
MK
256SecStartupPhase2 (\r
257 IN VOID *Context\r
1921695e
MK
258 )\r
259{\r
053e878b
MK
260 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
261 EFI_PEI_PPI_DESCRIPTOR *PpiList;\r
262 UINT32 Index;\r
263 EFI_PEI_PPI_DESCRIPTOR *AllSecPpiList;\r
264 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
1921695e 265\r
373c2c5b 266 PeiCoreEntryPoint = NULL;\r
053e878b 267 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;\r
373c2c5b 268\r
1b261a70
CC
269 //\r
270 // Perform platform specific initialization before entering PeiCore.\r
271 //\r
272 PpiList = SecPlatformMain (SecCoreData);\r
1921695e
MK
273 //\r
274 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug\r
275 // is enabled.\r
276 //\r
373c2c5b 277 if (PpiList != NULL) {\r
8a1305a1
CC
278 Index = 0;\r
279 do {\r
08283b96 280 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&\r
053e878b
MK
281 (((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation != 0)\r
282 )\r
283 {\r
08283b96
CC
284 //\r
285 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.\r
286 //\r
287 FindAndReportEntryPoints (\r
053e878b
MK
288 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
289 (EFI_FIRMWARE_VOLUME_HEADER *)((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation,\r
08283b96
CC
290 &PeiCoreEntryPoint\r
291 );\r
373c2c5b
CC
292 if (PeiCoreEntryPoint != NULL) {\r
293 break;\r
294 } else {\r
295 //\r
8a1305a1 296 // Invalid PeiCore FV provided by platform\r
373c2c5b
CC
297 //\r
298 CpuDeadLoop ();\r
299 }\r
300 }\r
8a1305a1 301 } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
373c2c5b 302 }\r
053e878b 303\r
373c2c5b
CC
304 //\r
305 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.\r
306 //\r
307 if (PeiCoreEntryPoint == NULL) {\r
08283b96
CC
308 //\r
309 // Both SecCore and PeiCore are in BFV.\r
310 //\r
311 FindAndReportEntryPoints (\r
053e878b
MK
312 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
313 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
08283b96
CC
314 &PeiCoreEntryPoint\r
315 );\r
373c2c5b
CC
316 if (PeiCoreEntryPoint == NULL) {\r
317 CpuDeadLoop ();\r
318 }\r
1921695e
MK
319 }\r
320\r
1921695e 321 if (PpiList != NULL) {\r
053e878b 322 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *)SecCoreData->PeiTemporaryRamBase;\r
47f167f4 323\r
1921695e
MK
324 //\r
325 // Remove the terminal flag from the terminal PPI\r
326 //\r
327 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));\r
053e878b 328 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;\r
1921695e
MK
329 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
330\r
331 //\r
332 // Append the platform additional PPI list\r
333 //\r
334 Index += 1;\r
335 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {\r
336 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
337 Index++;\r
338 PpiList++;\r
339 }\r
340\r
341 //\r
342 // Add the terminal PPI\r
343 //\r
053e878b 344 CopyMem (&AllSecPpiList[Index++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
1921695e
MK
345\r
346 //\r
347 // Set PpiList to the total PPI\r
348 //\r
349 PpiList = AllSecPpiList;\r
350\r
351 //\r
352 // Adjust PEI TEMP RAM Range.\r
353 //\r
354 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
053e878b 355 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
1921695e 356 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);\r
9e9ca210
SZ
357 //\r
358 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement\r
359 // will be built based on them in PEI phase.\r
360 //\r
053e878b 361 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);\r
59d3fad3 362 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;\r
1921695e
MK
363 } else {\r
364 //\r
365 // No addition PPI, PpiList directly point to the common PPI list.\r
366 //\r
367 PpiList = &mPeiSecPlatformInformationPpi[0];\r
368 }\r
369\r
af34c106
JF
370 DEBUG ((\r
371 DEBUG_INFO,\r
ec16deea 372 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",\r
af34c106
JF
373 __FUNCTION__,\r
374 SecCoreData->StackBase,\r
053e878b 375 (UINT32)SecCoreData->StackSize\r
af34c106
JF
376 ));\r
377\r
1921695e
MK
378 //\r
379 // Report Status Code to indicate transferring to PEI core\r
380 //\r
381 REPORT_STATUS_CODE (\r
382 EFI_PROGRESS_CODE,\r
383 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT\r
384 );\r
385\r
386 //\r
387 // Transfer the control to the PEI core\r
388 //\r
389 ASSERT (PeiCoreEntryPoint != NULL);\r
053e878b 390 (*PeiCoreEntryPoint)(SecCoreData, PpiList);\r
1921695e
MK
391\r
392 //\r
393 // Should not come here.\r
394 //\r
61257251 395 UNREACHABLE ();\r
1921695e
MK
396}\r
397\r
398/**\r
399 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked\r
400 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.\r
401\r
402 @retval EFI_SUCCESS Use of Temporary RAM was disabled.\r
403 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.\r
404\r
405**/\r
406EFI_STATUS\r
407EFIAPI\r
408SecTemporaryRamDone (\r
409 VOID\r
410 )\r
411{\r
053e878b
MK
412 EFI_STATUS Status;\r
413 EFI_STATUS Status2;\r
414 UINTN Index;\r
415 BOOLEAN State;\r
416 EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;\r
417 REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;\r
1921695e 418\r
8a5b8cef
JF
419 //\r
420 // Republish Sec Platform Information(2) PPI\r
421 //\r
422 RepublishSecPlatformInformationPpi ();\r
423\r
479613bd
MK
424 //\r
425 // Re-install SEC PPIs using a PEIM produced service if published\r
426 //\r
427 for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {\r
428 Status = PeiServicesLocatePpi (\r
429 &gRepublishSecPpiPpiGuid,\r
430 Index,\r
431 &PeiPpiDescriptor,\r
053e878b 432 (VOID **)&RepublishSecPpiPpi\r
479613bd
MK
433 );\r
434 if (!EFI_ERROR (Status)) {\r
435 DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));\r
436 Status2 = RepublishSecPpiPpi->RepublishSecPpis ();\r
437 ASSERT_EFI_ERROR (Status2);\r
438 }\r
439 }\r
440\r
1921695e
MK
441 //\r
442 // Migrate DebugAgentContext.\r
443 //\r
444 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);\r
445\r
446 //\r
447 // Disable interrupts and save current interrupt state\r
448 //\r
479613bd 449 State = SaveAndDisableInterrupts ();\r
1921695e 450\r
f6ec1dd3
GJ
451 //\r
452 // Migrate GDT before NEM near down\r
453 //\r
454 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
455 Status = MigrateGdt ();\r
456 ASSERT_EFI_ERROR (Status);\r
457 }\r
458\r
1921695e
MK
459 //\r
460 // Disable Temporary RAM after Stack and Heap have been migrated at this point.\r
461 //\r
462 SecPlatformDisableTemporaryMemory ();\r
463\r
464 //\r
465 // Restore original interrupt state\r
466 //\r
467 SetInterruptState (State);\r
468\r
469 return EFI_SUCCESS;\r
470}\r