]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
Clean up SEC implementation for Ovmf.
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
49ba9447 1/** @file
2 Main SEC phase code. Transitions to PEI.
3
56d7640a 4 Copyright (c) 2008 - 2009, 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
34#define SEC_IDT_ENTRY_COUNT 34
49ba9447 35
42a83e80 36typedef struct _SEC_IDT_TABLE {
37 EFI_PEI_SERVICES *PeiService;
38 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
39} SEC_IDT_TABLE;
40
41VOID
42EFIAPI
43SecStartupPhase2 (
44 IN VOID *Context
45 );
49ba9447 46
47EFI_STATUS
48EFIAPI
49TemporaryRamMigration (
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
42a83e80 56//
57//
58//
59TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
60 TemporaryRamMigration
49ba9447 61};
62
42a83e80 63EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
49ba9447 64 {
65 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
66 &gEfiTemporaryRamSupportPpiGuid,
42a83e80 67 &mTemporaryRamSupportPpi
49ba9447 68 },
69};
70
42a83e80 71//
72// Template of an IDT entry pointing to 10:FFFFFFE4h.
73//
74IA32_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**/
94EFI_STATUS
95FindMainFv (
96 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv
97 )
98{
99 EFI_FIRMWARE_VOLUME_HEADER *Fv;
100 UINTN Distance;
101 BOOLEAN Found;
102
103 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
104
105 Found = FALSE;
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
528/*
529 Find and return Pei Core entry point.
530
531 It also find SEC and PEI Core file debug inforamtion. It will report them if
532 remote debug is enabled.
533
534**/
535VOID
536EFIAPI
537FindAndReportEntryPoints (
538 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
539 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
540 )
541{
542 EFI_STATUS Status;
543 EFI_PHYSICAL_ADDRESS SecCoreImageBase;
544 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
545 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
546
547 //
548 // Find SEC Core and PEI Core image base
549 //
550 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
551 ASSERT_EFI_ERROR (Status);
552
553 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
554
555 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
556 //
557 // Report SEC Core debug information when remote debug is enabled
558 //
559 ImageContext.ImageAddress = SecCoreImageBase;
560 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
561 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
562
563 //
564 // Report PEI Core debug information when remote debug is enabled
565 //
566 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
567 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
568 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
569
570 //
571 // Find PEI Core entry point
572 //
573 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
574 if (EFI_ERROR (Status)) {
575 *PeiCoreEntryPoint = 0;
576 }
577
578 return;
49ba9447 579}
580
581VOID
582EFIAPI
583SecCoreStartupWithStack (
c1c2669c 584 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
0913fadc 585 IN VOID *TopOfCurrentStack
49ba9447 586 )
587{
42a83e80 588 EFI_SEC_PEI_HAND_OFF SecCoreData;
589 SEC_IDT_TABLE IdtTableInStack;
590 IA32_DESCRIPTOR IdtDescriptor;
591 UINT32 Index;
49ba9447 592
42a83e80 593 ProcessLibraryConstructorList (NULL, NULL);
594
595 DEBUG ((EFI_D_ERROR,
c1c2669c 596 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
597 (UINT32)(UINTN)BootFv,
598 (UINT32)(UINTN)TopOfCurrentStack
599 ));
600
284af948 601 //
602 // Initialize floating point operating environment
603 // to be compliant with UEFI spec.
604 //
605 InitializeFloatingPointUnits ();
606
42a83e80 607 //
608 // Initialize IDT
609 //
610 IdtTableInStack.PeiService = NULL;
611 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
612 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
613 }
614
615 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
616 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
617
618 AsmWriteIdtr (&IdtDescriptor);
49ba9447 619
620 //
42a83e80 621 // |-------------| <-- TopOfCurrentStack
49ba9447 622 // | Stack | 32k
42a83e80 623 // |-------------|
624 // | Heap | 32k
625 // |-------------| <-- SecCoreData.TemporaryRamBase
49ba9447 626 //
627
628 //
42a83e80 629 // Initialize SEC hand-off state
49ba9447 630 //
42a83e80 631 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
632
633 SecCoreData.TemporaryRamSize = SIZE_64KB;
634 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
49ba9447 635
42a83e80 636 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
637 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
49ba9447 638
42a83e80 639 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
640 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
49ba9447 641
42a83e80 642 SecCoreData.BootFirmwareVolumeBase = BootFv;
643 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
49ba9447 644
645 //
42a83e80 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
49ba9447 651 //
42a83e80 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.
49ba9447 663
42a83e80 664 @param[in] Context The first input parameter of InitializeDebugAgent().
c1c2669c 665
42a83e80 666**/
667VOID
668EFIAPI
669SecStartupPhase2(
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);
c1c2669c 685 SecCoreData->BootFirmwareVolumeBase = BootFv;
cb0a4290 686 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
0913fadc 687
49ba9447 688 //
42a83e80 689 // Transfer the control to the PEI core
0913fadc 690 //
42a83e80 691 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
692
693 //
694 // If we get here then the PEI Core returned, which is not recoverable.
49ba9447 695 //
696 ASSERT (FALSE);
697 CpuDeadLoop ();
698}
699
700EFI_STATUS
701EFIAPI
702TemporaryRamMigration (
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{
42a83e80 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
49ba9447 718 DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize));
42a83e80 719
720 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
721 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
722
723 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
724 NewStack = (VOID*)(UINTN)PermanentMemoryBase;
725
726 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
727 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
728
729 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
730 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
49ba9447 731
732 //
42a83e80 733 // Migrate Heap
734 //
735 CopyMem (NewHeap, OldHeap, CopySize >> 1);
736
737 //
738 // Migrate Stack
739 //
740 CopyMem (NewStack, OldStack, CopySize >> 1);
741
742 //
743 // Rebase IDT table in permanent memory
744 //
745 AsmReadIdtr (&IdtDescriptor);
746 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
747
748 AsmWriteIdtr (&IdtDescriptor);
49ba9447 749
750 //
42a83e80 751 // Use SetJump()/LongJump() to switch to a new stack.
49ba9447 752 //
42a83e80 753 if (SetJump (&JumpBuffer) == 0) {
754#if defined (MDE_CPU_IA32)
755 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
756#endif
757#if defined (MDE_CPU_X64)
758 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
759#endif
760 LongJump (&JumpBuffer, (UINTN)-1);
761 }
762
763 SaveAndSetDebugTimerInterrupt (OldStatus);
49ba9447 764
765 return EFI_SUCCESS;
766}
767