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