]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/SecCore/SecMain.c
5d5e7f17dced59c9f2253d7b2b14d53cf7784d42
[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 Index = 0;
242 do {
243 if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&
244 (((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation != 0)
245 ) {
246 //
247 // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.
248 //
249 FindAndReportEntryPoints (
250 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
251 (EFI_FIRMWARE_VOLUME_HEADER *) ((EFI_PEI_CORE_FV_LOCATION_PPI *) PpiList[Index].Ppi)->PeiCoreFvLocation,
252 &PeiCoreEntryPoint
253 );
254 if (PeiCoreEntryPoint != NULL) {
255 break;
256 } else {
257 //
258 // Invalid PeiCore FV provided by platform
259 //
260 CpuDeadLoop ();
261 }
262 }
263 } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
264 }
265 //
266 // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.
267 //
268 if (PeiCoreEntryPoint == NULL) {
269 //
270 // Both SecCore and PeiCore are in BFV.
271 //
272 FindAndReportEntryPoints (
273 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
274 (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase,
275 &PeiCoreEntryPoint
276 );
277 if (PeiCoreEntryPoint == NULL) {
278 CpuDeadLoop ();
279 }
280 }
281
282 if (PpiList != NULL) {
283 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *) SecCoreData->PeiTemporaryRamBase;
284
285 //
286 // Remove the terminal flag from the terminal PPI
287 //
288 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
289 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;
290 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
291
292 //
293 // Append the platform additional PPI list
294 //
295 Index += 1;
296 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
297 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
298 Index++;
299 PpiList++;
300 }
301
302 //
303 // Add the terminal PPI
304 //
305 CopyMem (&AllSecPpiList[Index ++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
306
307 //
308 // Set PpiList to the total PPI
309 //
310 PpiList = AllSecPpiList;
311
312 //
313 // Adjust PEI TEMP RAM Range.
314 //
315 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
316 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
317 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);
318 //
319 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement
320 // will be built based on them in PEI phase.
321 //
322 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);
323 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;
324 } else {
325 //
326 // No addition PPI, PpiList directly point to the common PPI list.
327 //
328 PpiList = &mPeiSecPlatformInformationPpi[0];
329 }
330
331 DEBUG ((
332 DEBUG_INFO,
333 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
334 __FUNCTION__,
335 SecCoreData->StackBase,
336 (UINT32) SecCoreData->StackSize
337 ));
338
339 //
340 // Report Status Code to indicate transferring to PEI core
341 //
342 REPORT_STATUS_CODE (
343 EFI_PROGRESS_CODE,
344 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
345 );
346
347 //
348 // Transfer the control to the PEI core
349 //
350 ASSERT (PeiCoreEntryPoint != NULL);
351 (*PeiCoreEntryPoint) (SecCoreData, PpiList);
352
353 //
354 // Should not come here.
355 //
356 UNREACHABLE ();
357 }
358
359 /**
360 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
361 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
362
363 @retval EFI_SUCCESS Use of Temporary RAM was disabled.
364 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
365
366 **/
367 EFI_STATUS
368 EFIAPI
369 SecTemporaryRamDone (
370 VOID
371 )
372 {
373 BOOLEAN State;
374
375 //
376 // Republish Sec Platform Information(2) PPI
377 //
378 RepublishSecPlatformInformationPpi ();
379
380 //
381 // Migrate DebugAgentContext.
382 //
383 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
384
385 //
386 // Disable interrupts and save current interrupt state
387 //
388 State = SaveAndDisableInterrupts();
389
390 //
391 // Disable Temporary RAM after Stack and Heap have been migrated at this point.
392 //
393 SecPlatformDisableTemporaryMemory ();
394
395 //
396 // Restore original interrupt state
397 //
398 SetInterruptState (State);
399
400 return EFI_SUCCESS;
401 }