]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Add FindFfsSectionInstance
[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 main 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 DecompressGuidedFv (
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 *NewFvSection;
335 EFI_FIRMWARE_VOLUME_HEADER *NewFv;
336
337 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;
338
339 Status = FindFfsFileAndSection (
340 *Fv,
341 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
342 EFI_SECTION_GUID_DEFINED,
343 (EFI_COMMON_SECTION_HEADER**) &Section
344 );
345 if (EFI_ERROR (Status)) {
346 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
347 return Status;
348 }
349
350 Status = ExtractGuidedSectionGetInfo (
351 Section,
352 &OutputBufferSize,
353 &ScratchBufferSize,
354 &SectionAttribute
355 );
356 if (EFI_ERROR (Status)) {
357 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
358 return Status;
359 }
360
361 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)
362 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + 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 = FindFfsSectionInSections (
376 OutputBuffer,
377 OutputBufferSize,
378 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
379 (EFI_COMMON_SECTION_HEADER**) &NewFvSection
380 );
381 if (EFI_ERROR (Status)) {
382 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));
383 return Status;
384 }
385
386 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);
387 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));
388
389 if (NewFv->Signature != EFI_FVH_SIGNATURE) {
390 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));
391 CpuDeadLoop ();
392 return EFI_VOLUME_CORRUPTED;
393 }
394
395 *Fv = NewFv;
396 return EFI_SUCCESS;
397 }
398
399 /**
400 Locates the PEI Core entry point address
401
402 @param[in] Fv The firmware volume to search
403 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
404
405 @retval EFI_SUCCESS The file and section was found
406 @retval EFI_NOT_FOUND The file and section was not found
407 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
408
409 **/
410 EFI_STATUS
411 FindPeiCoreImageBaseInFv (
412 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
413 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
414 )
415 {
416 EFI_STATUS Status;
417 EFI_COMMON_SECTION_HEADER *Section;
418
419 Status = FindFfsFileAndSection (
420 Fv,
421 EFI_FV_FILETYPE_PEI_CORE,
422 EFI_SECTION_PE32,
423 &Section
424 );
425 if (EFI_ERROR (Status)) {
426 Status = FindFfsFileAndSection (
427 Fv,
428 EFI_FV_FILETYPE_PEI_CORE,
429 EFI_SECTION_TE,
430 &Section
431 );
432 if (EFI_ERROR (Status)) {
433 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
434 return Status;
435 }
436 }
437
438 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
439 return EFI_SUCCESS;
440 }
441
442 /**
443 Locates the PEI Core entry point address
444
445 @param[in,out] Fv The firmware volume to search
446 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
447
448 @retval EFI_SUCCESS The file and section was found
449 @retval EFI_NOT_FOUND The file and section was not found
450 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
451
452 **/
453 VOID
454 FindPeiCoreImageBase (
455 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
456 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
457 )
458 {
459 *PeiCoreImageBase = 0;
460
461 FindMainFv (BootFv);
462
463 DecompressGuidedFv (BootFv);
464
465 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
466 }
467
468 /**
469 Find core image base.
470
471 **/
472 EFI_STATUS
473 FindImageBase (
474 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
475 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
476 )
477 {
478 EFI_PHYSICAL_ADDRESS CurrentAddress;
479 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
480 EFI_FFS_FILE_HEADER *File;
481 UINT32 Size;
482 EFI_PHYSICAL_ADDRESS EndOfFile;
483 EFI_COMMON_SECTION_HEADER *Section;
484 EFI_PHYSICAL_ADDRESS EndOfSection;
485
486 *SecCoreImageBase = 0;
487
488 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
489 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
490
491 //
492 // Loop through the FFS files in the Boot Firmware Volume
493 //
494 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
495
496 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
497 if (CurrentAddress > EndOfFirmwareVolume) {
498 return EFI_NOT_FOUND;
499 }
500
501 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
502 Size = *(UINT32*) File->Size & 0xffffff;
503 if (Size < sizeof (*File)) {
504 return EFI_NOT_FOUND;
505 }
506
507 EndOfFile = CurrentAddress + Size;
508 if (EndOfFile > EndOfFirmwareVolume) {
509 return EFI_NOT_FOUND;
510 }
511
512 //
513 // Look for SEC Core
514 //
515 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
516 continue;
517 }
518
519 //
520 // Loop through the FFS file sections within the FFS file
521 //
522 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
523 for (;;) {
524 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
525 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
526
527 Size = *(UINT32*) Section->Size & 0xffffff;
528 if (Size < sizeof (*Section)) {
529 return EFI_NOT_FOUND;
530 }
531
532 EndOfSection = CurrentAddress + Size;
533 if (EndOfSection > EndOfFile) {
534 return EFI_NOT_FOUND;
535 }
536
537 //
538 // Look for executable sections
539 //
540 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
541 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
542 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
543 }
544 break;
545 }
546 }
547
548 //
549 // SEC Core image found
550 //
551 if (*SecCoreImageBase != 0) {
552 return EFI_SUCCESS;
553 }
554 }
555 }
556
557 /*
558 Find and return Pei Core entry point.
559
560 It also find SEC and PEI Core file debug inforamtion. It will report them if
561 remote debug is enabled.
562
563 **/
564 VOID
565 FindAndReportEntryPoints (
566 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
567 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
568 )
569 {
570 EFI_STATUS Status;
571 EFI_PHYSICAL_ADDRESS SecCoreImageBase;
572 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
573 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
574
575 //
576 // Find SEC Core and PEI Core image base
577 //
578 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
579 ASSERT_EFI_ERROR (Status);
580
581 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
582
583 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
584 //
585 // Report SEC Core debug information when remote debug is enabled
586 //
587 ImageContext.ImageAddress = SecCoreImageBase;
588 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
589 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
590
591 //
592 // Report PEI Core debug information when remote debug is enabled
593 //
594 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
595 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
596 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
597
598 //
599 // Find PEI Core entry point
600 //
601 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
602 if (EFI_ERROR (Status)) {
603 *PeiCoreEntryPoint = 0;
604 }
605
606 return;
607 }
608
609 VOID
610 EFIAPI
611 SecCoreStartupWithStack (
612 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
613 IN VOID *TopOfCurrentStack
614 )
615 {
616 EFI_SEC_PEI_HAND_OFF SecCoreData;
617 SEC_IDT_TABLE IdtTableInStack;
618 IA32_DESCRIPTOR IdtDescriptor;
619 UINT32 Index;
620
621 ProcessLibraryConstructorList (NULL, NULL);
622
623 DEBUG ((EFI_D_INFO,
624 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
625 (UINT32)(UINTN)BootFv,
626 (UINT32)(UINTN)TopOfCurrentStack
627 ));
628
629 //
630 // Initialize floating point operating environment
631 // to be compliant with UEFI spec.
632 //
633 InitializeFloatingPointUnits ();
634
635 //
636 // Initialize IDT
637 //
638 IdtTableInStack.PeiService = NULL;
639 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
640 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
641 }
642
643 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
644 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
645
646 AsmWriteIdtr (&IdtDescriptor);
647
648 #if defined (MDE_CPU_X64)
649 //
650 // ASSERT that the Page Tables were set by the reset vector code to
651 // the address we expect.
652 //
653 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));
654 #endif
655
656 //
657 // |-------------| <-- TopOfCurrentStack
658 // | Stack | 32k
659 // |-------------|
660 // | Heap | 32k
661 // |-------------| <-- SecCoreData.TemporaryRamBase
662 //
663
664 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +
665 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
666 (UINTN) TopOfCurrentStack);
667
668 //
669 // Initialize SEC hand-off state
670 //
671 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
672
673 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);
674 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
675
676 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
677 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
678
679 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
680 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
681
682 SecCoreData.BootFirmwareVolumeBase = BootFv;
683 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
684
685 //
686 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
687 //
688 IoWrite8 (0x21, 0xff);
689 IoWrite8 (0xA1, 0xff);
690
691 //
692 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
693 //
694 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
695 }
696
697 /**
698 Caller provided function to be invoked at the end of InitializeDebugAgent().
699
700 Entry point to the C language phase of SEC. After the SEC assembly
701 code has initialized some temporary memory and set up the stack,
702 the control is transferred to this function.
703
704 @param[in] Context The first input parameter of InitializeDebugAgent().
705
706 **/
707 VOID
708 EFIAPI
709 SecStartupPhase2(
710 IN VOID *Context
711 )
712 {
713 EFI_SEC_PEI_HAND_OFF *SecCoreData;
714 EFI_FIRMWARE_VOLUME_HEADER *BootFv;
715 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
716
717 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
718
719 //
720 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
721 // is enabled.
722 //
723 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
724 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
725 SecCoreData->BootFirmwareVolumeBase = BootFv;
726 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
727
728 //
729 // Transfer the control to the PEI core
730 //
731 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
732
733 //
734 // If we get here then the PEI Core returned, which is not recoverable.
735 //
736 ASSERT (FALSE);
737 CpuDeadLoop ();
738 }
739
740 EFI_STATUS
741 EFIAPI
742 TemporaryRamMigration (
743 IN CONST EFI_PEI_SERVICES **PeiServices,
744 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
745 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
746 IN UINTN CopySize
747 )
748 {
749 IA32_DESCRIPTOR IdtDescriptor;
750 VOID *OldHeap;
751 VOID *NewHeap;
752 VOID *OldStack;
753 VOID *NewStack;
754 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
755 BOOLEAN OldStatus;
756 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
757
758 DEBUG ((EFI_D_INFO,
759 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",
760 (UINTN) TemporaryMemoryBase,
761 (UINTN) PermanentMemoryBase,
762 CopySize
763 ));
764
765 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
766 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
767
768 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
769 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
770
771 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
772 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
773
774 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
775 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
776
777 //
778 // Migrate Heap
779 //
780 CopyMem (NewHeap, OldHeap, CopySize >> 1);
781
782 //
783 // Migrate Stack
784 //
785 CopyMem (NewStack, OldStack, CopySize >> 1);
786
787 //
788 // Rebase IDT table in permanent memory
789 //
790 AsmReadIdtr (&IdtDescriptor);
791 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
792
793 AsmWriteIdtr (&IdtDescriptor);
794
795 //
796 // Use SetJump()/LongJump() to switch to a new stack.
797 //
798 if (SetJump (&JumpBuffer) == 0) {
799 #if defined (MDE_CPU_IA32)
800 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
801 #endif
802 #if defined (MDE_CPU_X64)
803 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
804 #endif
805 LongJump (&JumpBuffer, (UINTN)-1);
806 }
807
808 SaveAndSetDebugTimerInterrupt (OldStatus);
809
810 return EFI_SUCCESS;
811 }
812