UefiPayloadPkg: Enhance UEFI payload for coreboot and Slim Bootloader
[mirror_edk2.git] / UefiPayloadPkg / SecCore / SecMain.c
CommitLineData
04af8bf2
DG
1/** @file\r
2 C functions in SEC\r
3\r
4Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9\r
10#include "SecMain.h"\r
11\r
12EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {\r
13 SecTemporaryRamSupport\r
14};\r
15\r
16EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {\r
17 {\r
18 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
19 &gEfiTemporaryRamSupportPpiGuid,\r
20 &gSecTemporaryRamSupportPpi\r
21 }\r
22};\r
23\r
24//\r
25// These are IDT entries pointing to 10:FFFFFFE4h.\r
26//\r
27UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;\r
28\r
29/**\r
30 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
31\r
32 Entry point to the C language phase of SEC. After the SEC assembly\r
33 code has initialized some temporary memory and set up the stack,\r
34 the control is transferred to this function.\r
35\r
36 @param[in] Context The first input parameter of InitializeDebugAgent().\r
37\r
38**/\r
39VOID\r
40EFIAPI\r
41SecStartupPhase2(\r
42 IN VOID *Context\r
43 );\r
44\r
45\r
46/**\r
47\r
48 Entry point to the C language phase of SEC. After the SEC assembly\r
49 code has initialized some temporary memory and set up the stack,\r
50 the control is transferred to this function.\r
51\r
52\r
53 @param SizeOfRam Size of the temporary memory available for use.\r
54 @param TempRamBase Base address of temporary ram\r
55 @param BootFirmwareVolume Base address of the Boot Firmware Volume.\r
56 @param BootloaderParameter A parameter from bootloader, e.g. HobList from SlimBootloader\r
57\r
58**/\r
59VOID\r
60EFIAPI\r
61SecStartup (\r
62 IN UINT32 SizeOfRam,\r
63 IN UINT32 TempRamBase,\r
64 IN VOID *BootFirmwareVolume,\r
65 IN UINT32 BootloaderParameter\r
66 )\r
67{\r
68 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
69 IA32_DESCRIPTOR IdtDescriptor;\r
70 SEC_IDT_TABLE IdtTableInStack;\r
71 UINT32 Index;\r
72 UINT32 PeiStackSize;\r
73\r
74 PeiStackSize = (SizeOfRam >> 1);\r
75\r
76 ASSERT (PeiStackSize < SizeOfRam);\r
77\r
78 //\r
79 // Process all libraries constructor function linked to SecCore.\r
80 //\r
81 ProcessLibraryConstructorList ();\r
82\r
83 //\r
84 // Initialize floating point operating environment\r
85 // to be compliant with UEFI spec.\r
86 //\r
87 InitializeFloatingPointUnits ();\r
88\r
89\r
90 // |-------------------|---->\r
91 // |Idt Table |\r
92 // |-------------------|\r
93 // |PeiService Pointer | PeiStackSize\r
94 // |-------------------|\r
95 // | |\r
96 // | Stack |\r
97 // |-------------------|---->\r
98 // | |\r
99 // | |\r
100 // | Heap | PeiTemporaryRamSize\r
101 // | |\r
102 // | |\r
103 // |-------------------|----> TempRamBase\r
104\r
105 IdtTableInStack.PeiService = 0;\r
106 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
107 CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));\r
108 }\r
109\r
110 IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;\r
111 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
112\r
113 AsmWriteIdtr (&IdtDescriptor);\r
114\r
115 //\r
116 // Update the base address and length of Pei temporary memory\r
117 //\r
118 SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);\r
119 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;\r
120 SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);\r
121 SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;\r
122 SecCoreData.TemporaryRamSize = SizeOfRam;\r
123 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
124 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;\r
125 SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);\r
126 SecCoreData.StackSize = PeiStackSize;\r
127\r
128 //\r
129 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
130 //\r
131 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
132\r
133}\r
134\r
135/**\r
136 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
137\r
138 Entry point to the C language phase of SEC. After the SEC assembly\r
139 code has initialized some temporary memory and set up the stack,\r
140 the control is transferred to this function.\r
141\r
142 @param[in] Context The first input parameter of InitializeDebugAgent().\r
143\r
144**/\r
145VOID\r
146EFIAPI\r
147SecStartupPhase2(\r
148 IN VOID *Context\r
149 )\r
150{\r
151 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
152 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
153\r
154 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
155 //\r
156 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug\r
157 // is enabled.\r
158 //\r
159 FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);\r
160 if (PeiCoreEntryPoint == NULL)\r
161 {\r
162 CpuDeadLoop ();\r
163 }\r
164\r
165 //\r
166 // Transfer the control to the PEI core\r
167 //\r
168 ASSERT (PeiCoreEntryPoint != NULL);\r
169 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi);\r
170\r
171 //\r
172 // Should not come here.\r
173 //\r
174 return ;\r
175}\r
176\r
177/**\r
178 This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into\r
179 permanent memory.\r
180\r
181 @param PeiServices Pointer to the PEI Services Table.\r
182 @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the\r
183 Temporary RAM contents.\r
184 @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the\r
185 Temporary RAM contents.\r
186 @param CopySize Amount of memory to migrate from temporary to permanent memory.\r
187\r
188 @retval EFI_SUCCESS The data was successfully returned.\r
189 @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when\r
190 TemporaryMemoryBase > PermanentMemoryBase.\r
191\r
192**/\r
193EFI_STATUS\r
194EFIAPI\r
195SecTemporaryRamSupport (\r
196 IN CONST EFI_PEI_SERVICES **PeiServices,\r
197 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
198 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
199 IN UINTN CopySize\r
200 )\r
201{\r
202 IA32_DESCRIPTOR IdtDescriptor;\r
203 VOID* OldHeap;\r
204 VOID* NewHeap;\r
205 VOID* OldStack;\r
206 VOID* NewStack;\r
207 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
208 BOOLEAN OldStatus;\r
209 UINTN PeiStackSize;\r
210\r
211 PeiStackSize = (CopySize >> 1);\r
212\r
213 ASSERT (PeiStackSize < CopySize);\r
214\r
215 //\r
216 // |-------------------|---->\r
217 // | Stack | PeiStackSize\r
218 // |-------------------|---->\r
219 // | Heap | PeiTemporaryRamSize\r
220 // |-------------------|----> TempRamBase\r
221 //\r
222 // |-------------------|---->\r
223 // | Heap | PeiTemporaryRamSize\r
224 // |-------------------|---->\r
225 // | Stack | PeiStackSize\r
226 // |-------------------|----> PermanentMemoryBase\r
227 //\r
228\r
229 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
230 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);\r
231\r
232 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);\r
233 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
234\r
235 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
236 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
237\r
238 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
239 //\r
240 // Initialize Debug Agent to support source level debug in PEI phase after memory ready.\r
241 // It will build HOB and fix up the pointer in IDT table.\r
242 //\r
243 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
244\r
245 //\r
246 // Migrate Heap\r
247 //\r
248 CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);\r
249\r
250 //\r
251 // Migrate Stack\r
252 //\r
253 CopyMem (NewStack, OldStack, PeiStackSize);\r
254\r
255\r
256 //\r
257 // We need *not* fix the return address because currently,\r
258 // The PeiCore is executed in flash.\r
259 //\r
260\r
261 //\r
262 // Rebase IDT table in permanent memory\r
263 //\r
264 AsmReadIdtr (&IdtDescriptor);\r
265 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
266\r
267 AsmWriteIdtr (&IdtDescriptor);\r
268\r
269\r
270 //\r
271 // Program MTRR\r
272 //\r
273\r
274 //\r
275 // SecSwitchStack function must be invoked after the memory migration\r
276 // immediately, also we need fixup the stack change caused by new call into\r
277 // permanent memory.\r
278 //\r
279 SecSwitchStack (\r
280 (UINT32) (UINTN) OldStack,\r
281 (UINT32) (UINTN) NewStack\r
282 );\r
283\r
284 SaveAndSetDebugTimerInterrupt (OldStatus);\r
285\r
286 return EFI_SUCCESS;\r
287}\r
288\r