]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/SecCore/SecMain.c
66c952b897fafdcbf2dbaca5713ddfac32a2ca0f
[mirror_edk2.git] / UefiCpuPkg / SecCore / SecMain.c
1 /** @file
2 C functions in SEC
3
4 Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "SecMain.h"
10
11 EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi = {
12 SecTemporaryRamDone
13 };
14
15 EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };
16
17 EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
18 {
19 //
20 // SecPerformance PPI notify descriptor.
21 //
22 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
23 &gPeiSecPerformancePpiGuid,
24 (VOID *) (UINTN) SecPerformancePpiCallBack
25 },
26 {
27 EFI_PEI_PPI_DESCRIPTOR_PPI,
28 &gEfiTemporaryRamDonePpiGuid,
29 &gSecTemporaryRamDonePpi
30 },
31 {
32 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
33 &gEfiSecPlatformInformationPpiGuid,
34 &mSecPlatformInformationPpi
35 }
36 };
37
38 //
39 // These are IDT entries pointing to 10:FFFFFFE4h.
40 //
41 UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
42
43 /**
44 Caller provided function to be invoked at the end of InitializeDebugAgent().
45
46 Entry point to the C language phase of SEC. After the SEC assembly
47 code has initialized some temporary memory and set up the stack,
48 the control is transferred to this function.
49
50 @param[in] Context The first input parameter of InitializeDebugAgent().
51
52 **/
53 VOID
54 NORETURN
55 EFIAPI
56 SecStartupPhase2(
57 IN VOID *Context
58 );
59
60 /**
61 Entry point of the notification callback function itself within the PEIM.
62 It is to get SEC performance data and build HOB to convey the SEC performance
63 data to DXE phase.
64
65 @param PeiServices Indirect reference to the PEI Services Table.
66 @param NotifyDescriptor Address of the notification descriptor data structure.
67 @param Ppi Address of the PPI that was installed.
68
69 @return Status of the notification.
70 The status code returned from this function is ignored.
71 **/
72 EFI_STATUS
73 EFIAPI
74 SecPerformancePpiCallBack (
75 IN EFI_PEI_SERVICES **PeiServices,
76 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
77 IN VOID *Ppi
78 )
79 {
80 EFI_STATUS Status;
81 PEI_SEC_PERFORMANCE_PPI *SecPerf;
82 FIRMWARE_SEC_PERFORMANCE Performance;
83
84 SecPerf = (PEI_SEC_PERFORMANCE_PPI *) Ppi;
85 Status = SecPerf->GetPerformance ((CONST EFI_PEI_SERVICES **) PeiServices, SecPerf, &Performance);
86 if (!EFI_ERROR (Status)) {
87 BuildGuidDataHob (
88 &gEfiFirmwarePerformanceGuid,
89 &Performance,
90 sizeof (FIRMWARE_SEC_PERFORMANCE)
91 );
92 DEBUG ((DEBUG_INFO, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance.ResetEnd));
93 }
94
95 return Status;
96 }
97
98 /**
99
100 Entry point to the C language phase of SEC. After the SEC assembly
101 code has initialized some temporary memory and set up the stack,
102 the control is transferred to this function.
103
104
105 @param SizeOfRam Size of the temporary memory available for use.
106 @param TempRamBase Base address of temporary ram
107 @param BootFirmwareVolume Base address of the Boot Firmware Volume.
108 **/
109 VOID
110 NORETURN
111 EFIAPI
112 SecStartup (
113 IN UINT32 SizeOfRam,
114 IN UINT32 TempRamBase,
115 IN VOID *BootFirmwareVolume
116 )
117 {
118 EFI_SEC_PEI_HAND_OFF SecCoreData;
119 IA32_DESCRIPTOR IdtDescriptor;
120 SEC_IDT_TABLE IdtTableInStack;
121 UINT32 Index;
122 UINT32 PeiStackSize;
123 EFI_STATUS Status;
124
125 //
126 // Report Status Code to indicate entering SEC core
127 //
128 REPORT_STATUS_CODE (
129 EFI_PROGRESS_CODE,
130 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT
131 );
132
133 PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);
134 if (PeiStackSize == 0) {
135 PeiStackSize = (SizeOfRam >> 1);
136 }
137
138 ASSERT (PeiStackSize < SizeOfRam);
139
140 //
141 // Process all libraries constructor function linked to SecCore.
142 //
143 ProcessLibraryConstructorList ();
144
145 //
146 // Initialize floating point operating environment
147 // to be compliant with UEFI spec.
148 //
149 InitializeFloatingPointUnits ();
150
151 // |-------------------|---->
152 // |IDT Table |
153 // |-------------------|
154 // |PeiService Pointer | PeiStackSize
155 // |-------------------|
156 // | |
157 // | Stack |
158 // |-------------------|---->
159 // | |
160 // | |
161 // | Heap | PeiTemporayRamSize
162 // | |
163 // | |
164 // |-------------------|----> TempRamBase
165
166 IdtTableInStack.PeiService = 0;
167 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
168 CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
169 }
170
171 IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
172 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
173
174 AsmWriteIdtr (&IdtDescriptor);
175
176 //
177 // Setup the default exception handlers
178 //
179 Status = InitializeCpuExceptionHandlers (NULL);
180 ASSERT_EFI_ERROR (Status);
181
182 //
183 // Update the base address and length of Pei temporary memory
184 //
185 SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
186 SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
187 SecCoreData.BootFirmwareVolumeSize = (UINTN)((EFI_FIRMWARE_VOLUME_HEADER *) BootFirmwareVolume)->FvLength;
188 SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
189 SecCoreData.TemporaryRamSize = SizeOfRam;
190 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
191 SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;
192 SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
193 SecCoreData.StackSize = PeiStackSize;
194
195 //
196 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
197 //
198 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
199
200 //
201 // Should not come here.
202 //
203 UNREACHABLE ();
204 }
205
206 /**
207 Caller provided function to be invoked at the end of InitializeDebugAgent().
208
209 Entry point to the C language phase of SEC. After the SEC assembly
210 code has initialized some temporary memory and set up the stack,
211 the control is transferred to this function.
212
213 @param[in] Context The first input parameter of InitializeDebugAgent().
214
215 **/
216 VOID
217 NORETURN
218 EFIAPI
219 SecStartupPhase2(
220 IN VOID *Context
221 )
222 {
223 EFI_SEC_PEI_HAND_OFF *SecCoreData;
224 EFI_PEI_PPI_DESCRIPTOR *PpiList;
225 UINT32 Index;
226 EFI_PEI_PPI_DESCRIPTOR *AllSecPpiList;
227 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
228
229 PeiCoreEntryPoint = NULL;
230 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
231
232 //
233 // Perform platform specific initialization before entering PeiCore.
234 //
235 PpiList = SecPlatformMain (SecCoreData);
236 //
237 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
238 // is enabled.
239 //
240 if (PpiList != NULL) {
241 for (Index = 0;
242 (PpiList[Index].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
243 Index++) {
244 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&
245 (((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation != 0)
246 ) {
247 //
248 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.
249 //
250 FindAndReportEntryPoints (
251 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
252 (EFI_FIRMWARE_VOLUME_HEADER *) ((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation,
253 &PeiCoreEntryPoint
254 );
255 if (PeiCoreEntryPoint != NULL) {
256 break;
257 } else {
258 //
259 // PeiCore not found
260 //
261 CpuDeadLoop ();
262 }
263 }
264 }
265 }
266 //
267 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.
268 //
269 if (PeiCoreEntryPoint == NULL) {
270 //
271 // Both SecCore and PeiCore are in BFV.
272 //
273 FindAndReportEntryPoints (
274 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
275 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
276 &PeiCoreEntryPoint
277 );
278 if (PeiCoreEntryPoint == NULL) {
279 CpuDeadLoop ();
280 }
281 }
282
283 if (PpiList != NULL) {
284 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *) SecCoreData->PeiTemporaryRamBase;
285
286 //
287 // Remove the terminal flag from the terminal PPI
288 //
289 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
290 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;
291 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
292
293 //
294 // Append the platform additional PPI list
295 //
296 Index += 1;
297 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
298 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
299 Index++;
300 PpiList++;
301 }
302
303 //
304 // Add the terminal PPI
305 //
306 CopyMem (&AllSecPpiList[Index ++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
307
308 //
309 // Set PpiList to the total PPI
310 //
311 PpiList = AllSecPpiList;
312
313 //
314 // Adjust PEI TEMP RAM Range.
315 //
316 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
317 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
318 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);
319 //
320 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement
321 // will be built based on them in PEI phase.
322 //
323 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);
324 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;
325 } else {
326 //
327 // No addition PPI, PpiList directly point to the common PPI list.
328 //
329 PpiList = &mPeiSecPlatformInformationPpi[0];
330 }
331
332 DEBUG ((
333 DEBUG_INFO,
334 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
335 __FUNCTION__,
336 SecCoreData->StackBase,
337 (UINT32) SecCoreData->StackSize
338 ));
339
340 //
341 // Report Status Code to indicate transferring to PEI core
342 //
343 REPORT_STATUS_CODE (
344 EFI_PROGRESS_CODE,
345 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
346 );
347
348 //
349 // Transfer the control to the PEI core
350 //
351 ASSERT (PeiCoreEntryPoint != NULL);
352 (*PeiCoreEntryPoint) (SecCoreData, PpiList);
353
354 //
355 // Should not come here.
356 //
357 UNREACHABLE ();
358 }
359
360 /**
361 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
362 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
363
364 @retval EFI_SUCCESS Use of Temporary RAM was disabled.
365 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
366
367 **/
368 EFI_STATUS
369 EFIAPI
370 SecTemporaryRamDone (
371 VOID
372 )
373 {
374 BOOLEAN State;
375
376 //
377 // Republish Sec Platform Information(2) PPI
378 //
379 RepublishSecPlatformInformationPpi ();
380
381 //
382 // Migrate DebugAgentContext.
383 //
384 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
385
386 //
387 // Disable interrupts and save current interrupt state
388 //
389 State = SaveAndDisableInterrupts();
390
391 //
392 // Disable Temporary RAM after Stack and Heap have been migrated at this point.
393 //
394 SecPlatformDisableTemporaryMemory ();
395
396 //
397 // Restore original interrupt state
398 //
399 SetInterruptState (State);
400
401 return EFI_SUCCESS;
402 }