]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Cleanup debug messages
[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
208EFIAPI\r
209FindFfsFileAndSection (\r
210 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
211 IN EFI_FV_FILETYPE FileType,\r
212 IN EFI_SECTION_TYPE SectionType,\r
213 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
214 )\r
215{\r
216 EFI_STATUS Status;\r
217 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
218 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
219 EFI_FFS_FILE_HEADER *File;\r
220 UINT32 Size;\r
221 EFI_PHYSICAL_ADDRESS EndOfFile;\r
222\r
223 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
c67178b7 224 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
bb4aa855
JJ
225 return EFI_VOLUME_CORRUPTED;\r
226 }\r
227\r
228 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
229 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
230\r
231 //\r
232 // Loop through the FFS files in the Boot Firmware Volume\r
233 //\r
234 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
235\r
236 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
237 if (CurrentAddress > EndOfFirmwareVolume) {\r
238 return EFI_VOLUME_CORRUPTED;\r
239 }\r
240\r
241 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
242 Size = *(UINT32*) File->Size & 0xffffff;\r
243 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
244 return EFI_VOLUME_CORRUPTED;\r
245 }\r
bb4aa855
JJ
246\r
247 EndOfFile = CurrentAddress + Size;\r
248 if (EndOfFile > EndOfFirmwareVolume) {\r
249 return EFI_VOLUME_CORRUPTED;\r
250 }\r
251\r
252 //\r
253 // Look for the request file type\r
254 //\r
255 if (File->Type != FileType) {\r
bb4aa855
JJ
256 continue;\r
257 }\r
258\r
259 Status = FindFfsSectionInSections (\r
260 (VOID*) (File + 1),\r
261 (UINTN) EndOfFile - (UINTN) (File + 1),\r
262 SectionType,\r
263 FoundSection\r
264 );\r
265 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
266 return Status;\r
267 }\r
268 }\r
269}\r
270\r
271/**\r
272 Locates the compressed main firmware volume and decompresses it.\r
273\r
274 @param[in,out] Fv On input, the firmware volume to search\r
275 On output, the decompressed main FV\r
276\r
277 @retval EFI_SUCCESS The file and section was found\r
278 @retval EFI_NOT_FOUND The file and section was not found\r
279 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
280\r
281**/\r
282EFI_STATUS\r
283EFIAPI\r
284DecompressGuidedFv (\r
285 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
286 )\r
287{\r
288 EFI_STATUS Status;\r
289 EFI_GUID_DEFINED_SECTION *Section;\r
290 UINT32 OutputBufferSize;\r
291 UINT32 ScratchBufferSize;\r
292 UINT16 SectionAttribute;\r
293 UINT32 AuthenticationStatus;\r
294 VOID *OutputBuffer;\r
295 VOID *ScratchBuffer;\r
296 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;\r
297 EFI_FIRMWARE_VOLUME_HEADER *NewFv;\r
298\r
299 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
300\r
301 Status = FindFfsFileAndSection (\r
302 *Fv,\r
303 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
304 EFI_SECTION_GUID_DEFINED,\r
305 (EFI_COMMON_SECTION_HEADER**) &Section\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
309 return Status;\r
310 }\r
311\r
312 Status = ExtractGuidedSectionGetInfo (\r
313 Section,\r
314 &OutputBufferSize,\r
315 &ScratchBufferSize,\r
316 &SectionAttribute\r
317 );\r
318 if (EFI_ERROR (Status)) {\r
319 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
320 return Status;\r
321 }\r
322\r
323 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)\r
324 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);\r
325 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
326 Status = ExtractGuidedSectionDecode (\r
327 Section,\r
328 &OutputBuffer,\r
329 ScratchBuffer,\r
330 &AuthenticationStatus\r
331 );\r
332 if (EFI_ERROR (Status)) {\r
333 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
334 return Status;\r
335 }\r
336\r
337 Status = FindFfsSectionInSections (\r
338 OutputBuffer,\r
339 OutputBufferSize,\r
340 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
341 (EFI_COMMON_SECTION_HEADER**) &NewFvSection\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));\r
345 return Status;\r
346 }\r
347\r
348 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);\r
349 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));\r
350\r
351 if (NewFv->Signature != EFI_FVH_SIGNATURE) {\r
352 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));\r
353 CpuDeadLoop ();\r
354 return EFI_VOLUME_CORRUPTED;\r
355 }\r
356\r
357 *Fv = NewFv;\r
358 return EFI_SUCCESS;\r
359}\r
360\r
361/**\r
362 Locates the PEI Core entry point address\r
363\r
364 @param[in] Fv The firmware volume to search\r
365 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
366\r
367 @retval EFI_SUCCESS The file and section was found\r
368 @retval EFI_NOT_FOUND The file and section was not found\r
369 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
370\r
371**/\r
372EFI_STATUS\r
373EFIAPI\r
374FindPeiCoreImageBaseInFv (\r
375 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
376 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
377 )\r
378{\r
379 EFI_STATUS Status;\r
380 EFI_COMMON_SECTION_HEADER *Section;\r
381\r
382 Status = FindFfsFileAndSection (\r
383 Fv,\r
384 EFI_FV_FILETYPE_PEI_CORE,\r
385 EFI_SECTION_PE32,\r
386 &Section\r
387 );\r
388 if (EFI_ERROR (Status)) {\r
389 Status = FindFfsFileAndSection (\r
390 Fv,\r
391 EFI_FV_FILETYPE_PEI_CORE,\r
392 EFI_SECTION_TE,\r
393 &Section\r
394 );\r
395 if (EFI_ERROR (Status)) {\r
396 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
397 return Status;\r
398 }\r
399 }\r
400\r
401 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
402 return EFI_SUCCESS;\r
403}\r
404\r
405/**\r
406 Locates the PEI Core entry point address\r
407\r
408 @param[in,out] Fv The firmware volume to search\r
409 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
410\r
411 @retval EFI_SUCCESS The file and section was found\r
412 @retval EFI_NOT_FOUND The file and section was not found\r
413 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
414\r
415**/\r
416VOID\r
417EFIAPI\r
418FindPeiCoreImageBase (\r
419 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
420 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
421 )\r
422{\r
423 *PeiCoreImageBase = 0;\r
424\r
425 FindMainFv (BootFv);\r
426\r
427 DecompressGuidedFv (BootFv);\r
428\r
429 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
430}\r
431\r
432/**\r
433 Find core image base.\r
434\r
435**/\r
436EFI_STATUS\r
437EFIAPI\r
438FindImageBase (\r
439 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
440 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
441 )\r
442{\r
443 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
444 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
445 EFI_FFS_FILE_HEADER *File;\r
446 UINT32 Size;\r
447 EFI_PHYSICAL_ADDRESS EndOfFile;\r
448 EFI_COMMON_SECTION_HEADER *Section;\r
449 EFI_PHYSICAL_ADDRESS EndOfSection;\r
450\r
451 *SecCoreImageBase = 0;\r
452\r
453 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
454 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
455\r
456 //\r
457 // Loop through the FFS files in the Boot Firmware Volume\r
458 //\r
459 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
460\r
461 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
462 if (CurrentAddress > EndOfFirmwareVolume) {\r
463 return EFI_NOT_FOUND;\r
464 }\r
465\r
466 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
467 Size = *(UINT32*) File->Size & 0xffffff;\r
468 if (Size < sizeof (*File)) {\r
469 return EFI_NOT_FOUND;\r
470 }\r
471\r
472 EndOfFile = CurrentAddress + Size;\r
473 if (EndOfFile > EndOfFirmwareVolume) {\r
474 return EFI_NOT_FOUND;\r
475 }\r
476\r
477 //\r
478 // Look for SEC Core\r
479 //\r
480 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
481 continue;\r
482 }\r
483\r
484 //\r
485 // Loop through the FFS file sections within the FFS file\r
486 //\r
487 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
488 for (;;) {\r
489 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
490 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
491\r
492 Size = *(UINT32*) Section->Size & 0xffffff;\r
493 if (Size < sizeof (*Section)) {\r
494 return EFI_NOT_FOUND;\r
495 }\r
496\r
497 EndOfSection = CurrentAddress + Size;\r
498 if (EndOfSection > EndOfFile) {\r
499 return EFI_NOT_FOUND;\r
500 }\r
501\r
502 //\r
503 // Look for executable sections\r
504 //\r
505 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
506 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
507 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
508 }\r
509 break;\r
510 }\r
511 }\r
512\r
513 //\r
514 // SEC Core image found\r
515 //\r
516 if (*SecCoreImageBase != 0) {\r
517 return EFI_SUCCESS;\r
518 }\r
519 }\r
520}\r
521\r
522/*\r
523 Find and return Pei Core entry point.\r
524\r
525 It also find SEC and PEI Core file debug inforamtion. It will report them if\r
526 remote debug is enabled.\r
527\r
528**/\r
529VOID\r
530EFIAPI\r
531FindAndReportEntryPoints (\r
532 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
533 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
534 )\r
535{\r
536 EFI_STATUS Status;\r
537 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
538 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
539 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
540\r
541 //\r
542 // Find SEC Core and PEI Core image base\r
543 //\r
544 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
545 ASSERT_EFI_ERROR (Status);\r
546\r
547 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
548 \r
549 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
550 //\r
551 // Report SEC Core debug information when remote debug is enabled\r
552 //\r
553 ImageContext.ImageAddress = SecCoreImageBase;\r
554 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
555 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
556\r
557 //\r
558 // Report PEI Core debug information when remote debug is enabled\r
559 //\r
560 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
561 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
562 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
563\r
564 //\r
565 // Find PEI Core entry point\r
566 //\r
567 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
568 if (EFI_ERROR (Status)) {\r
569 *PeiCoreEntryPoint = 0;\r
570 }\r
571\r
572 return;\r
573}\r
574\r
575VOID\r
576EFIAPI\r
577SecCoreStartupWithStack (\r
578 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
579 IN VOID *TopOfCurrentStack\r
580 )\r
581{\r
582 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
583 SEC_IDT_TABLE IdtTableInStack;\r
584 IA32_DESCRIPTOR IdtDescriptor;\r
585 UINT32 Index;\r
586\r
587 ProcessLibraryConstructorList (NULL, NULL);\r
588\r
c67178b7 589 DEBUG ((EFI_D_INFO,\r
bb4aa855
JJ
590 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
591 (UINT32)(UINTN)BootFv,\r
592 (UINT32)(UINTN)TopOfCurrentStack\r
593 ));\r
594\r
595 //\r
596 // Initialize floating point operating environment\r
597 // to be compliant with UEFI spec.\r
598 //\r
599 InitializeFloatingPointUnits ();\r
600\r
601 //\r
602 // Initialize IDT\r
603 // \r
604 IdtTableInStack.PeiService = NULL;\r
605 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
606 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
607 }\r
608\r
609 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
610 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
611\r
612 AsmWriteIdtr (&IdtDescriptor);\r
613\r
b382ede3
JJ
614#if defined (MDE_CPU_X64)\r
615 //\r
616 // ASSERT that the Page Tables were set by the reset vector code to\r
617 // the address we expect.\r
618 //\r
619 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
620#endif\r
621\r
bb4aa855
JJ
622 //\r
623 // |-------------| <-- TopOfCurrentStack\r
624 // | Stack | 32k\r
625 // |-------------|\r
626 // | Heap | 32k\r
627 // |-------------| <-- SecCoreData.TemporaryRamBase\r
628 //\r
629\r
7cb6b0e0
JJ
630 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
631 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
632 (UINTN) TopOfCurrentStack);\r
633\r
bb4aa855
JJ
634 //\r
635 // Initialize SEC hand-off state\r
636 //\r
637 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
638\r
7cb6b0e0 639 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
640 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
641\r
642 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
643 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
644\r
645 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
646 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
647\r
648 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
649 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
650\r
651 //\r
652 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
653 //\r
654 IoWrite8 (0x21, 0xff);\r
655 IoWrite8 (0xA1, 0xff);\r
656 \r
657 //\r
658 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
659 //\r
660 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
661}\r
662 \r
663/**\r
664 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
665\r
666 Entry point to the C language phase of SEC. After the SEC assembly\r
667 code has initialized some temporary memory and set up the stack,\r
668 the control is transferred to this function.\r
669\r
670 @param[in] Context The first input parameter of InitializeDebugAgent().\r
671\r
672**/\r
673VOID\r
674EFIAPI\r
675SecStartupPhase2(\r
676 IN VOID *Context\r
677 )\r
678{\r
679 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
680 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
681 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
682 \r
683 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
684 \r
685 //\r
686 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
687 // is enabled.\r
688 //\r
689 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
690 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
691 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
692 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
693\r
694 //\r
695 // Transfer the control to the PEI core\r
696 //\r
697 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
698 \r
699 //\r
700 // If we get here then the PEI Core returned, which is not recoverable.\r
701 //\r
702 ASSERT (FALSE);\r
703 CpuDeadLoop ();\r
704}\r
705\r
706EFI_STATUS\r
707EFIAPI\r
708TemporaryRamMigration (\r
709 IN CONST EFI_PEI_SERVICES **PeiServices,\r
710 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
711 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
712 IN UINTN CopySize\r
713 )\r
714{\r
715 IA32_DESCRIPTOR IdtDescriptor;\r
716 VOID *OldHeap;\r
717 VOID *NewHeap;\r
718 VOID *OldStack;\r
719 VOID *NewStack;\r
720 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
721 BOOLEAN OldStatus;\r
722 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
723 \r
c67178b7
JJ
724 DEBUG ((EFI_D_INFO,\r
725 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
726 (UINTN) TemporaryMemoryBase,\r
727 (UINTN) PermanentMemoryBase,\r
728 CopySize\r
729 ));\r
bb4aa855
JJ
730 \r
731 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
732 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
733 \r
734 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
735 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
736\r
737 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
738 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
739 \r
740 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
741 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
742\r
743 //\r
744 // Migrate Heap\r
745 //\r
746 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
747\r
748 //\r
749 // Migrate Stack\r
750 //\r
751 CopyMem (NewStack, OldStack, CopySize >> 1);\r
752 \r
753 //\r
754 // Rebase IDT table in permanent memory\r
755 //\r
756 AsmReadIdtr (&IdtDescriptor);\r
757 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
758\r
759 AsmWriteIdtr (&IdtDescriptor);\r
760\r
761 //\r
762 // Use SetJump()/LongJump() to switch to a new stack.\r
763 // \r
764 if (SetJump (&JumpBuffer) == 0) {\r
765#if defined (MDE_CPU_IA32)\r
766 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
767#endif \r
768#if defined (MDE_CPU_X64)\r
769 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
770#endif \r
771 LongJump (&JumpBuffer, (UINTN)-1);\r
772 }\r
773\r
774 SaveAndSetDebugTimerInterrupt (OldStatus);\r
775\r
776 return EFI_SUCCESS;\r
777}\r
778\r