]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UefiCpuPkg/SecCore/SecMain.c
UefiCpuPkg/SecCore: Add debug messages to illuminate data flow
[mirror_edk2.git] / UefiCpuPkg / SecCore / SecMain.c
... / ...
CommitLineData
1/** @file\r
2 C functions in SEC\r
3\r
4 Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "SecMain.h"\r
10\r
11EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi = {\r
12 SecTemporaryRamDone\r
13};\r
14\r
15EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };\r
16\r
17EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {\r
18 {\r
19 //\r
20 // SecPerformance PPI notify descriptor.\r
21 //\r
22 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,\r
23 &gPeiSecPerformancePpiGuid,\r
24 (VOID *)(UINTN)SecPerformancePpiCallBack\r
25 },\r
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
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
50 EFI_STATUS Status;\r
51 UINTN GdtBufferSize;\r
52 IA32_DESCRIPTOR Gdtr;\r
53 VOID *GdtBuffer;\r
54\r
55 AsmReadGdtr ((IA32_DESCRIPTOR *)&Gdtr);\r
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
68 CopyMem (GdtBuffer, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
69 Gdtr.Base = (UINTN)GdtBuffer;\r
70 AsmWriteGdtr (&Gdtr);\r
71\r
72 return EFI_SUCCESS;\r
73}\r
74\r
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
91NORETURN\r
92EFIAPI\r
93SecStartupPhase2 (\r
94 IN VOID *Context\r
95 );\r
96\r
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
117 EFI_STATUS Status;\r
118 PEI_SEC_PERFORMANCE_PPI *SecPerf;\r
119 FIRMWARE_SEC_PERFORMANCE Performance;\r
120\r
121 SecPerf = (PEI_SEC_PERFORMANCE_PPI *)Ppi;\r
122 Status = SecPerf->GetPerformance ((CONST EFI_PEI_SERVICES **)PeiServices, SecPerf, &Performance);\r
123 if (!EFI_ERROR (Status)) {\r
124 BuildGuidDataHob (\r
125 &gEfiFirmwarePerformanceGuid,\r
126 &Performance,\r
127 sizeof (FIRMWARE_SEC_PERFORMANCE)\r
128 );\r
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
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
147NORETURN\r
148EFIAPI\r
149SecStartup (\r
150 IN UINT32 SizeOfRam,\r
151 IN UINT32 TempRamBase,\r
152 IN VOID *BootFirmwareVolume\r
153 )\r
154{\r
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
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 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
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
213 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
214 CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&mIdtEntryTemplate, sizeof (UINT64));\r
215 }\r
216\r
217 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
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
231 SecCoreData.DataSize = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF);\r
232 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;\r
233 SecCoreData.BootFirmwareVolumeSize = (UINTN)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;\r
234 SecCoreData.TemporaryRamBase = (VOID *)(UINTN)TempRamBase;\r
235 SecCoreData.TemporaryRamSize = SizeOfRam;\r
236 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
237 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;\r
238 SecCoreData.StackBase = (VOID *)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);\r
239 SecCoreData.StackSize = PeiStackSize;\r
240\r
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
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
259\r
260 //\r
261 // Should not come here.\r
262 //\r
263 UNREACHABLE ();\r
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
277NORETURN\r
278EFIAPI\r
279SecStartupPhase2 (\r
280 IN VOID *Context\r
281 )\r
282{\r
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
288\r
289 PeiCoreEntryPoint = NULL;\r
290 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;\r
291\r
292 //\r
293 // Perform platform specific initialization before entering PeiCore.\r
294 //\r
295 PpiList = SecPlatformMain (SecCoreData);\r
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
300 if (PpiList != NULL) {\r
301 Index = 0;\r
302 do {\r
303 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&\r
304 (((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation != 0)\r
305 )\r
306 {\r
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
311 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
312 (EFI_FIRMWARE_VOLUME_HEADER *)((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation,\r
313 &PeiCoreEntryPoint\r
314 );\r
315 if (PeiCoreEntryPoint != NULL) {\r
316 break;\r
317 } else {\r
318 //\r
319 // Invalid PeiCore FV provided by platform\r
320 //\r
321 CpuDeadLoop ();\r
322 }\r
323 }\r
324 } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
325 }\r
326\r
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
331 //\r
332 // Both SecCore and PeiCore are in BFV.\r
333 //\r
334 FindAndReportEntryPoints (\r
335 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
336 (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,\r
337 &PeiCoreEntryPoint\r
338 );\r
339 if (PeiCoreEntryPoint == NULL) {\r
340 CpuDeadLoop ();\r
341 }\r
342 }\r
343\r
344 DEBUG ((\r
345 DEBUG_INFO,\r
346 "%a() PeiCoreEntryPoint: 0x%x\n",\r
347 __FUNCTION__,\r
348 PeiCoreEntryPoint\r
349 ));\r
350\r
351 if (PpiList != NULL) {\r
352 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *)SecCoreData->PeiTemporaryRamBase;\r
353\r
354 //\r
355 // Remove the terminal flag from the terminal PPI\r
356 //\r
357 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));\r
358 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;\r
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
374 CopyMem (&AllSecPpiList[Index++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
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
385 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
386 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);\r
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
391 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);\r
392 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;\r
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
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
407 DEBUG ((\r
408 DEBUG_INFO,\r
409 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",\r
410 __FUNCTION__,\r
411 SecCoreData->StackBase,\r
412 (UINT32)SecCoreData->StackSize\r
413 ));\r
414\r
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
427 (*PeiCoreEntryPoint)(SecCoreData, PpiList);\r
428\r
429 //\r
430 // Should not come here.\r
431 //\r
432 UNREACHABLE ();\r
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
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
455\r
456 //\r
457 // Republish Sec Platform Information(2) PPI\r
458 //\r
459 RepublishSecPlatformInformationPpi ();\r
460\r
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
469 (VOID **)&RepublishSecPpiPpi\r
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
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
486 State = SaveAndDisableInterrupts ();\r
487\r
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
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