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