]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Remove EFIAPI from functions that don't require it
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
bb4aa855
JJ
1/** @file\r
2 Main SEC phase code. Transitions to PEI.\r
3\r
c67178b7 4 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
bb4aa855
JJ
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <PiPei.h>\r
17\r
18#include <Library/PeimEntryPoint.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/PeiServicesLib.h>\r
23#include <Library/PcdLib.h>\r
24#include <Library/UefiCpuLib.h>\r
25#include <Library/DebugAgentLib.h>\r
26#include <Library/IoLib.h>\r
27#include <Library/PeCoffLib.h>\r
28#include <Library/PeCoffGetEntryPointLib.h>\r
29#include <Library/PeCoffExtraActionLib.h>\r
30#include <Library/ExtractGuidedSectionLib.h>\r
31\r
32#include <Ppi/TemporaryRamSupport.h>\r
33\r
34#define SEC_IDT_ENTRY_COUNT 34\r
35\r
36typedef struct _SEC_IDT_TABLE {\r
37 EFI_PEI_SERVICES *PeiService;\r
38 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];\r
39} SEC_IDT_TABLE;\r
40\r
41VOID\r
42EFIAPI\r
43SecStartupPhase2 (\r
44 IN VOID *Context\r
45 );\r
46\r
47EFI_STATUS\r
48EFIAPI\r
49TemporaryRamMigration (\r
50 IN CONST EFI_PEI_SERVICES **PeiServices,\r
51 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
52 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
53 IN UINTN CopySize\r
54 );\r
55\r
56//\r
57//\r
58// \r
59EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {\r
60 TemporaryRamMigration\r
61};\r
62\r
63EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {\r
64 {\r
65 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
66 &gEfiTemporaryRamSupportPpiGuid,\r
67 &mTemporaryRamSupportPpi\r
68 },\r
69};\r
70\r
71//\r
72// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
73//\r
74IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {\r
75 { // Bits\r
76 0xffe4, // OffsetLow\r
77 0x10, // Selector\r
78 0x0, // Reserved_0\r
79 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType\r
80 0xffff // OffsetHigh\r
81 } \r
82};\r
83\r
84/**\r
85 Locates the main boot firmware volume.\r
86\r
87 @param[in,out] BootFv On input, the base of the BootFv\r
88 On output, the decompressed main firmware volume\r
89\r
90 @retval EFI_SUCCESS The main firmware volume was located and decompressed\r
91 @retval EFI_NOT_FOUND The main firmware volume was not found\r
92\r
93**/\r
94EFI_STATUS\r
95FindMainFv (\r
96 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv\r
97 )\r
98{\r
99 EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
100 UINTN Distance;\r
101\r
102 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);\r
103\r
104 Fv = *BootFv;\r
105 Distance = (UINTN) (*BootFv)->FvLength;\r
106 do {\r
107 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);\r
108 Distance += EFI_PAGE_SIZE;\r
109 if (Distance > SIZE_32MB) {\r
110 return EFI_NOT_FOUND;\r
111 }\r
112\r
113 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
114 continue;\r
115 }\r
116\r
117 if ((UINTN) Fv->FvLength > Distance) {\r
118 continue;\r
119 }\r
120\r
121 *BootFv = Fv;\r
122 return EFI_SUCCESS;\r
123\r
124 } while (TRUE);\r
125}\r
126\r
127/**\r
128 Locates a section within a series of sections\r
129 with the specified section type.\r
130\r
131 @param[in] Sections The sections to search\r
132 @param[in] SizeOfSections Total size of all sections\r
133 @param[in] SectionType The section type to locate\r
134 @param[out] FoundSection The FFS section if found\r
135\r
136 @retval EFI_SUCCESS The file and section was found\r
137 @retval EFI_NOT_FOUND The file and section was not found\r
138 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
139\r
140**/\r
141EFI_STATUS\r
142FindFfsSectionInSections (\r
143 IN VOID *Sections,\r
144 IN UINTN SizeOfSections,\r
145 IN EFI_SECTION_TYPE SectionType,\r
146 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
147 )\r
148{\r
149 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
150 UINT32 Size;\r
151 EFI_PHYSICAL_ADDRESS EndOfSections;\r
152 EFI_COMMON_SECTION_HEADER *Section;\r
153 EFI_PHYSICAL_ADDRESS EndOfSection;\r
154\r
155 //\r
156 // Loop through the FFS file sections within the PEI Core FFS file\r
157 //\r
158 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;\r
159 EndOfSections = EndOfSection + SizeOfSections;\r
160 for (;;) {\r
161 if (EndOfSection == EndOfSections) {\r
162 break;\r
163 }\r
164 CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
165 if (CurrentAddress >= EndOfSections) {\r
166 return EFI_VOLUME_CORRUPTED;\r
167 }\r
168\r
169 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
bb4aa855
JJ
170\r
171 Size = SECTION_SIZE (Section);\r
172 if (Size < sizeof (*Section)) {\r
173 return EFI_VOLUME_CORRUPTED;\r
174 }\r
175\r
176 EndOfSection = CurrentAddress + Size;\r
177 if (EndOfSection > EndOfSections) {\r
178 return EFI_VOLUME_CORRUPTED;\r
179 }\r
180\r
181 //\r
182 // Look for the requested section type\r
183 //\r
184 if (Section->Type == SectionType) {\r
185 *FoundSection = Section;\r
186 return EFI_SUCCESS;\r
187 }\r
bb4aa855
JJ
188 }\r
189\r
190 return EFI_NOT_FOUND;\r
191}\r
192\r
193/**\r
194 Locates a FFS file with the specified file type and a section\r
195 within that file with the specified section type.\r
196\r
197 @param[in] Fv The firmware volume to search\r
198 @param[in] FileType The file type to locate\r
199 @param[in] SectionType The section type to locate\r
200 @param[out] FoundSection The FFS section if found\r
201\r
202 @retval EFI_SUCCESS The file and section was found\r
203 @retval EFI_NOT_FOUND The file and section was not found\r
204 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
205\r
206**/\r
207EFI_STATUS\r
bb4aa855
JJ
208FindFfsFileAndSection (\r
209 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
210 IN EFI_FV_FILETYPE FileType,\r
211 IN EFI_SECTION_TYPE SectionType,\r
212 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
217 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
218 EFI_FFS_FILE_HEADER *File;\r
219 UINT32 Size;\r
220 EFI_PHYSICAL_ADDRESS EndOfFile;\r
221\r
222 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
c67178b7 223 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
bb4aa855
JJ
224 return EFI_VOLUME_CORRUPTED;\r
225 }\r
226\r
227 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
228 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
229\r
230 //\r
231 // Loop through the FFS files in the Boot Firmware Volume\r
232 //\r
233 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
234\r
235 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
236 if (CurrentAddress > EndOfFirmwareVolume) {\r
237 return EFI_VOLUME_CORRUPTED;\r
238 }\r
239\r
240 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
241 Size = *(UINT32*) File->Size & 0xffffff;\r
242 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
243 return EFI_VOLUME_CORRUPTED;\r
244 }\r
bb4aa855
JJ
245\r
246 EndOfFile = CurrentAddress + Size;\r
247 if (EndOfFile > EndOfFirmwareVolume) {\r
248 return EFI_VOLUME_CORRUPTED;\r
249 }\r
250\r
251 //\r
252 // Look for the request file type\r
253 //\r
254 if (File->Type != FileType) {\r
bb4aa855
JJ
255 continue;\r
256 }\r
257\r
258 Status = FindFfsSectionInSections (\r
259 (VOID*) (File + 1),\r
260 (UINTN) EndOfFile - (UINTN) (File + 1),\r
261 SectionType,\r
262 FoundSection\r
263 );\r
264 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
265 return Status;\r
266 }\r
267 }\r
268}\r
269\r
270/**\r
271 Locates the compressed main firmware volume and decompresses it.\r
272\r
273 @param[in,out] Fv On input, the firmware volume to search\r
274 On output, the decompressed main FV\r
275\r
276 @retval EFI_SUCCESS The file and section was found\r
277 @retval EFI_NOT_FOUND The file and section was not found\r
278 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
279\r
280**/\r
281EFI_STATUS\r
bb4aa855
JJ
282DecompressGuidedFv (\r
283 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
284 )\r
285{\r
286 EFI_STATUS Status;\r
287 EFI_GUID_DEFINED_SECTION *Section;\r
288 UINT32 OutputBufferSize;\r
289 UINT32 ScratchBufferSize;\r
290 UINT16 SectionAttribute;\r
291 UINT32 AuthenticationStatus;\r
292 VOID *OutputBuffer;\r
293 VOID *ScratchBuffer;\r
294 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;\r
295 EFI_FIRMWARE_VOLUME_HEADER *NewFv;\r
296\r
297 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
298\r
299 Status = FindFfsFileAndSection (\r
300 *Fv,\r
301 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
302 EFI_SECTION_GUID_DEFINED,\r
303 (EFI_COMMON_SECTION_HEADER**) &Section\r
304 );\r
305 if (EFI_ERROR (Status)) {\r
306 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
307 return Status;\r
308 }\r
309\r
310 Status = ExtractGuidedSectionGetInfo (\r
311 Section,\r
312 &OutputBufferSize,\r
313 &ScratchBufferSize,\r
314 &SectionAttribute\r
315 );\r
316 if (EFI_ERROR (Status)) {\r
317 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
318 return Status;\r
319 }\r
320\r
321 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)\r
322 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);\r
323 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
324 Status = ExtractGuidedSectionDecode (\r
325 Section,\r
326 &OutputBuffer,\r
327 ScratchBuffer,\r
328 &AuthenticationStatus\r
329 );\r
330 if (EFI_ERROR (Status)) {\r
331 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
332 return Status;\r
333 }\r
334\r
335 Status = FindFfsSectionInSections (\r
336 OutputBuffer,\r
337 OutputBufferSize,\r
338 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
339 (EFI_COMMON_SECTION_HEADER**) &NewFvSection\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));\r
343 return Status;\r
344 }\r
345\r
346 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);\r
347 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));\r
348\r
349 if (NewFv->Signature != EFI_FVH_SIGNATURE) {\r
350 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));\r
351 CpuDeadLoop ();\r
352 return EFI_VOLUME_CORRUPTED;\r
353 }\r
354\r
355 *Fv = NewFv;\r
356 return EFI_SUCCESS;\r
357}\r
358\r
359/**\r
360 Locates the PEI Core entry point address\r
361\r
362 @param[in] Fv The firmware volume to search\r
363 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
364\r
365 @retval EFI_SUCCESS The file and section was found\r
366 @retval EFI_NOT_FOUND The file and section was not found\r
367 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
368\r
369**/\r
370EFI_STATUS\r
bb4aa855
JJ
371FindPeiCoreImageBaseInFv (\r
372 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
373 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
374 )\r
375{\r
376 EFI_STATUS Status;\r
377 EFI_COMMON_SECTION_HEADER *Section;\r
378\r
379 Status = FindFfsFileAndSection (\r
380 Fv,\r
381 EFI_FV_FILETYPE_PEI_CORE,\r
382 EFI_SECTION_PE32,\r
383 &Section\r
384 );\r
385 if (EFI_ERROR (Status)) {\r
386 Status = FindFfsFileAndSection (\r
387 Fv,\r
388 EFI_FV_FILETYPE_PEI_CORE,\r
389 EFI_SECTION_TE,\r
390 &Section\r
391 );\r
392 if (EFI_ERROR (Status)) {\r
393 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
394 return Status;\r
395 }\r
396 }\r
397\r
398 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
399 return EFI_SUCCESS;\r
400}\r
401\r
402/**\r
403 Locates the PEI Core entry point address\r
404\r
405 @param[in,out] Fv The firmware volume to search\r
406 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
407\r
408 @retval EFI_SUCCESS The file and section was found\r
409 @retval EFI_NOT_FOUND The file and section was not found\r
410 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
411\r
412**/\r
413VOID\r
bb4aa855
JJ
414FindPeiCoreImageBase (\r
415 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
416 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
417 )\r
418{\r
419 *PeiCoreImageBase = 0;\r
420\r
421 FindMainFv (BootFv);\r
422\r
423 DecompressGuidedFv (BootFv);\r
424\r
425 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
426}\r
427\r
428/**\r
429 Find core image base.\r
430\r
431**/\r
432EFI_STATUS\r
bb4aa855
JJ
433FindImageBase (\r
434 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
435 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
436 )\r
437{\r
438 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
439 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
440 EFI_FFS_FILE_HEADER *File;\r
441 UINT32 Size;\r
442 EFI_PHYSICAL_ADDRESS EndOfFile;\r
443 EFI_COMMON_SECTION_HEADER *Section;\r
444 EFI_PHYSICAL_ADDRESS EndOfSection;\r
445\r
446 *SecCoreImageBase = 0;\r
447\r
448 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
449 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
450\r
451 //\r
452 // Loop through the FFS files in the Boot Firmware Volume\r
453 //\r
454 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
455\r
456 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
457 if (CurrentAddress > EndOfFirmwareVolume) {\r
458 return EFI_NOT_FOUND;\r
459 }\r
460\r
461 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
462 Size = *(UINT32*) File->Size & 0xffffff;\r
463 if (Size < sizeof (*File)) {\r
464 return EFI_NOT_FOUND;\r
465 }\r
466\r
467 EndOfFile = CurrentAddress + Size;\r
468 if (EndOfFile > EndOfFirmwareVolume) {\r
469 return EFI_NOT_FOUND;\r
470 }\r
471\r
472 //\r
473 // Look for SEC Core\r
474 //\r
475 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
476 continue;\r
477 }\r
478\r
479 //\r
480 // Loop through the FFS file sections within the FFS file\r
481 //\r
482 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
483 for (;;) {\r
484 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
485 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
486\r
487 Size = *(UINT32*) Section->Size & 0xffffff;\r
488 if (Size < sizeof (*Section)) {\r
489 return EFI_NOT_FOUND;\r
490 }\r
491\r
492 EndOfSection = CurrentAddress + Size;\r
493 if (EndOfSection > EndOfFile) {\r
494 return EFI_NOT_FOUND;\r
495 }\r
496\r
497 //\r
498 // Look for executable sections\r
499 //\r
500 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
501 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
502 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
503 }\r
504 break;\r
505 }\r
506 }\r
507\r
508 //\r
509 // SEC Core image found\r
510 //\r
511 if (*SecCoreImageBase != 0) {\r
512 return EFI_SUCCESS;\r
513 }\r
514 }\r
515}\r
516\r
517/*\r
518 Find and return Pei Core entry point.\r
519\r
520 It also find SEC and PEI Core file debug inforamtion. It will report them if\r
521 remote debug is enabled.\r
522\r
523**/\r
524VOID\r
bb4aa855
JJ
525FindAndReportEntryPoints (\r
526 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
527 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
528 )\r
529{\r
530 EFI_STATUS Status;\r
531 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
532 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
533 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
534\r
535 //\r
536 // Find SEC Core and PEI Core image base\r
537 //\r
538 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
539 ASSERT_EFI_ERROR (Status);\r
540\r
541 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
542 \r
543 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
544 //\r
545 // Report SEC Core debug information when remote debug is enabled\r
546 //\r
547 ImageContext.ImageAddress = SecCoreImageBase;\r
548 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
549 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
550\r
551 //\r
552 // Report PEI Core debug information when remote debug is enabled\r
553 //\r
554 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
555 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
556 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
557\r
558 //\r
559 // Find PEI Core entry point\r
560 //\r
561 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
562 if (EFI_ERROR (Status)) {\r
563 *PeiCoreEntryPoint = 0;\r
564 }\r
565\r
566 return;\r
567}\r
568\r
569VOID\r
570EFIAPI\r
571SecCoreStartupWithStack (\r
572 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
573 IN VOID *TopOfCurrentStack\r
574 )\r
575{\r
576 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
577 SEC_IDT_TABLE IdtTableInStack;\r
578 IA32_DESCRIPTOR IdtDescriptor;\r
579 UINT32 Index;\r
580\r
581 ProcessLibraryConstructorList (NULL, NULL);\r
582\r
c67178b7 583 DEBUG ((EFI_D_INFO,\r
bb4aa855
JJ
584 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
585 (UINT32)(UINTN)BootFv,\r
586 (UINT32)(UINTN)TopOfCurrentStack\r
587 ));\r
588\r
589 //\r
590 // Initialize floating point operating environment\r
591 // to be compliant with UEFI spec.\r
592 //\r
593 InitializeFloatingPointUnits ();\r
594\r
595 //\r
596 // Initialize IDT\r
597 // \r
598 IdtTableInStack.PeiService = NULL;\r
599 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
600 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
601 }\r
602\r
603 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
604 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
605\r
606 AsmWriteIdtr (&IdtDescriptor);\r
607\r
b382ede3
JJ
608#if defined (MDE_CPU_X64)\r
609 //\r
610 // ASSERT that the Page Tables were set by the reset vector code to\r
611 // the address we expect.\r
612 //\r
613 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
614#endif\r
615\r
bb4aa855
JJ
616 //\r
617 // |-------------| <-- TopOfCurrentStack\r
618 // | Stack | 32k\r
619 // |-------------|\r
620 // | Heap | 32k\r
621 // |-------------| <-- SecCoreData.TemporaryRamBase\r
622 //\r
623\r
7cb6b0e0
JJ
624 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
625 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
626 (UINTN) TopOfCurrentStack);\r
627\r
bb4aa855
JJ
628 //\r
629 // Initialize SEC hand-off state\r
630 //\r
631 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
632\r
7cb6b0e0 633 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
634 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
635\r
636 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
637 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
638\r
639 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
640 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
641\r
642 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
643 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
644\r
645 //\r
646 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
647 //\r
648 IoWrite8 (0x21, 0xff);\r
649 IoWrite8 (0xA1, 0xff);\r
650 \r
651 //\r
652 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
653 //\r
654 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
655}\r
656 \r
657/**\r
658 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
659\r
660 Entry point to the C language phase of SEC. After the SEC assembly\r
661 code has initialized some temporary memory and set up the stack,\r
662 the control is transferred to this function.\r
663\r
664 @param[in] Context The first input parameter of InitializeDebugAgent().\r
665\r
666**/\r
667VOID\r
668EFIAPI\r
669SecStartupPhase2(\r
670 IN VOID *Context\r
671 )\r
672{\r
673 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
674 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
675 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
676 \r
677 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
678 \r
679 //\r
680 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
681 // is enabled.\r
682 //\r
683 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
684 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
685 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
686 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
687\r
688 //\r
689 // Transfer the control to the PEI core\r
690 //\r
691 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
692 \r
693 //\r
694 // If we get here then the PEI Core returned, which is not recoverable.\r
695 //\r
696 ASSERT (FALSE);\r
697 CpuDeadLoop ();\r
698}\r
699\r
700EFI_STATUS\r
701EFIAPI\r
702TemporaryRamMigration (\r
703 IN CONST EFI_PEI_SERVICES **PeiServices,\r
704 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
705 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
706 IN UINTN CopySize\r
707 )\r
708{\r
709 IA32_DESCRIPTOR IdtDescriptor;\r
710 VOID *OldHeap;\r
711 VOID *NewHeap;\r
712 VOID *OldStack;\r
713 VOID *NewStack;\r
714 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
715 BOOLEAN OldStatus;\r
716 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
717 \r
c67178b7
JJ
718 DEBUG ((EFI_D_INFO,\r
719 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
720 (UINTN) TemporaryMemoryBase,\r
721 (UINTN) PermanentMemoryBase,\r
722 CopySize\r
723 ));\r
bb4aa855
JJ
724 \r
725 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
726 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
727 \r
728 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
729 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
730\r
731 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
732 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
733 \r
734 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
735 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
736\r
737 //\r
738 // Migrate Heap\r
739 //\r
740 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
741\r
742 //\r
743 // Migrate Stack\r
744 //\r
745 CopyMem (NewStack, OldStack, CopySize >> 1);\r
746 \r
747 //\r
748 // Rebase IDT table in permanent memory\r
749 //\r
750 AsmReadIdtr (&IdtDescriptor);\r
751 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
752\r
753 AsmWriteIdtr (&IdtDescriptor);\r
754\r
755 //\r
756 // Use SetJump()/LongJump() to switch to a new stack.\r
757 // \r
758 if (SetJump (&JumpBuffer) == 0) {\r
759#if defined (MDE_CPU_IA32)\r
760 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
761#endif \r
762#if defined (MDE_CPU_X64)\r
763 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
764#endif \r
765 LongJump (&JumpBuffer, (UINTN)-1);\r
766 }\r
767\r
768 SaveAndSetDebugTimerInterrupt (OldStatus);\r
769\r
770 return EFI_SUCCESS;\r
771}\r
772\r