]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Cleanup debug messages
[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 @param[in] Sections The sections to search
132 @param[in] SizeOfSections Total size of all sections
133 @param[in] SectionType The section type to locate
134 @param[out] FoundSection The FFS section if found
135
136 @retval EFI_SUCCESS The file and section was found
137 @retval EFI_NOT_FOUND The file and section was not found
138 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
139
140 **/
141 EFI_STATUS
142 FindFfsSectionInSections (
143 IN VOID *Sections,
144 IN UINTN SizeOfSections,
145 IN EFI_SECTION_TYPE SectionType,
146 OUT EFI_COMMON_SECTION_HEADER **FoundSection
147 )
148 {
149 EFI_PHYSICAL_ADDRESS CurrentAddress;
150 UINT32 Size;
151 EFI_PHYSICAL_ADDRESS EndOfSections;
152 EFI_COMMON_SECTION_HEADER *Section;
153 EFI_PHYSICAL_ADDRESS EndOfSection;
154
155 //
156 // Loop through the FFS file sections within the PEI Core FFS file
157 //
158 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
159 EndOfSections = EndOfSection + SizeOfSections;
160 for (;;) {
161 if (EndOfSection == EndOfSections) {
162 break;
163 }
164 CurrentAddress = (EndOfSection + 3) & ~(3ULL);
165 if (CurrentAddress >= EndOfSections) {
166 return EFI_VOLUME_CORRUPTED;
167 }
168
169 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
170
171 Size = SECTION_SIZE (Section);
172 if (Size < sizeof (*Section)) {
173 return EFI_VOLUME_CORRUPTED;
174 }
175
176 EndOfSection = CurrentAddress + Size;
177 if (EndOfSection > EndOfSections) {
178 return EFI_VOLUME_CORRUPTED;
179 }
180
181 //
182 // Look for the requested section type
183 //
184 if (Section->Type == SectionType) {
185 *FoundSection = Section;
186 return EFI_SUCCESS;
187 }
188 }
189
190 return EFI_NOT_FOUND;
191 }
192
193 /**
194 Locates a FFS file with the specified file type and a section
195 within that file with the specified section type.
196
197 @param[in] Fv The firmware volume to search
198 @param[in] FileType The file type to locate
199 @param[in] SectionType The section type to locate
200 @param[out] FoundSection The FFS section if found
201
202 @retval EFI_SUCCESS The file and section was found
203 @retval EFI_NOT_FOUND The file and section was not found
204 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
205
206 **/
207 EFI_STATUS
208 EFIAPI
209 FindFfsFileAndSection (
210 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
211 IN EFI_FV_FILETYPE FileType,
212 IN EFI_SECTION_TYPE SectionType,
213 OUT EFI_COMMON_SECTION_HEADER **FoundSection
214 )
215 {
216 EFI_STATUS Status;
217 EFI_PHYSICAL_ADDRESS CurrentAddress;
218 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
219 EFI_FFS_FILE_HEADER *File;
220 UINT32 Size;
221 EFI_PHYSICAL_ADDRESS EndOfFile;
222
223 if (Fv->Signature != EFI_FVH_SIGNATURE) {
224 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));
225 return EFI_VOLUME_CORRUPTED;
226 }
227
228 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
229 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
230
231 //
232 // Loop through the FFS files in the Boot Firmware Volume
233 //
234 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
235
236 CurrentAddress = (EndOfFile + 7) & ~(7ULL);
237 if (CurrentAddress > EndOfFirmwareVolume) {
238 return EFI_VOLUME_CORRUPTED;
239 }
240
241 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
242 Size = *(UINT32*) File->Size & 0xffffff;
243 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
244 return EFI_VOLUME_CORRUPTED;
245 }
246
247 EndOfFile = CurrentAddress + Size;
248 if (EndOfFile > EndOfFirmwareVolume) {
249 return EFI_VOLUME_CORRUPTED;
250 }
251
252 //
253 // Look for the request file type
254 //
255 if (File->Type != FileType) {
256 continue;
257 }
258
259 Status = FindFfsSectionInSections (
260 (VOID*) (File + 1),
261 (UINTN) EndOfFile - (UINTN) (File + 1),
262 SectionType,
263 FoundSection
264 );
265 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
266 return Status;
267 }
268 }
269 }
270
271 /**
272 Locates the compressed main firmware volume and decompresses it.
273
274 @param[in,out] Fv On input, the firmware volume to search
275 On output, the decompressed main FV
276
277 @retval EFI_SUCCESS The file and section was found
278 @retval EFI_NOT_FOUND The file and section was not found
279 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
280
281 **/
282 EFI_STATUS
283 EFIAPI
284 DecompressGuidedFv (
285 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
286 )
287 {
288 EFI_STATUS Status;
289 EFI_GUID_DEFINED_SECTION *Section;
290 UINT32 OutputBufferSize;
291 UINT32 ScratchBufferSize;
292 UINT16 SectionAttribute;
293 UINT32 AuthenticationStatus;
294 VOID *OutputBuffer;
295 VOID *ScratchBuffer;
296 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;
297 EFI_FIRMWARE_VOLUME_HEADER *NewFv;
298
299 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;
300
301 Status = FindFfsFileAndSection (
302 *Fv,
303 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
304 EFI_SECTION_GUID_DEFINED,
305 (EFI_COMMON_SECTION_HEADER**) &Section
306 );
307 if (EFI_ERROR (Status)) {
308 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
309 return Status;
310 }
311
312 Status = ExtractGuidedSectionGetInfo (
313 Section,
314 &OutputBufferSize,
315 &ScratchBufferSize,
316 &SectionAttribute
317 );
318 if (EFI_ERROR (Status)) {
319 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
320 return Status;
321 }
322
323 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)
324 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);
325 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
326 Status = ExtractGuidedSectionDecode (
327 Section,
328 &OutputBuffer,
329 ScratchBuffer,
330 &AuthenticationStatus
331 );
332 if (EFI_ERROR (Status)) {
333 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));
334 return Status;
335 }
336
337 Status = FindFfsSectionInSections (
338 OutputBuffer,
339 OutputBufferSize,
340 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
341 (EFI_COMMON_SECTION_HEADER**) &NewFvSection
342 );
343 if (EFI_ERROR (Status)) {
344 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));
345 return Status;
346 }
347
348 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);
349 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));
350
351 if (NewFv->Signature != EFI_FVH_SIGNATURE) {
352 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));
353 CpuDeadLoop ();
354 return EFI_VOLUME_CORRUPTED;
355 }
356
357 *Fv = NewFv;
358 return EFI_SUCCESS;
359 }
360
361 /**
362 Locates the PEI Core entry point address
363
364 @param[in] Fv The firmware volume to search
365 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
366
367 @retval EFI_SUCCESS The file and section was found
368 @retval EFI_NOT_FOUND The file and section was not found
369 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
370
371 **/
372 EFI_STATUS
373 EFIAPI
374 FindPeiCoreImageBaseInFv (
375 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
376 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
377 )
378 {
379 EFI_STATUS Status;
380 EFI_COMMON_SECTION_HEADER *Section;
381
382 Status = FindFfsFileAndSection (
383 Fv,
384 EFI_FV_FILETYPE_PEI_CORE,
385 EFI_SECTION_PE32,
386 &Section
387 );
388 if (EFI_ERROR (Status)) {
389 Status = FindFfsFileAndSection (
390 Fv,
391 EFI_FV_FILETYPE_PEI_CORE,
392 EFI_SECTION_TE,
393 &Section
394 );
395 if (EFI_ERROR (Status)) {
396 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
397 return Status;
398 }
399 }
400
401 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
402 return EFI_SUCCESS;
403 }
404
405 /**
406 Locates the PEI Core entry point address
407
408 @param[in,out] Fv The firmware volume to search
409 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
410
411 @retval EFI_SUCCESS The file and section was found
412 @retval EFI_NOT_FOUND The file and section was not found
413 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
414
415 **/
416 VOID
417 EFIAPI
418 FindPeiCoreImageBase (
419 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
420 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
421 )
422 {
423 *PeiCoreImageBase = 0;
424
425 FindMainFv (BootFv);
426
427 DecompressGuidedFv (BootFv);
428
429 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
430 }
431
432 /**
433 Find core image base.
434
435 **/
436 EFI_STATUS
437 EFIAPI
438 FindImageBase (
439 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
440 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
441 )
442 {
443 EFI_PHYSICAL_ADDRESS CurrentAddress;
444 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
445 EFI_FFS_FILE_HEADER *File;
446 UINT32 Size;
447 EFI_PHYSICAL_ADDRESS EndOfFile;
448 EFI_COMMON_SECTION_HEADER *Section;
449 EFI_PHYSICAL_ADDRESS EndOfSection;
450
451 *SecCoreImageBase = 0;
452
453 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
454 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
455
456 //
457 // Loop through the FFS files in the Boot Firmware Volume
458 //
459 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
460
461 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
462 if (CurrentAddress > EndOfFirmwareVolume) {
463 return EFI_NOT_FOUND;
464 }
465
466 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
467 Size = *(UINT32*) File->Size & 0xffffff;
468 if (Size < sizeof (*File)) {
469 return EFI_NOT_FOUND;
470 }
471
472 EndOfFile = CurrentAddress + Size;
473 if (EndOfFile > EndOfFirmwareVolume) {
474 return EFI_NOT_FOUND;
475 }
476
477 //
478 // Look for SEC Core
479 //
480 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
481 continue;
482 }
483
484 //
485 // Loop through the FFS file sections within the FFS file
486 //
487 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
488 for (;;) {
489 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
490 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
491
492 Size = *(UINT32*) Section->Size & 0xffffff;
493 if (Size < sizeof (*Section)) {
494 return EFI_NOT_FOUND;
495 }
496
497 EndOfSection = CurrentAddress + Size;
498 if (EndOfSection > EndOfFile) {
499 return EFI_NOT_FOUND;
500 }
501
502 //
503 // Look for executable sections
504 //
505 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
506 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
507 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
508 }
509 break;
510 }
511 }
512
513 //
514 // SEC Core image found
515 //
516 if (*SecCoreImageBase != 0) {
517 return EFI_SUCCESS;
518 }
519 }
520 }
521
522 /*
523 Find and return Pei Core entry point.
524
525 It also find SEC and PEI Core file debug inforamtion. It will report them if
526 remote debug is enabled.
527
528 **/
529 VOID
530 EFIAPI
531 FindAndReportEntryPoints (
532 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
533 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
534 )
535 {
536 EFI_STATUS Status;
537 EFI_PHYSICAL_ADDRESS SecCoreImageBase;
538 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
539 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
540
541 //
542 // Find SEC Core and PEI Core image base
543 //
544 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
545 ASSERT_EFI_ERROR (Status);
546
547 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
548
549 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
550 //
551 // Report SEC Core debug information when remote debug is enabled
552 //
553 ImageContext.ImageAddress = SecCoreImageBase;
554 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
555 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
556
557 //
558 // Report PEI Core debug information when remote debug is enabled
559 //
560 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
561 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
562 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
563
564 //
565 // Find PEI Core entry point
566 //
567 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
568 if (EFI_ERROR (Status)) {
569 *PeiCoreEntryPoint = 0;
570 }
571
572 return;
573 }
574
575 VOID
576 EFIAPI
577 SecCoreStartupWithStack (
578 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
579 IN VOID *TopOfCurrentStack
580 )
581 {
582 EFI_SEC_PEI_HAND_OFF SecCoreData;
583 SEC_IDT_TABLE IdtTableInStack;
584 IA32_DESCRIPTOR IdtDescriptor;
585 UINT32 Index;
586
587 ProcessLibraryConstructorList (NULL, NULL);
588
589 DEBUG ((EFI_D_INFO,
590 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
591 (UINT32)(UINTN)BootFv,
592 (UINT32)(UINTN)TopOfCurrentStack
593 ));
594
595 //
596 // Initialize floating point operating environment
597 // to be compliant with UEFI spec.
598 //
599 InitializeFloatingPointUnits ();
600
601 //
602 // Initialize IDT
603 //
604 IdtTableInStack.PeiService = NULL;
605 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
606 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
607 }
608
609 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
610 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
611
612 AsmWriteIdtr (&IdtDescriptor);
613
614 #if defined (MDE_CPU_X64)
615 //
616 // ASSERT that the Page Tables were set by the reset vector code to
617 // the address we expect.
618 //
619 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));
620 #endif
621
622 //
623 // |-------------| <-- TopOfCurrentStack
624 // | Stack | 32k
625 // |-------------|
626 // | Heap | 32k
627 // |-------------| <-- SecCoreData.TemporaryRamBase
628 //
629
630 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +
631 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
632 (UINTN) TopOfCurrentStack);
633
634 //
635 // Initialize SEC hand-off state
636 //
637 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
638
639 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);
640 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
641
642 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
643 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
644
645 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
646 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
647
648 SecCoreData.BootFirmwareVolumeBase = BootFv;
649 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
650
651 //
652 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
653 //
654 IoWrite8 (0x21, 0xff);
655 IoWrite8 (0xA1, 0xff);
656
657 //
658 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
659 //
660 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
661 }
662
663 /**
664 Caller provided function to be invoked at the end of InitializeDebugAgent().
665
666 Entry point to the C language phase of SEC. After the SEC assembly
667 code has initialized some temporary memory and set up the stack,
668 the control is transferred to this function.
669
670 @param[in] Context The first input parameter of InitializeDebugAgent().
671
672 **/
673 VOID
674 EFIAPI
675 SecStartupPhase2(
676 IN VOID *Context
677 )
678 {
679 EFI_SEC_PEI_HAND_OFF *SecCoreData;
680 EFI_FIRMWARE_VOLUME_HEADER *BootFv;
681 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
682
683 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
684
685 //
686 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
687 // is enabled.
688 //
689 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
690 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
691 SecCoreData->BootFirmwareVolumeBase = BootFv;
692 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
693
694 //
695 // Transfer the control to the PEI core
696 //
697 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
698
699 //
700 // If we get here then the PEI Core returned, which is not recoverable.
701 //
702 ASSERT (FALSE);
703 CpuDeadLoop ();
704 }
705
706 EFI_STATUS
707 EFIAPI
708 TemporaryRamMigration (
709 IN CONST EFI_PEI_SERVICES **PeiServices,
710 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
711 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
712 IN UINTN CopySize
713 )
714 {
715 IA32_DESCRIPTOR IdtDescriptor;
716 VOID *OldHeap;
717 VOID *NewHeap;
718 VOID *OldStack;
719 VOID *NewStack;
720 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
721 BOOLEAN OldStatus;
722 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
723
724 DEBUG ((EFI_D_INFO,
725 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",
726 (UINTN) TemporaryMemoryBase,
727 (UINTN) PermanentMemoryBase,
728 CopySize
729 ));
730
731 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
732 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
733
734 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
735 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
736
737 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
738 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
739
740 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
741 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
742
743 //
744 // Migrate Heap
745 //
746 CopyMem (NewHeap, OldHeap, CopySize >> 1);
747
748 //
749 // Migrate Stack
750 //
751 CopyMem (NewStack, OldStack, CopySize >> 1);
752
753 //
754 // Rebase IDT table in permanent memory
755 //
756 AsmReadIdtr (&IdtDescriptor);
757 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
758
759 AsmWriteIdtr (&IdtDescriptor);
760
761 //
762 // Use SetJump()/LongJump() to switch to a new stack.
763 //
764 if (SetJump (&JumpBuffer) == 0) {
765 #if defined (MDE_CPU_IA32)
766 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
767 #endif
768 #if defined (MDE_CPU_X64)
769 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
770 #endif
771 LongJump (&JumpBuffer, (UINTN)-1);
772 }
773
774 SaveAndSetDebugTimerInterrupt (OldStatus);
775
776 return EFI_SUCCESS;
777 }
778