4 Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi
= {
15 EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi
= { SecPlatformInformation
};
17 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi
[] = {
20 // SecPerformance PPI notify descriptor.
22 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
,
23 &gPeiSecPerformancePpiGuid
,
24 (VOID
*)(UINTN
)SecPerformancePpiCallBack
27 EFI_PEI_PPI_DESCRIPTOR_PPI
,
28 &gEfiTemporaryRamDonePpiGuid
,
29 &gSecTemporaryRamDonePpi
32 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
33 &gEfiSecPlatformInformationPpiGuid
,
34 &mSecPlatformInformationPpi
39 Migrates the Global Descriptor Table (GDT) to permanent memory.
41 @retval EFI_SUCCESS The GDT was migrated successfully.
42 @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
55 AsmReadGdtr ((IA32_DESCRIPTOR
*)&Gdtr
);
56 GdtBufferSize
= sizeof (IA32_SEGMENT_DESCRIPTOR
) -1 + Gdtr
.Limit
+ 1;
58 Status
= PeiServicesAllocatePool (
62 ASSERT (GdtBuffer
!= NULL
);
63 if (EFI_ERROR (Status
)) {
64 return EFI_OUT_OF_RESOURCES
;
67 GdtBuffer
= ALIGN_POINTER (GdtBuffer
, sizeof (IA32_SEGMENT_DESCRIPTOR
));
68 CopyMem (GdtBuffer
, (VOID
*)Gdtr
.Base
, Gdtr
.Limit
+ 1);
69 Gdtr
.Base
= (UINTN
)GdtBuffer
;
76 // These are IDT entries pointing to 10:FFFFFFE4h.
78 UINT64 mIdtEntryTemplate
= 0xffff8e000010ffe4ULL
;
81 Caller provided function to be invoked at the end of InitializeDebugAgent().
83 Entry point to the C language phase of SEC. After the SEC assembly
84 code has initialized some temporary memory and set up the stack,
85 the control is transferred to this function.
87 @param[in] Context The first input parameter of InitializeDebugAgent().
98 Entry point of the notification callback function itself within the PEIM.
99 It is to get SEC performance data and build HOB to convey the SEC performance
102 @param PeiServices Indirect reference to the PEI Services Table.
103 @param NotifyDescriptor Address of the notification descriptor data structure.
104 @param Ppi Address of the PPI that was installed.
106 @return Status of the notification.
107 The status code returned from this function is ignored.
111 SecPerformancePpiCallBack (
112 IN EFI_PEI_SERVICES
**PeiServices
,
113 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
118 PEI_SEC_PERFORMANCE_PPI
*SecPerf
;
119 FIRMWARE_SEC_PERFORMANCE Performance
;
121 SecPerf
= (PEI_SEC_PERFORMANCE_PPI
*)Ppi
;
122 Status
= SecPerf
->GetPerformance ((CONST EFI_PEI_SERVICES
**)PeiServices
, SecPerf
, &Performance
);
123 if (!EFI_ERROR (Status
)) {
125 &gEfiFirmwarePerformanceGuid
,
127 sizeof (FIRMWARE_SEC_PERFORMANCE
)
129 DEBUG ((DEBUG_INFO
, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance
.ResetEnd
));
137 Entry point to the C language phase of SEC. After the SEC assembly
138 code has initialized some temporary memory and set up the stack,
139 the control is transferred to this function.
142 @param SizeOfRam Size of the temporary memory available for use.
143 @param TempRamBase Base address of temporary ram
144 @param BootFirmwareVolume Base address of the Boot Firmware Volume.
151 IN UINT32 TempRamBase
,
152 IN VOID
*BootFirmwareVolume
155 EFI_SEC_PEI_HAND_OFF SecCoreData
;
156 IA32_DESCRIPTOR IdtDescriptor
;
157 SEC_IDT_TABLE IdtTableInStack
;
163 // Report Status Code to indicate entering SEC core
167 EFI_SOFTWARE_SEC
| EFI_SW_SEC_PC_ENTRY_POINT
172 "%a() TempRAM Base: 0x%x, TempRAM Size: 0x%x, BootFirmwareVolume 0x%x\n",
179 PeiStackSize
= PcdGet32 (PcdPeiTemporaryRamStackSize
);
180 if (PeiStackSize
== 0) {
181 PeiStackSize
= (SizeOfRam
>> 1);
184 ASSERT (PeiStackSize
< SizeOfRam
);
187 // Process all libraries constructor function linked to SecCore.
189 ProcessLibraryConstructorList ();
192 // Initialize floating point operating environment
193 // to be compliant with UEFI spec.
195 InitializeFloatingPointUnits ();
197 // |-------------------|---->
199 // |-------------------|
200 // |PeiService Pointer | PeiStackSize
201 // |-------------------|
204 // |-------------------|---->
207 // | Heap | PeiTemporayRamSize
210 // |-------------------|----> TempRamBase
212 IdtTableInStack
.PeiService
= 0;
213 for (Index
= 0; Index
< SEC_IDT_ENTRY_COUNT
; Index
++) {
214 ZeroMem ((VOID
*)&IdtTableInStack
.IdtTable
[Index
], sizeof (IA32_IDT_GATE_DESCRIPTOR
));
215 CopyMem ((VOID
*)&IdtTableInStack
.IdtTable
[Index
], (VOID
*)&mIdtEntryTemplate
, sizeof (UINT64
));
218 IdtDescriptor
.Base
= (UINTN
)&IdtTableInStack
.IdtTable
;
219 IdtDescriptor
.Limit
= (UINT16
)(sizeof (IdtTableInStack
.IdtTable
) - 1);
221 AsmWriteIdtr (&IdtDescriptor
);
224 // Setup the default exception handlers
226 Status
= InitializeCpuExceptionHandlers (NULL
);
227 ASSERT_EFI_ERROR (Status
);
230 // Update the base address and length of Pei temporary memory
232 SecCoreData
.DataSize
= (UINT16
)sizeof (EFI_SEC_PEI_HAND_OFF
);
233 SecCoreData
.BootFirmwareVolumeBase
= BootFirmwareVolume
;
234 SecCoreData
.BootFirmwareVolumeSize
= (UINTN
)((EFI_FIRMWARE_VOLUME_HEADER
*)BootFirmwareVolume
)->FvLength
;
235 SecCoreData
.TemporaryRamBase
= (VOID
*)(UINTN
)TempRamBase
;
236 SecCoreData
.TemporaryRamSize
= SizeOfRam
;
237 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
238 SecCoreData
.PeiTemporaryRamSize
= SizeOfRam
- PeiStackSize
;
239 SecCoreData
.StackBase
= (VOID
*)(UINTN
)(TempRamBase
+ SecCoreData
.PeiTemporaryRamSize
);
240 SecCoreData
.StackSize
= PeiStackSize
;
244 "%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",
246 SecCoreData
.BootFirmwareVolumeBase
,
247 SecCoreData
.BootFirmwareVolumeSize
,
248 SecCoreData
.TemporaryRamBase
,
249 SecCoreData
.TemporaryRamSize
,
250 SecCoreData
.PeiTemporaryRamBase
,
251 SecCoreData
.PeiTemporaryRamSize
,
252 SecCoreData
.StackBase
,
253 SecCoreData
.StackSize
257 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
259 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC
, &SecCoreData
, SecStartupPhase2
);
262 // Should not come here.
268 Caller provided function to be invoked at the end of InitializeDebugAgent().
270 Entry point to the C language phase of SEC. After the SEC assembly
271 code has initialized some temporary memory and set up the stack,
272 the control is transferred to this function.
274 @param[in] Context The first input parameter of InitializeDebugAgent().
284 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
285 EFI_PEI_PPI_DESCRIPTOR
*PpiList
;
287 EFI_PEI_PPI_DESCRIPTOR
*AllSecPpiList
;
288 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
;
290 PeiCoreEntryPoint
= NULL
;
291 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)Context
;
294 // Perform platform specific initialization before entering PeiCore.
296 PpiList
= SecPlatformMain (SecCoreData
);
298 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
301 if (PpiList
!= NULL
) {
304 if (CompareGuid (PpiList
[Index
].Guid
, &gEfiPeiCoreFvLocationPpiGuid
) &&
305 (((EFI_PEI_CORE_FV_LOCATION_PPI
*)PpiList
[Index
].Ppi
)->PeiCoreFvLocation
!= 0)
309 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.
311 FindAndReportEntryPoints (
312 (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
,
313 (EFI_FIRMWARE_VOLUME_HEADER
*)((EFI_PEI_CORE_FV_LOCATION_PPI
*)PpiList
[Index
].Ppi
)->PeiCoreFvLocation
,
316 if (PeiCoreEntryPoint
!= NULL
) {
320 // Invalid PeiCore FV provided by platform
325 } while ((PpiList
[Index
++].Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
329 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.
331 if (PeiCoreEntryPoint
== NULL
) {
333 // Both SecCore and PeiCore are in BFV.
335 FindAndReportEntryPoints (
336 (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
,
337 (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
,
340 if (PeiCoreEntryPoint
== NULL
) {
347 "%a() PeiCoreEntryPoint: 0x%x\n",
352 if (PpiList
!= NULL
) {
353 AllSecPpiList
= (EFI_PEI_PPI_DESCRIPTOR
*)SecCoreData
->PeiTemporaryRamBase
;
356 // Remove the terminal flag from the terminal PPI
358 CopyMem (AllSecPpiList
, mPeiSecPlatformInformationPpi
, sizeof (mPeiSecPlatformInformationPpi
));
359 Index
= sizeof (mPeiSecPlatformInformationPpi
) / sizeof (EFI_PEI_PPI_DESCRIPTOR
) - 1;
360 AllSecPpiList
[Index
].Flags
= AllSecPpiList
[Index
].Flags
& (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
363 // Append the platform additional PPI list
366 while (((PpiList
->Flags
& EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
)) {
367 CopyMem (&AllSecPpiList
[Index
], PpiList
, sizeof (EFI_PEI_PPI_DESCRIPTOR
));
373 // Add the terminal PPI
375 CopyMem (&AllSecPpiList
[Index
++], PpiList
, sizeof (EFI_PEI_PPI_DESCRIPTOR
));
378 // Set PpiList to the total PPI
380 PpiList
= AllSecPpiList
;
383 // Adjust PEI TEMP RAM Range.
385 ASSERT (SecCoreData
->PeiTemporaryRamSize
> Index
* sizeof (EFI_PEI_PPI_DESCRIPTOR
));
386 SecCoreData
->PeiTemporaryRamBase
= (VOID
*)((UINTN
)SecCoreData
->PeiTemporaryRamBase
+ Index
* sizeof (EFI_PEI_PPI_DESCRIPTOR
));
387 SecCoreData
->PeiTemporaryRamSize
= SecCoreData
->PeiTemporaryRamSize
- Index
* sizeof (EFI_PEI_PPI_DESCRIPTOR
);
389 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement
390 // will be built based on them in PEI phase.
392 SecCoreData
->PeiTemporaryRamBase
= (VOID
*)(((UINTN
)SecCoreData
->PeiTemporaryRamBase
+ 7) & ~0x07);
393 SecCoreData
->PeiTemporaryRamSize
&= ~(UINTN
)0x07;
396 "%a() PeiTemporaryRamBase: 0x%x, PeiTemporaryRamSize: 0x%x\n",
398 SecCoreData
->PeiTemporaryRamBase
,
399 SecCoreData
->PeiTemporaryRamSize
403 // No addition PPI, PpiList directly point to the common PPI list.
405 PpiList
= &mPeiSecPlatformInformationPpi
[0];
410 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
412 SecCoreData
->StackBase
,
413 (UINT32
)SecCoreData
->StackSize
417 // Report Status Code to indicate transferring to PEI core
421 EFI_SOFTWARE_SEC
| EFI_SW_SEC_PC_HANDOFF_TO_NEXT
425 // Transfer the control to the PEI core
427 ASSERT (PeiCoreEntryPoint
!= NULL
);
428 (*PeiCoreEntryPoint
)(SecCoreData
, PpiList
);
431 // Should not come here.
437 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
438 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
440 @retval EFI_SUCCESS Use of Temporary RAM was disabled.
441 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
446 SecTemporaryRamDone (
454 EFI_PEI_PPI_DESCRIPTOR
*PeiPpiDescriptor
;
455 REPUBLISH_SEC_PPI_PPI
*RepublishSecPpiPpi
;
458 // Republish Sec Platform Information(2) PPI
460 RepublishSecPlatformInformationPpi ();
463 // Re-install SEC PPIs using a PEIM produced service if published
465 for (Index
= 0, Status
= EFI_SUCCESS
; Status
== EFI_SUCCESS
; Index
++) {
466 Status
= PeiServicesLocatePpi (
467 &gRepublishSecPpiPpiGuid
,
470 (VOID
**)&RepublishSecPpiPpi
472 if (!EFI_ERROR (Status
)) {
473 DEBUG ((DEBUG_INFO
, "Calling RepublishSecPpi instance %d.\n", Index
));
474 Status2
= RepublishSecPpiPpi
->RepublishSecPpis ();
475 ASSERT_EFI_ERROR (Status2
);
480 // Migrate DebugAgentContext.
482 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC
, NULL
, NULL
);
485 // Disable interrupts and save current interrupt state
487 State
= SaveAndDisableInterrupts ();
490 // Migrate GDT before NEM near down
492 if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes
)) {
493 Status
= MigrateGdt ();
494 ASSERT_EFI_ERROR (Status
);
498 // Disable Temporary RAM after Stack and Heap have been migrated at this point.
500 SecPlatformDisableTemporaryMemory ();
503 // Restore original interrupt state
505 SetInterruptState (State
);