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