]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/SecCore/SecMain.c
UefiCpuPkg: Move MigrateGdt from DiscoverMemory to TempRamDone. (CVE-2019-11098)
[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
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
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
24 (VOID *) (UINTN) SecPerformancePpiCallBack\r
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
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
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
MK
92EFIAPI\r
93SecStartupPhase2(\r
94 IN VOID *Context\r
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
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
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
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 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
204 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
205 CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));\r
206 }\r
207\r
208 IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;\r
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
222 SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);\r
223 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;\r
f0162959 224 SecCoreData.BootFirmwareVolumeSize = (UINTN)((EFI_FIRMWARE_VOLUME_HEADER *) BootFirmwareVolume)->FvLength;\r
1921695e
MK
225 SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;\r
226 SecCoreData.TemporaryRamSize = SizeOfRam;\r
227 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
228 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;\r
229 SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);\r
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
MK
255EFIAPI\r
256SecStartupPhase2(\r
257 IN VOID *Context\r
258 )\r
259{\r
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
265\r
373c2c5b 266 PeiCoreEntryPoint = NULL;\r
1921695e 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
CC
280 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&\r
281 (((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation != 0)\r
282 ) {\r
283 //\r
284 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.\r
285 //\r
286 FindAndReportEntryPoints (\r
287 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,\r
288 (EFI_FIRMWARE_VOLUME_HEADER *) ((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation,\r
289 &PeiCoreEntryPoint\r
290 );\r
373c2c5b
CC
291 if (PeiCoreEntryPoint != NULL) {\r
292 break;\r
293 } else {\r
294 //\r
8a1305a1 295 // Invalid PeiCore FV provided by platform\r
373c2c5b
CC
296 //\r
297 CpuDeadLoop ();\r
298 }\r
299 }\r
8a1305a1 300 } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
373c2c5b
CC
301 }\r
302 //\r
303 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.\r
304 //\r
305 if (PeiCoreEntryPoint == NULL) {\r
08283b96
CC
306 //\r
307 // Both SecCore and PeiCore are in BFV.\r
308 //\r
309 FindAndReportEntryPoints (\r
310 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,\r
311 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,\r
312 &PeiCoreEntryPoint\r
313 );\r
373c2c5b
CC
314 if (PeiCoreEntryPoint == NULL) {\r
315 CpuDeadLoop ();\r
316 }\r
1921695e
MK
317 }\r
318\r
1921695e 319 if (PpiList != NULL) {\r
47f167f4
ED
320 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *) SecCoreData->PeiTemporaryRamBase;\r
321\r
1921695e
MK
322 //\r
323 // Remove the terminal flag from the terminal PPI\r
324 //\r
325 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));\r
326 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;\r
327 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
328\r
329 //\r
330 // Append the platform additional PPI list\r
331 //\r
332 Index += 1;\r
333 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {\r
334 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
335 Index++;\r
336 PpiList++;\r
337 }\r
338\r
339 //\r
340 // Add the terminal PPI\r
341 //\r
342 CopyMem (&AllSecPpiList[Index ++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
343\r
344 //\r
345 // Set PpiList to the total PPI\r
346 //\r
347 PpiList = AllSecPpiList;\r
348\r
349 //\r
350 // Adjust PEI TEMP RAM Range.\r
351 //\r
352 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
353 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
354 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);\r
9e9ca210
SZ
355 //\r
356 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement\r
357 // will be built based on them in PEI phase.\r
358 //\r
359 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);\r
59d3fad3 360 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;\r
1921695e
MK
361 } else {\r
362 //\r
363 // No addition PPI, PpiList directly point to the common PPI list.\r
364 //\r
365 PpiList = &mPeiSecPlatformInformationPpi[0];\r
366 }\r
367\r
af34c106
JF
368 DEBUG ((\r
369 DEBUG_INFO,\r
ec16deea 370 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",\r
af34c106
JF
371 __FUNCTION__,\r
372 SecCoreData->StackBase,\r
ec16deea 373 (UINT32) SecCoreData->StackSize\r
af34c106
JF
374 ));\r
375\r
1921695e
MK
376 //\r
377 // Report Status Code to indicate transferring to PEI core\r
378 //\r
379 REPORT_STATUS_CODE (\r
380 EFI_PROGRESS_CODE,\r
381 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT\r
382 );\r
383\r
384 //\r
385 // Transfer the control to the PEI core\r
386 //\r
387 ASSERT (PeiCoreEntryPoint != NULL);\r
388 (*PeiCoreEntryPoint) (SecCoreData, PpiList);\r
389\r
390 //\r
391 // Should not come here.\r
392 //\r
61257251 393 UNREACHABLE ();\r
1921695e
MK
394}\r
395\r
396/**\r
397 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked\r
398 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.\r
399\r
400 @retval EFI_SUCCESS Use of Temporary RAM was disabled.\r
401 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.\r
402\r
403**/\r
404EFI_STATUS\r
405EFIAPI\r
406SecTemporaryRamDone (\r
407 VOID\r
408 )\r
409{\r
479613bd
MK
410 EFI_STATUS Status;\r
411 EFI_STATUS Status2;\r
412 UINTN Index;\r
413 BOOLEAN State;\r
414 EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;\r
415 REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;\r
1921695e 416\r
8a5b8cef
JF
417 //\r
418 // Republish Sec Platform Information(2) PPI\r
419 //\r
420 RepublishSecPlatformInformationPpi ();\r
421\r
479613bd
MK
422 //\r
423 // Re-install SEC PPIs using a PEIM produced service if published\r
424 //\r
425 for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {\r
426 Status = PeiServicesLocatePpi (\r
427 &gRepublishSecPpiPpiGuid,\r
428 Index,\r
429 &PeiPpiDescriptor,\r
430 (VOID **) &RepublishSecPpiPpi\r
431 );\r
432 if (!EFI_ERROR (Status)) {\r
433 DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));\r
434 Status2 = RepublishSecPpiPpi->RepublishSecPpis ();\r
435 ASSERT_EFI_ERROR (Status2);\r
436 }\r
437 }\r
438\r
1921695e
MK
439 //\r
440 // Migrate DebugAgentContext.\r
441 //\r
442 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);\r
443\r
444 //\r
445 // Disable interrupts and save current interrupt state\r
446 //\r
479613bd 447 State = SaveAndDisableInterrupts ();\r
1921695e 448\r
f6ec1dd3
GJ
449 //\r
450 // Migrate GDT before NEM near down\r
451 //\r
452 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {\r
453 Status = MigrateGdt ();\r
454 ASSERT_EFI_ERROR (Status);\r
455 }\r
456\r
1921695e
MK
457 //\r
458 // Disable Temporary RAM after Stack and Heap have been migrated at this point.\r
459 //\r
460 SecPlatformDisableTemporaryMemory ();\r
461\r
462 //\r
463 // Restore original interrupt state\r
464 //\r
465 SetInterruptState (State);\r
466\r
467 return EFI_SUCCESS;\r
468}\r