]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/SecCore/SecMain.c
MdePkg/include: Update DMAR definitions to Intel VT-d spec ver4.0
[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
e93bc630
OI
170 DEBUG ((\r
171 DEBUG_INFO,\r
172 "%a() TempRAM Base: 0x%x, TempRAM Size: 0x%x, BootFirmwareVolume 0x%x\n",\r
173 __FUNCTION__,\r
174 TempRamBase,\r
175 SizeOfRam,\r
176 BootFirmwareVolume\r
177 ));\r
178\r
1921695e
MK
179 PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);\r
180 if (PeiStackSize == 0) {\r
181 PeiStackSize = (SizeOfRam >> 1);\r
182 }\r
183\r
184 ASSERT (PeiStackSize < SizeOfRam);\r
185\r
186 //\r
187 // Process all libraries constructor function linked to SecCore.\r
188 //\r
189 ProcessLibraryConstructorList ();\r
190\r
191 //\r
192 // Initialize floating point operating environment\r
193 // to be compliant with UEFI spec.\r
194 //\r
195 InitializeFloatingPointUnits ();\r
196\r
197 // |-------------------|---->\r
198 // |IDT Table |\r
199 // |-------------------|\r
200 // |PeiService Pointer | PeiStackSize\r
201 // |-------------------|\r
202 // | |\r
203 // | Stack |\r
204 // |-------------------|---->\r
205 // | |\r
206 // | |\r
207 // | Heap | PeiTemporayRamSize\r
208 // | |\r
209 // | |\r
210 // |-------------------|----> TempRamBase\r
211\r
212 IdtTableInStack.PeiService = 0;\r
053e878b
MK
213 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
214 CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&mIdtEntryTemplate, sizeof (UINT64));\r
1921695e
MK
215 }\r
216\r
053e878b 217 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
1921695e
MK
218 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
219\r
220 AsmWriteIdtr (&IdtDescriptor);\r
221\r
222 //\r
223 // Setup the default exception handlers\r
224 //\r
225 Status = InitializeCpuExceptionHandlers (NULL);\r
226 ASSERT_EFI_ERROR (Status);\r
227\r
228 //\r
229 // Update the base address and length of Pei temporary memory\r
230 //\r
053e878b 231 SecCoreData.DataSize = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF);\r
1921695e 232 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;\r
053e878b
MK
233 SecCoreData.BootFirmwareVolumeSize = (UINTN)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;\r
234 SecCoreData.TemporaryRamBase = (VOID *)(UINTN)TempRamBase;\r
1921695e
MK
235 SecCoreData.TemporaryRamSize = SizeOfRam;\r
236 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
237 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;\r
053e878b 238 SecCoreData.StackBase = (VOID *)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);\r
1921695e
MK
239 SecCoreData.StackSize = PeiStackSize;\r
240\r
e93bc630
OI
241 DEBUG ((\r
242 DEBUG_INFO,\r
243 "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n",\r
244 __FUNCTION__,\r
245 SecCoreData.BootFirmwareVolumeBase,\r
246 SecCoreData.BootFirmwareVolumeSize,\r
247 SecCoreData.TemporaryRamBase,\r
248 SecCoreData.TemporaryRamSize,\r
249 SecCoreData.PeiTemporaryRamBase,\r
250 SecCoreData.PeiTemporaryRamSize,\r
251 SecCoreData.StackBase,\r
252 SecCoreData.StackSize\r
253 ));\r
254\r
1921695e
MK
255 //\r
256 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
257 //\r
258 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
7cd8a575
MH
259\r
260 //\r
261 // Should not come here.\r
262 //\r
263 UNREACHABLE ();\r
1921695e
MK
264}\r
265\r
266/**\r
267 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
268\r
269 Entry point to the C language phase of SEC. After the SEC assembly\r
270 code has initialized some temporary memory and set up the stack,\r
271 the control is transferred to this function.\r
272\r
273 @param[in] Context The first input parameter of InitializeDebugAgent().\r
274\r
275**/\r
276VOID\r
61257251 277NORETURN\r
1921695e 278EFIAPI\r
053e878b
MK
279SecStartupPhase2 (\r
280 IN VOID *Context\r
1921695e
MK
281 )\r
282{\r
053e878b
MK
283 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
284 EFI_PEI_PPI_DESCRIPTOR *PpiList;\r
285 UINT32 Index;\r
286 EFI_PEI_PPI_DESCRIPTOR *AllSecPpiList;\r
287 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
1921695e 288\r
373c2c5b 289 PeiCoreEntryPoint = NULL;\r
053e878b 290 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;\r
373c2c5b 291\r
1b261a70
CC
292 //\r
293 // Perform platform specific initialization before entering PeiCore.\r
294 //\r
295 PpiList = SecPlatformMain (SecCoreData);\r
1921695e
MK
296 //\r
297 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug\r
298 // is enabled.\r
299 //\r
373c2c5b 300 if (PpiList != NULL) {\r
8a1305a1
CC
301 Index = 0;\r
302 do {\r
08283b96 303 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&\r
053e878b
MK
304 (((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation != 0)\r
305 )\r
306 {\r
08283b96
CC
307 //\r
308 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.\r
309 //\r
310 FindAndReportEntryPoints (\r
053e878b
MK
311 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
312 (EFI_FIRMWARE_VOLUME_HEADER *)((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation,\r
08283b96
CC
313 &PeiCoreEntryPoint\r
314 );\r
373c2c5b
CC
315 if (PeiCoreEntryPoint != NULL) {\r
316 break;\r
317 } else {\r
318 //\r
8a1305a1 319 // Invalid PeiCore FV provided by platform\r
373c2c5b
CC
320 //\r
321 CpuDeadLoop ();\r
322 }\r
323 }\r
8a1305a1 324 } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
373c2c5b 325 }\r
053e878b 326\r
373c2c5b
CC
327 //\r
328 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.\r
329 //\r
330 if (PeiCoreEntryPoint == NULL) {\r
08283b96
CC
331 //\r
332 // Both SecCore and PeiCore are in BFV.\r
333 //\r
334 FindAndReportEntryPoints (\r
053e878b
MK
335 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
336 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
08283b96
CC
337 &PeiCoreEntryPoint\r
338 );\r
373c2c5b
CC
339 if (PeiCoreEntryPoint == NULL) {\r
340 CpuDeadLoop ();\r
341 }\r
1921695e
MK
342 }\r
343\r
e93bc630
OI
344 DEBUG ((\r
345 DEBUG_INFO,\r
346 "%a() PeiCoreEntryPoint: 0x%x\n",\r
347 __FUNCTION__,\r
348 PeiCoreEntryPoint\r
349 ));\r
350\r
1921695e 351 if (PpiList != NULL) {\r
053e878b 352 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *)SecCoreData->PeiTemporaryRamBase;\r
47f167f4 353\r
1921695e
MK
354 //\r
355 // Remove the terminal flag from the terminal PPI\r
356 //\r
357 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));\r
053e878b 358 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;\r
1921695e
MK
359 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
360\r
361 //\r
362 // Append the platform additional PPI list\r
363 //\r
364 Index += 1;\r
365 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {\r
366 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
367 Index++;\r
368 PpiList++;\r
369 }\r
370\r
371 //\r
372 // Add the terminal PPI\r
373 //\r
053e878b 374 CopyMem (&AllSecPpiList[Index++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
1921695e
MK
375\r
376 //\r
377 // Set PpiList to the total PPI\r
378 //\r
379 PpiList = AllSecPpiList;\r
380\r
381 //\r
382 // Adjust PEI TEMP RAM Range.\r
383 //\r
384 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
053e878b 385 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
1921695e 386 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);\r
9e9ca210
SZ
387 //\r
388 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement\r
389 // will be built based on them in PEI phase.\r
390 //\r
053e878b 391 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);\r
59d3fad3 392 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;\r
e93bc630
OI
393 DEBUG ((\r
394 DEBUG_INFO,\r
395 "%a() PeiTemporaryRamBase: 0x%x, PeiTemporaryRamSize: 0x%x\n",\r
396 __FUNCTION__,\r
397 SecCoreData->PeiTemporaryRamBase,\r
398 SecCoreData->PeiTemporaryRamSize\r
399 ));\r
1921695e
MK
400 } else {\r
401 //\r
402 // No addition PPI, PpiList directly point to the common PPI list.\r
403 //\r
404 PpiList = &mPeiSecPlatformInformationPpi[0];\r
405 }\r
406\r
af34c106
JF
407 DEBUG ((\r
408 DEBUG_INFO,\r
ec16deea 409 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",\r
af34c106
JF
410 __FUNCTION__,\r
411 SecCoreData->StackBase,\r
053e878b 412 (UINT32)SecCoreData->StackSize\r
af34c106
JF
413 ));\r
414\r
1921695e
MK
415 //\r
416 // Report Status Code to indicate transferring to PEI core\r
417 //\r
418 REPORT_STATUS_CODE (\r
419 EFI_PROGRESS_CODE,\r
420 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT\r
421 );\r
422\r
423 //\r
424 // Transfer the control to the PEI core\r
425 //\r
426 ASSERT (PeiCoreEntryPoint != NULL);\r
053e878b 427 (*PeiCoreEntryPoint)(SecCoreData, PpiList);\r
1921695e
MK
428\r
429 //\r
430 // Should not come here.\r
431 //\r
61257251 432 UNREACHABLE ();\r
1921695e
MK
433}\r
434\r
435/**\r
436 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked\r
437 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.\r
438\r
439 @retval EFI_SUCCESS Use of Temporary RAM was disabled.\r
440 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.\r
441\r
442**/\r
443EFI_STATUS\r
444EFIAPI\r
445SecTemporaryRamDone (\r
446 VOID\r
447 )\r
448{\r
053e878b
MK
449 EFI_STATUS Status;\r
450 EFI_STATUS Status2;\r
451 UINTN Index;\r
452 BOOLEAN State;\r
453 EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;\r
454 REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;\r
1921695e 455\r
8a5b8cef
JF
456 //\r
457 // Republish Sec Platform Information(2) PPI\r
458 //\r
459 RepublishSecPlatformInformationPpi ();\r
460\r
479613bd
MK
461 //\r
462 // Re-install SEC PPIs using a PEIM produced service if published\r
463 //\r
464 for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {\r
465 Status = PeiServicesLocatePpi (\r
466 &gRepublishSecPpiPpiGuid,\r
467 Index,\r
468 &PeiPpiDescriptor,\r
053e878b 469 (VOID **)&RepublishSecPpiPpi\r
479613bd
MK
470 );\r
471 if (!EFI_ERROR (Status)) {\r
472 DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));\r
473 Status2 = RepublishSecPpiPpi->RepublishSecPpis ();\r
474 ASSERT_EFI_ERROR (Status2);\r
475 }\r
476 }\r
477\r
1921695e
MK
478 //\r
479 // Migrate DebugAgentContext.\r
480 //\r
481 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);\r
482\r
483 //\r
484 // Disable interrupts and save current interrupt state\r
485 //\r
479613bd 486 State = SaveAndDisableInterrupts ();\r
1921695e 487\r
f6ec1dd3
GJ
488 //\r
489 // Migrate GDT before NEM near down\r
490 //\r
491 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
492 Status = MigrateGdt ();\r
493 ASSERT_EFI_ERROR (Status);\r
494 }\r
495\r
1921695e
MK
496 //\r
497 // Disable Temporary RAM after Stack and Heap have been migrated at this point.\r
498 //\r
499 SecPlatformDisableTemporaryMemory ();\r
500\r
501 //\r
502 // Restore original interrupt state\r
503 //\r
504 SetInterruptState (State);\r
505\r
506 return EFI_SUCCESS;\r
507}\r