3 Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
11 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi
= {
12 SecTemporaryRamSupport
15 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi
[] = {
17 EFI_PEI_PPI_DESCRIPTOR_PPI
,
18 &gFspInApiModePpiGuid
,
22 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
23 &gEfiTemporaryRamSupportPpiGuid
,
24 &gSecTemporaryRamSupportPpi
29 // These are IDT entries pointing to 08:FFFFFFE4h.
31 UINT64 mIdtEntryTemplate
= 0xffff8e000008ffe4ULL
;
35 Entry point to the C language phase of SEC. After the SEC assembly
36 code has initialized some temporary memory and set up the stack,
37 the control is transferred to this function.
40 @param[in] SizeOfRam Size of the temporary memory available for use.
41 @param[in] TempRamBase Base address of temporary ram
42 @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
43 @param[in] PeiCore PeiCore entry point.
44 @param[in] BootLoaderStack BootLoader stack.
45 @param[in] ApiIdx the index of API.
47 @return This function never returns.
54 IN UINT32 TempRamBase
,
55 IN VOID
*BootFirmwareVolume
,
56 IN PEI_CORE_ENTRY PeiCore
,
57 IN UINT32 BootLoaderStack
,
61 EFI_SEC_PEI_HAND_OFF SecCoreData
;
62 IA32_DESCRIPTOR IdtDescriptor
;
63 SEC_IDT_TABLE IdtTableInStack
;
65 FSP_GLOBAL_DATA PeiFspData
;
66 UINT64 ExceptionHandler
;
70 // Process all libraries constructor function linked to SecCore.
72 ProcessLibraryConstructorList ();
75 // Initialize floating point operating environment
76 // to be compliant with UEFI spec.
78 InitializeFloatingPointUnits ();
81 // Scenario 1 memory map when running on bootloader stack
83 // |-------------------|---->
85 // |-------------------|
86 // |PeiService Pointer |
87 // |-------------------|
93 // |-------------------|----> TempRamBase
96 // |-------------------|
97 // |Bootloader stack |----> somewhere in memory, FSP will share this stack.
98 // |-------------------|
101 // Scenario 2 memory map when running FSP on a separate stack
103 // |-------------------|---->
105 // |-------------------|
106 // |PeiService Pointer | PeiStackSize
107 // |-------------------|
110 // |-------------------|---->
113 // | Heap | PeiTemporaryRamSize
116 // |-------------------|----> TempRamBase
117 IdtTableInStack
.PeiService
= 0;
118 AsmReadIdtr (&IdtDescriptor
);
119 if (IdtDescriptor
.Base
== 0) {
120 ExceptionHandler
= FspGetExceptionHandler (mIdtEntryTemplate
);
121 for (Index
= 0; Index
< FixedPcdGet8 (PcdFspMaxInterruptSupported
); Index
++) {
122 CopyMem ((VOID
*)&IdtTableInStack
.IdtTable
[Index
], (VOID
*)&ExceptionHandler
, sizeof (UINT64
));
125 IdtSize
= sizeof (IdtTableInStack
.IdtTable
);
127 IdtSize
= IdtDescriptor
.Limit
+ 1;
128 if (IdtSize
> sizeof (IdtTableInStack
.IdtTable
)) {
130 // ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
134 CopyMem ((VOID
*)(UINTN
)&IdtTableInStack
.IdtTable
, (VOID
*)IdtDescriptor
.Base
, IdtSize
);
138 IdtDescriptor
.Base
= (UINTN
)&IdtTableInStack
.IdtTable
;
139 IdtDescriptor
.Limit
= (UINT16
)(IdtSize
- 1);
141 AsmWriteIdtr (&IdtDescriptor
);
144 // Initialize the global FSP data region
146 FspGlobalDataInit (&PeiFspData
, BootLoaderStack
, (UINT8
)ApiIdx
);
149 // Update the base address and length of Pei temporary memory
151 SecCoreData
.DataSize
= sizeof (EFI_SEC_PEI_HAND_OFF
);
152 SecCoreData
.BootFirmwareVolumeBase
= BootFirmwareVolume
;
153 SecCoreData
.BootFirmwareVolumeSize
= (UINT32
)((EFI_FIRMWARE_VOLUME_HEADER
*)BootFirmwareVolume
)->FvLength
;
156 // Support FSP reserved temporary memory from the whole temporary memory provided by bootloader.
157 // FSP reserved temporary memory will not be given to PeiCore.
159 SecCoreData
.TemporaryRamBase
= (UINT8
*)(UINTN
)TempRamBase
+ PcdGet32 (PcdFspPrivateTemporaryRamSize
);
160 SecCoreData
.TemporaryRamSize
= SizeOfRam
- PcdGet32 (PcdFspPrivateTemporaryRamSize
);
161 if (PcdGet8 (PcdFspHeapSizePercentage
) == 0) {
162 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
163 SecCoreData
.PeiTemporaryRamSize
= SecCoreData
.TemporaryRamSize
;
164 SecCoreData
.StackBase
= (VOID
*)GetFspEntryStack (); // Share the same boot loader stack
165 SecCoreData
.StackSize
= 0;
167 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
168 SecCoreData
.PeiTemporaryRamSize
= SecCoreData
.TemporaryRamSize
* PcdGet8 (PcdFspHeapSizePercentage
) / 100;
169 SecCoreData
.StackBase
= (VOID
*)(UINTN
)((UINTN
)SecCoreData
.TemporaryRamBase
+ SecCoreData
.PeiTemporaryRamSize
);
170 SecCoreData
.StackSize
= SecCoreData
.TemporaryRamSize
- SecCoreData
.PeiTemporaryRamSize
;
173 DEBUG ((DEBUG_INFO
, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData
.BootFirmwareVolumeBase
));
174 DEBUG ((DEBUG_INFO
, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData
.BootFirmwareVolumeSize
));
175 DEBUG ((DEBUG_INFO
, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData
.TemporaryRamBase
));
176 DEBUG ((DEBUG_INFO
, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData
.TemporaryRamSize
));
177 DEBUG ((DEBUG_INFO
, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData
.PeiTemporaryRamBase
));
178 DEBUG ((DEBUG_INFO
, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData
.PeiTemporaryRamSize
));
179 DEBUG ((DEBUG_INFO
, "Fsp StackBase - 0x%x\n", SecCoreData
.StackBase
));
180 DEBUG ((DEBUG_INFO
, "Fsp StackSize - 0x%x\n", SecCoreData
.StackSize
));
183 // Call PeiCore Entry
185 PeiCore (&SecCoreData
, mPeiSecPlatformInformationPpi
);
188 // Should never be here
194 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
197 @param[in] PeiServices Pointer to the PEI Services Table.
198 @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
199 Temporary RAM contents.
200 @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
201 Temporary RAM contents.
202 @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
204 @retval EFI_SUCCESS The data was successfully returned.
205 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
206 TemporaryMemoryBase > PermanentMemoryBase.
211 SecTemporaryRamSupport (
212 IN CONST EFI_PEI_SERVICES
**PeiServices
,
213 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
214 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
218 IA32_DESCRIPTOR IdtDescriptor
;
230 // Override OnSeparateStack to 1 because this function will switch stack to permanent memory
231 // which makes FSP running on different stack from bootloader temporary ram stack.
233 GetFspGlobalDataPointer ()->OnSeparateStack
= 1;
235 if (PcdGet8 (PcdFspHeapSizePercentage
) == 0) {
236 CurrentStack
= AsmReadEsp ();
237 FspStackBase
= (UINTN
)GetFspEntryStack ();
239 StackSize
= FspStackBase
- CurrentStack
;
242 OldHeap
= (VOID
*)(UINTN
)TemporaryMemoryBase
;
243 NewHeap
= (VOID
*)((UINTN
)PermanentMemoryBase
);
245 OldStack
= (VOID
*)CurrentStack
;
247 // The old stack is copied at the end of the stack region because stack grows down.
249 NewStack
= (VOID
*)((UINTN
)PermanentMemoryBase
- StackSize
);
251 HeapSize
= CopySize
* PcdGet8 (PcdFspHeapSizePercentage
) / 100;
252 StackSize
= CopySize
- HeapSize
;
254 OldHeap
= (VOID
*)(UINTN
)TemporaryMemoryBase
;
255 NewHeap
= (VOID
*)((UINTN
)PermanentMemoryBase
+ StackSize
);
257 OldStack
= (VOID
*)((UINTN
)TemporaryMemoryBase
+ HeapSize
);
258 NewStack
= (VOID
*)(UINTN
)PermanentMemoryBase
;
264 CopyMem (NewHeap
, OldHeap
, HeapSize
);
269 CopyMem (NewStack
, OldStack
, StackSize
);
272 // We need *not* fix the return address because currently,
273 // The PeiCore is executed in flash.
277 // Rebase IDT table in permanent memory
279 AsmReadIdtr (&IdtDescriptor
);
280 IdtDescriptor
.Base
= IdtDescriptor
.Base
- (UINTN
)OldStack
+ (UINTN
)NewStack
;
282 AsmWriteIdtr (&IdtDescriptor
);
285 // Fixed the FSP data pointer
287 FspDataPointerFixUp ((UINTN
)NewStack
- (UINTN
)OldStack
);
290 // SecSwitchStack function must be invoked after the memory migration
291 // immediately, also we need fixup the stack change caused by new call into
295 (UINT32
)(UINTN
)OldStack
,
296 (UINT32
)(UINTN
)NewStack