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