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