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