]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/SecCore/SecMain.c
BaseTools/Capsule: Do not support -o with --dump-info
[mirror_edk2.git] / UefiCpuPkg / SecCore / SecMain.c
1 /** @file
2 C functions in SEC
3
4 Copyright (c) 2008 - 2018, 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 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
236 AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *) SecCoreData->PeiTemporaryRamBase;
237 //
238 // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
239 // is enabled.
240 //
241 FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
242 if (PeiCoreEntryPoint == NULL)
243 {
244 CpuDeadLoop ();
245 }
246
247 //
248 // Perform platform specific initialization before entering PeiCore.
249 //
250 PpiList = SecPlatformMain (SecCoreData);
251 if (PpiList != NULL) {
252 //
253 // Remove the terminal flag from the terminal PPI
254 //
255 CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
256 Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;
257 AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
258
259 //
260 // Append the platform additional PPI list
261 //
262 Index += 1;
263 while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
264 CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
265 Index++;
266 PpiList++;
267 }
268
269 //
270 // Add the terminal PPI
271 //
272 CopyMem (&AllSecPpiList[Index ++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
273
274 //
275 // Set PpiList to the total PPI
276 //
277 PpiList = AllSecPpiList;
278
279 //
280 // Adjust PEI TEMP RAM Range.
281 //
282 ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
283 SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
284 SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);
285 //
286 // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement
287 // will be built based on them in PEI phase.
288 //
289 SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);
290 SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;
291 } else {
292 //
293 // No addition PPI, PpiList directly point to the common PPI list.
294 //
295 PpiList = &mPeiSecPlatformInformationPpi[0];
296 }
297
298 DEBUG ((
299 DEBUG_INFO,
300 "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
301 __FUNCTION__,
302 SecCoreData->StackBase,
303 (UINT32) SecCoreData->StackSize
304 ));
305
306 //
307 // Report Status Code to indicate transferring to PEI core
308 //
309 REPORT_STATUS_CODE (
310 EFI_PROGRESS_CODE,
311 EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
312 );
313
314 //
315 // Transfer the control to the PEI core
316 //
317 ASSERT (PeiCoreEntryPoint != NULL);
318 (*PeiCoreEntryPoint) (SecCoreData, PpiList);
319
320 //
321 // Should not come here.
322 //
323 UNREACHABLE ();
324 }
325
326 /**
327 TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
328 by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
329
330 @retval EFI_SUCCESS Use of Temporary RAM was disabled.
331 @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
332
333 **/
334 EFI_STATUS
335 EFIAPI
336 SecTemporaryRamDone (
337 VOID
338 )
339 {
340 BOOLEAN State;
341
342 //
343 // Republish Sec Platform Information(2) PPI
344 //
345 RepublishSecPlatformInformationPpi ();
346
347 //
348 // Migrate DebugAgentContext.
349 //
350 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
351
352 //
353 // Disable interrupts and save current interrupt state
354 //
355 State = SaveAndDisableInterrupts();
356
357 //
358 // Disable Temporary RAM after Stack and Heap have been migrated at this point.
359 //
360 SecPlatformDisableTemporaryMemory ();
361
362 //
363 // Restore original interrupt state
364 //
365 SetInterruptState (State);
366
367 return EFI_SUCCESS;
368 }