]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Sec/SecMain.c
670ad8d763aab0dc3a5f8215ee57c96a3cf7c6dd
[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 /**
474 Reads 8-bits of CMOS data.
475
476 Reads the 8-bits of CMOS data at the location specified by Index.
477 The 8-bit read value is returned.
478
479 @param Index The CMOS location to read.
480
481 @return The value read.
482
483 **/
484 STATIC
485 UINT8
486 CmosRead8 (
487 IN UINTN Index
488 )
489 {
490 IoWrite8 (0x70, (UINT8) Index);
491 return IoRead8 (0x71);
492 }
493
494
495 STATIC
496 BOOLEAN
497 IsS3Resume (
498 VOID
499 )
500 {
501 return (CmosRead8 (0xF) == 0xFE);
502 }
503
504
505 STATIC
506 EFI_STATUS
507 GetS3ResumePeiFv (
508 IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv
509 )
510 {
511 *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);
512 return EFI_SUCCESS;
513 }
514
515
516 /**
517 Locates the PEI Core entry point address
518
519 @param[in,out] Fv The firmware volume to search
520 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
521
522 @retval EFI_SUCCESS The file and section was found
523 @retval EFI_NOT_FOUND The file and section was not found
524 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
525
526 **/
527 VOID
528 FindPeiCoreImageBase (
529 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
530 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
531 )
532 {
533 *PeiCoreImageBase = 0;
534
535 if (IsS3Resume ()) {
536 DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));
537 GetS3ResumePeiFv (BootFv);
538 } else {
539 DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n"));
540 FindMainFv (BootFv);
541
542 DecompressMemFvs (BootFv);
543 }
544
545 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
546 }
547
548 /**
549 Find core image base.
550
551 **/
552 EFI_STATUS
553 FindImageBase (
554 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
555 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
556 )
557 {
558 EFI_PHYSICAL_ADDRESS CurrentAddress;
559 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
560 EFI_FFS_FILE_HEADER *File;
561 UINT32 Size;
562 EFI_PHYSICAL_ADDRESS EndOfFile;
563 EFI_COMMON_SECTION_HEADER *Section;
564 EFI_PHYSICAL_ADDRESS EndOfSection;
565
566 *SecCoreImageBase = 0;
567
568 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
569 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
570
571 //
572 // Loop through the FFS files in the Boot Firmware Volume
573 //
574 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
575
576 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
577 if (CurrentAddress > EndOfFirmwareVolume) {
578 return EFI_NOT_FOUND;
579 }
580
581 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
582 Size = *(UINT32*) File->Size & 0xffffff;
583 if (Size < sizeof (*File)) {
584 return EFI_NOT_FOUND;
585 }
586
587 EndOfFile = CurrentAddress + Size;
588 if (EndOfFile > EndOfFirmwareVolume) {
589 return EFI_NOT_FOUND;
590 }
591
592 //
593 // Look for SEC Core
594 //
595 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
596 continue;
597 }
598
599 //
600 // Loop through the FFS file sections within the FFS file
601 //
602 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
603 for (;;) {
604 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
605 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
606
607 Size = *(UINT32*) Section->Size & 0xffffff;
608 if (Size < sizeof (*Section)) {
609 return EFI_NOT_FOUND;
610 }
611
612 EndOfSection = CurrentAddress + Size;
613 if (EndOfSection > EndOfFile) {
614 return EFI_NOT_FOUND;
615 }
616
617 //
618 // Look for executable sections
619 //
620 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
621 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
622 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
623 }
624 break;
625 }
626 }
627
628 //
629 // SEC Core image found
630 //
631 if (*SecCoreImageBase != 0) {
632 return EFI_SUCCESS;
633 }
634 }
635 }
636
637 /*
638 Find and return Pei Core entry point.
639
640 It also find SEC and PEI Core file debug inforamtion. It will report them if
641 remote debug is enabled.
642
643 **/
644 VOID
645 FindAndReportEntryPoints (
646 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
647 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
648 )
649 {
650 EFI_STATUS Status;
651 EFI_PHYSICAL_ADDRESS SecCoreImageBase;
652 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
653 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
654
655 //
656 // Find SEC Core and PEI Core image base
657 //
658 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
659 ASSERT_EFI_ERROR (Status);
660
661 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
662
663 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
664 //
665 // Report SEC Core debug information when remote debug is enabled
666 //
667 ImageContext.ImageAddress = SecCoreImageBase;
668 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
669 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
670
671 //
672 // Report PEI Core debug information when remote debug is enabled
673 //
674 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
675 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
676 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
677
678 //
679 // Find PEI Core entry point
680 //
681 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
682 if (EFI_ERROR (Status)) {
683 *PeiCoreEntryPoint = 0;
684 }
685
686 return;
687 }
688
689 VOID
690 EFIAPI
691 SecCoreStartupWithStack (
692 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
693 IN VOID *TopOfCurrentStack
694 )
695 {
696 EFI_SEC_PEI_HAND_OFF SecCoreData;
697 SEC_IDT_TABLE IdtTableInStack;
698 IA32_DESCRIPTOR IdtDescriptor;
699 UINT32 Index;
700
701 ProcessLibraryConstructorList (NULL, NULL);
702
703 DEBUG ((EFI_D_INFO,
704 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
705 (UINT32)(UINTN)BootFv,
706 (UINT32)(UINTN)TopOfCurrentStack
707 ));
708
709 //
710 // Initialize floating point operating environment
711 // to be compliant with UEFI spec.
712 //
713 InitializeFloatingPointUnits ();
714
715 //
716 // Initialize IDT
717 //
718 IdtTableInStack.PeiService = NULL;
719 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
720 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
721 }
722
723 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
724 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
725
726 AsmWriteIdtr (&IdtDescriptor);
727
728 #if defined (MDE_CPU_X64)
729 //
730 // ASSERT that the Page Tables were set by the reset vector code to
731 // the address we expect.
732 //
733 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));
734 #endif
735
736 //
737 // |-------------| <-- TopOfCurrentStack
738 // | Stack | 32k
739 // |-------------|
740 // | Heap | 32k
741 // |-------------| <-- SecCoreData.TemporaryRamBase
742 //
743
744 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +
745 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
746 (UINTN) TopOfCurrentStack);
747
748 //
749 // Initialize SEC hand-off state
750 //
751 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
752
753 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);
754 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
755
756 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
757 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
758
759 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
760 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
761
762 SecCoreData.BootFirmwareVolumeBase = BootFv;
763 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
764
765 //
766 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
767 //
768 IoWrite8 (0x21, 0xff);
769 IoWrite8 (0xA1, 0xff);
770
771 //
772 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
773 //
774 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
775 }
776
777 /**
778 Caller provided function to be invoked at the end of InitializeDebugAgent().
779
780 Entry point to the C language phase of SEC. After the SEC assembly
781 code has initialized some temporary memory and set up the stack,
782 the control is transferred to this function.
783
784 @param[in] Context The first input parameter of InitializeDebugAgent().
785
786 **/
787 VOID
788 EFIAPI
789 SecStartupPhase2(
790 IN VOID *Context
791 )
792 {
793 EFI_SEC_PEI_HAND_OFF *SecCoreData;
794 EFI_FIRMWARE_VOLUME_HEADER *BootFv;
795 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
796
797 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
798
799 //
800 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
801 // is enabled.
802 //
803 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
804 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
805 SecCoreData->BootFirmwareVolumeBase = BootFv;
806 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
807
808 //
809 // Transfer the control to the PEI core
810 //
811 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
812
813 //
814 // If we get here then the PEI Core returned, which is not recoverable.
815 //
816 ASSERT (FALSE);
817 CpuDeadLoop ();
818 }
819
820 EFI_STATUS
821 EFIAPI
822 TemporaryRamMigration (
823 IN CONST EFI_PEI_SERVICES **PeiServices,
824 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
825 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
826 IN UINTN CopySize
827 )
828 {
829 IA32_DESCRIPTOR IdtDescriptor;
830 VOID *OldHeap;
831 VOID *NewHeap;
832 VOID *OldStack;
833 VOID *NewStack;
834 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
835 BOOLEAN OldStatus;
836 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
837
838 DEBUG ((EFI_D_INFO,
839 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",
840 (UINTN) TemporaryMemoryBase,
841 (UINTN) PermanentMemoryBase,
842 CopySize
843 ));
844
845 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
846 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
847
848 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
849 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
850
851 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
852 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
853
854 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
855 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
856
857 //
858 // Migrate Heap
859 //
860 CopyMem (NewHeap, OldHeap, CopySize >> 1);
861
862 //
863 // Migrate Stack
864 //
865 CopyMem (NewStack, OldStack, CopySize >> 1);
866
867 //
868 // Rebase IDT table in permanent memory
869 //
870 AsmReadIdtr (&IdtDescriptor);
871 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
872
873 AsmWriteIdtr (&IdtDescriptor);
874
875 //
876 // Use SetJump()/LongJump() to switch to a new stack.
877 //
878 if (SetJump (&JumpBuffer) == 0) {
879 #if defined (MDE_CPU_IA32)
880 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
881 #endif
882 #if defined (MDE_CPU_X64)
883 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
884 #endif
885 LongJump (&JumpBuffer, (UINTN)-1);
886 }
887
888 SaveAndSetDebugTimerInterrupt (OldStatus);
889
890 return EFI_SUCCESS;
891 }
892