• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Last PEIM.
3   Responsibility of this module is to load the DXE Core from a Firmware Volume.
4 
5 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
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 "DxeIpl.h"
17 
18 
19 //
20 // Module Globals used in the DXE to PEI hand off
21 // These must be module globals, so the stack can be switched
22 //
23 CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
24   DxeLoadCore
25 };
26 
27 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
28   CustomGuidedSectionExtract
29 };
30 
31 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
32   Decompress
33 };
34 
35 CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
36   {
37     EFI_PEI_PPI_DESCRIPTOR_PPI,
38     &gEfiDxeIplPpiGuid,
39     (VOID *) &mDxeIplPpi
40   },
41   {
42     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
43     &gEfiPeiDecompressPpiGuid,
44     (VOID *) &mDecompressPpi
45   }
46 };
47 
48 CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
49   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
50   &gEfiEndOfPeiSignalPpiGuid,
51   NULL
52 };
53 
54 /**
55   Entry point of DXE IPL PEIM.
56 
57   This function installs DXE IPL PPI and Decompress PPI.  It also reloads
58   itself to memory on non-S3 resume boot path.
59 
60   @param  FileHandle  Handle of the file being invoked.
61   @param  PeiServices Describes the list of possible PEI Services.
62 
63   @retval EFI_SUCESS  The entry point of DXE IPL PEIM executes successfully.
64   @retval Others      Some error occurs during the execution of this function.
65 
66 **/
67 EFI_STATUS
68 EFIAPI
PeimInitializeDxeIpl(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)69 PeimInitializeDxeIpl (
70   IN       EFI_PEI_FILE_HANDLE  FileHandle,
71   IN CONST EFI_PEI_SERVICES     **PeiServices
72   )
73 {
74   EFI_STATUS                                Status;
75   EFI_BOOT_MODE                             BootMode;
76   EFI_GUID                                  *ExtractHandlerGuidTable;
77   UINTN                                     ExtractHandlerNumber;
78   EFI_PEI_PPI_DESCRIPTOR                    *GuidPpi;
79 
80   BootMode = GetBootModeHob ();
81 
82   if (BootMode != BOOT_ON_S3_RESUME) {
83     Status = PeiServicesRegisterForShadow (FileHandle);
84     if (Status == EFI_SUCCESS) {
85       //
86       // EFI_SUCESS means it is the first time to call register for shadow.
87       //
88       return Status;
89     }
90 
91     //
92     // Ensure that DXE IPL is shadowed to permanent memory.
93     //
94     ASSERT (Status == EFI_ALREADY_STARTED);
95   }
96 
97   //
98   // Get custom extract guided section method guid list
99   //
100   ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
101 
102   //
103   // Install custom extraction guid PPI
104   //
105   if (ExtractHandlerNumber > 0) {
106     GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
107     ASSERT (GuidPpi != NULL);
108     while (ExtractHandlerNumber-- > 0) {
109       GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
110       GuidPpi->Ppi   = (VOID *) &mCustomGuidedSectionExtractionPpi;
111       GuidPpi->Guid  = &ExtractHandlerGuidTable[ExtractHandlerNumber];
112       Status = PeiServicesInstallPpi (GuidPpi++);
113       ASSERT_EFI_ERROR(Status);
114     }
115   }
116 
117   //
118   // Install DxeIpl and Decompress PPIs.
119   //
120   Status = PeiServicesInstallPpi (mPpiList);
121   ASSERT_EFI_ERROR(Status);
122 
123   return Status;
124 }
125 
126 /**
127    Validate variable data for the MemoryTypeInformation.
128 
129    @param MemoryData       Variable data.
130    @param MemoryDataSize   Variable data length.
131 
132    @return TRUE            The variable data is valid.
133    @return FALSE           The variable data is invalid.
134 
135 **/
136 BOOLEAN
ValidateMemoryTypeInfoVariable(IN EFI_MEMORY_TYPE_INFORMATION * MemoryData,IN UINTN MemoryDataSize)137 ValidateMemoryTypeInfoVariable (
138   IN EFI_MEMORY_TYPE_INFORMATION      *MemoryData,
139   IN UINTN                            MemoryDataSize
140   )
141 {
142   UINTN                       Count;
143   UINTN                       Index;
144 
145   // Check the input parameter.
146   if (MemoryData == NULL) {
147     return FALSE;
148   }
149 
150   // Get Count
151   Count = MemoryDataSize / sizeof (*MemoryData);
152 
153   // Check Size
154   if (Count * sizeof(*MemoryData) != MemoryDataSize) {
155     return FALSE;
156   }
157 
158   // Check last entry type filed.
159   if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
160     return FALSE;
161   }
162 
163   // Check the type filed.
164   for (Index = 0; Index < Count - 1; Index++) {
165     if (MemoryData[Index].Type >= EfiMaxMemoryType) {
166       return FALSE;
167     }
168   }
169 
170   return TRUE;
171 }
172 
173 /**
174    Main entry point to last PEIM.
175 
176    This function finds DXE Core in the firmware volume and transfer the control to
177    DXE core.
178 
179    @param This          Entry point for DXE IPL PPI.
180    @param PeiServices   General purpose services available to every PEIM.
181    @param HobList       Address to the Pei HOB list.
182 
183    @return EFI_SUCCESS              DXE core was successfully loaded.
184    @return EFI_OUT_OF_RESOURCES     There are not enough resources to load DXE core.
185 
186 **/
187 EFI_STATUS
188 EFIAPI
DxeLoadCore(IN CONST EFI_DXE_IPL_PPI * This,IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_HOB_POINTERS HobList)189 DxeLoadCore (
190   IN CONST EFI_DXE_IPL_PPI *This,
191   IN EFI_PEI_SERVICES      **PeiServices,
192   IN EFI_PEI_HOB_POINTERS  HobList
193   )
194 {
195   EFI_STATUS                                Status;
196   EFI_FV_FILE_INFO                          DxeCoreFileInfo;
197   EFI_PHYSICAL_ADDRESS                      DxeCoreAddress;
198   UINT64                                    DxeCoreSize;
199   EFI_PHYSICAL_ADDRESS                      DxeCoreEntryPoint;
200   EFI_BOOT_MODE                             BootMode;
201   EFI_PEI_FILE_HANDLE                       FileHandle;
202   EFI_PEI_READ_ONLY_VARIABLE2_PPI           *Variable;
203   EFI_PEI_LOAD_FILE_PPI                     *LoadFile;
204   UINTN                                     Instance;
205   UINT32                                    AuthenticationState;
206   UINTN                                     DataSize;
207   EFI_PEI_S3_RESUME2_PPI                    *S3Resume;
208   EFI_PEI_RECOVERY_MODULE_PPI               *PeiRecovery;
209   EFI_MEMORY_TYPE_INFORMATION               MemoryData[EfiMaxMemoryType + 1];
210 
211   //
212   // if in S3 Resume, restore configure
213   //
214   BootMode = GetBootModeHob ();
215 
216   if (BootMode == BOOT_ON_S3_RESUME) {
217     Status = PeiServicesLocatePpi (
218                &gEfiPeiS3Resume2PpiGuid,
219                0,
220                NULL,
221                (VOID **) &S3Resume
222                );
223     if (EFI_ERROR (Status)) {
224       //
225       // Report Status code that S3Resume PPI can not be found
226       //
227       REPORT_STATUS_CODE (
228         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
229         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)
230         );
231     }
232     ASSERT_EFI_ERROR (Status);
233 
234     Status = S3Resume->S3RestoreConfig2 (S3Resume);
235     ASSERT_EFI_ERROR (Status);
236   } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
237     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));
238     Status = PeiServicesLocatePpi (
239                &gEfiPeiRecoveryModulePpiGuid,
240                0,
241                NULL,
242                (VOID **) &PeiRecovery
243                );
244 
245     if (EFI_ERROR (Status)) {
246       DEBUG ((DEBUG_ERROR, "Locate Recovery PPI Failed.(Status = %r)\n", Status));
247       //
248       // Report Status code the failure of locating Recovery PPI
249       //
250       REPORT_STATUS_CODE (
251         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
252         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
253         );
254       CpuDeadLoop ();
255     }
256 
257     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));
258     Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
259     if (EFI_ERROR (Status)) {
260       DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
261       //
262       // Report Status code that recovery image can not be found
263       //
264       REPORT_STATUS_CODE (
265         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
266         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
267         );
268       CpuDeadLoop ();
269     }
270     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
271     //
272     // Now should have a HOB with the DXE core
273     //
274   }
275 
276   if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) {
277     //
278     // Don't build GuidHob if GuidHob has been installed.
279     //
280     Status = PeiServicesLocatePpi (
281                &gEfiPeiReadOnlyVariable2PpiGuid,
282                0,
283                NULL,
284                (VOID **)&Variable
285                );
286     if (!EFI_ERROR (Status)) {
287       DataSize = sizeof (MemoryData);
288       Status = Variable->GetVariable (
289                            Variable,
290                            EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
291                            &gEfiMemoryTypeInformationGuid,
292                            NULL,
293                            &DataSize,
294                            &MemoryData
295                            );
296       if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {
297         //
298         // Build the GUID'd HOB for DXE
299         //
300         BuildGuidDataHob (
301           &gEfiMemoryTypeInformationGuid,
302           MemoryData,
303           DataSize
304           );
305       }
306     }
307   }
308 
309   //
310   // Look in all the FVs present in PEI and find the DXE Core FileHandle
311   //
312   FileHandle = DxeIplFindDxeCore ();
313 
314   //
315   // Load the DXE Core from a Firmware Volume.
316   //
317   Instance = 0;
318   do {
319     Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);
320     //
321     // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.
322     //
323     ASSERT_EFI_ERROR (Status);
324 
325     Status = LoadFile->LoadFile (
326                          LoadFile,
327                          FileHandle,
328                          &DxeCoreAddress,
329                          &DxeCoreSize,
330                          &DxeCoreEntryPoint,
331                          &AuthenticationState
332                          );
333   } while (EFI_ERROR (Status));
334 
335   //
336   // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.
337   //
338   Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);
339   ASSERT_EFI_ERROR (Status);
340 
341   //
342   // Add HOB for the DXE Core
343   //
344   BuildModuleHob (
345     &DxeCoreFileInfo.FileName,
346     DxeCoreAddress,
347     ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),
348     DxeCoreEntryPoint
349     );
350 
351   //
352   // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
353   //
354   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));
355 
356   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
357 
358   //
359   // Transfer control to the DXE Core
360   // The hand off state is simply a pointer to the HOB list
361   //
362   HandOffToDxeCore (DxeCoreEntryPoint, HobList);
363   //
364   // If we get here, then the DXE Core returned.  This is an error
365   // DxeCore should not return.
366   //
367   ASSERT (FALSE);
368   CpuDeadLoop ();
369 
370   return EFI_OUT_OF_RESOURCES;
371 }
372 
373 
374 /**
375    Searches DxeCore in all firmware Volumes and loads the first
376    instance that contains DxeCore.
377 
378    @return FileHandle of DxeCore to load DxeCore.
379 
380 **/
381 EFI_PEI_FILE_HANDLE
DxeIplFindDxeCore(VOID)382 DxeIplFindDxeCore (
383   VOID
384   )
385 {
386   EFI_STATUS            Status;
387   UINTN                 Instance;
388   EFI_PEI_FV_HANDLE     VolumeHandle;
389   EFI_PEI_FILE_HANDLE   FileHandle;
390 
391   Instance    = 0;
392   while (TRUE) {
393     //
394     // Traverse all firmware volume instances
395     //
396     Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
397     //
398     // If some error occurs here, then we cannot find any firmware
399     // volume that may contain DxeCore.
400     //
401     if (EFI_ERROR (Status)) {
402       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
403     }
404     ASSERT_EFI_ERROR (Status);
405 
406     //
407     // Find the DxeCore file type from the beginning in this firmware volume.
408     //
409     FileHandle = NULL;
410     Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
411     if (!EFI_ERROR (Status)) {
412       //
413       // Find DxeCore FileHandle in this volume, then we skip other firmware volume and
414       // return the FileHandle.
415       //
416       return FileHandle;
417     }
418     //
419     // We cannot find DxeCore in this firmware volume, then search the next volume.
420     //
421     Instance++;
422   }
423 }
424 
425 
426 
427 /**
428   The ExtractSection() function processes the input section and
429   returns a pointer to the section contents. If the section being
430   extracted does not require processing (if the section
431   GuidedSectionHeader.Attributes has the
432   EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
433   OutputBuffer is just updated to point to the start of the
434   section's contents. Otherwise, *Buffer must be allocated
435   from PEI permanent memory.
436 
437   @param This                   Indicates the
438                                 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
439                                 Buffer containing the input GUIDed section to be
440                                 processed. OutputBuffer OutputBuffer is
441                                 allocated from PEI permanent memory and contains
442                                 the new section stream.
443   @param InputSection           A pointer to the input buffer, which contains
444                                 the input section to be processed.
445   @param OutputBuffer           A pointer to a caller-allocated buffer, whose
446                                 size is specified by the contents of OutputSize.
447   @param OutputSize             A pointer to a caller-allocated
448                                 UINTN in which the size of *OutputBuffer
449                                 allocation is stored. If the function
450                                 returns anything other than EFI_SUCCESS,
451                                 the value of OutputSize is undefined.
452   @param AuthenticationStatus   A pointer to a caller-allocated
453                                 UINT32 that indicates the
454                                 authentication status of the
455                                 output buffer. If the input
456                                 section's GuidedSectionHeader.
457                                 Attributes field has the
458                                 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
459                                 bit as clear,
460                                 AuthenticationStatus must return
461                                 zero. These bits reflect the
462                                 status of the extraction
463                                 operation. If the function
464                                 returns anything other than
465                                 EFI_SUCCESS, the value of
466                                 AuthenticationStatus is
467                                 undefined.
468 
469   @retval EFI_SUCCESS           The InputSection was
470                                 successfully processed and the
471                                 section contents were returned.
472 
473   @retval EFI_OUT_OF_RESOURCES  The system has insufficient
474                                 resources to process the request.
475 
476   @retval EFI_INVALID_PARAMETER The GUID in InputSection does
477                                 not match this instance of the
478                                 GUIDed Section Extraction PPI.
479 
480 **/
481 EFI_STATUS
482 EFIAPI
CustomGuidedSectionExtract(IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI * This,IN CONST VOID * InputSection,OUT VOID ** OutputBuffer,OUT UINTN * OutputSize,OUT UINT32 * AuthenticationStatus)483 CustomGuidedSectionExtract (
484   IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
485   IN CONST  VOID                                  *InputSection,
486   OUT       VOID                                  **OutputBuffer,
487   OUT       UINTN                                 *OutputSize,
488   OUT       UINT32                                *AuthenticationStatus
489 )
490 {
491   EFI_STATUS      Status;
492   UINT8           *ScratchBuffer;
493   UINT32          ScratchBufferSize;
494   UINT32          OutputBufferSize;
495   UINT16          SectionAttribute;
496 
497   //
498   // Init local variable
499   //
500   ScratchBuffer = NULL;
501 
502   //
503   // Call GetInfo to get the size and attribute of input guided section data.
504   //
505   Status = ExtractGuidedSectionGetInfo (
506              InputSection,
507              &OutputBufferSize,
508              &ScratchBufferSize,
509              &SectionAttribute
510              );
511 
512   if (EFI_ERROR (Status)) {
513     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
514     return Status;
515   }
516 
517   if (ScratchBufferSize != 0) {
518     //
519     // Allocate scratch buffer
520     //
521     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
522     if (ScratchBuffer == NULL) {
523       return EFI_OUT_OF_RESOURCES;
524     }
525   }
526 
527   if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
528     //
529     // Allocate output buffer
530     //
531     *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
532     if (*OutputBuffer == NULL) {
533       return EFI_OUT_OF_RESOURCES;
534     }
535     DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
536     //
537     // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
538     // skip EFI section header to make section data at page alignment.
539     //
540     *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
541   }
542 
543   Status = ExtractGuidedSectionDecode (
544              InputSection,
545              OutputBuffer,
546              ScratchBuffer,
547              AuthenticationStatus
548              );
549   if (EFI_ERROR (Status)) {
550     //
551     // Decode failed
552     //
553     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
554     return Status;
555   }
556 
557   *OutputSize = (UINTN) OutputBufferSize;
558 
559   return EFI_SUCCESS;
560 }
561 
562 
563 
564 /**
565    Decompresses a section to the output buffer.
566 
567    This function looks up the compression type field in the input section and
568    applies the appropriate compression algorithm to compress the section to a
569    callee allocated buffer.
570 
571    @param  This                  Points to this instance of the
572                                  EFI_PEI_DECOMPRESS_PEI PPI.
573    @param  CompressionSection    Points to the compressed section.
574    @param  OutputBuffer          Holds the returned pointer to the decompressed
575                                  sections.
576    @param  OutputSize            Holds the returned size of the decompress
577                                  section streams.
578 
579    @retval EFI_SUCCESS           The section was decompressed successfully.
580                                  OutputBuffer contains the resulting data and
581                                  OutputSize contains the resulting size.
582 
583 **/
584 EFI_STATUS
585 EFIAPI
Decompress(IN CONST EFI_PEI_DECOMPRESS_PPI * This,IN CONST EFI_COMPRESSION_SECTION * CompressionSection,OUT VOID ** OutputBuffer,OUT UINTN * OutputSize)586 Decompress (
587   IN CONST  EFI_PEI_DECOMPRESS_PPI  *This,
588   IN CONST  EFI_COMPRESSION_SECTION *CompressionSection,
589   OUT       VOID                    **OutputBuffer,
590   OUT       UINTN                   *OutputSize
591  )
592 {
593   EFI_STATUS                      Status;
594   UINT8                           *DstBuffer;
595   UINT8                           *ScratchBuffer;
596   UINT32                          DstBufferSize;
597   UINT32                          ScratchBufferSize;
598   VOID                            *CompressionSource;
599   UINT32                          CompressionSourceSize;
600   UINT32                          UncompressedLength;
601   UINT8                           CompressionType;
602 
603   if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
604     ASSERT (FALSE);
605     return EFI_INVALID_PARAMETER;
606   }
607 
608   if (IS_SECTION2 (CompressionSection)) {
609     CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
610     CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
611     UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
612     CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
613   } else {
614     CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
615     CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
616     UncompressedLength = CompressionSection->UncompressedLength;
617     CompressionType = CompressionSection->CompressionType;
618   }
619 
620   //
621   // This is a compression set, expand it
622   //
623   switch (CompressionType) {
624   case EFI_STANDARD_COMPRESSION:
625     if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {
626       //
627       // Load EFI standard compression.
628       // For compressed data, decompress them to destination buffer.
629       //
630       Status = UefiDecompressGetInfo (
631                  CompressionSource,
632                  CompressionSourceSize,
633                  &DstBufferSize,
634                  &ScratchBufferSize
635                  );
636       if (EFI_ERROR (Status)) {
637         //
638         // GetInfo failed
639         //
640         DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
641         return EFI_NOT_FOUND;
642       }
643       //
644       // Allocate scratch buffer
645       //
646       ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
647       if (ScratchBuffer == NULL) {
648         return EFI_OUT_OF_RESOURCES;
649       }
650       //
651       // Allocate destination buffer, extra one page for adjustment
652       //
653       DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
654       if (DstBuffer == NULL) {
655         return EFI_OUT_OF_RESOURCES;
656       }
657       //
658       // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
659       // to make section data at page alignment.
660       //
661       DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
662       //
663       // Call decompress function
664       //
665       Status = UefiDecompress (
666                   CompressionSource,
667                   DstBuffer,
668                   ScratchBuffer
669                   );
670       if (EFI_ERROR (Status)) {
671         //
672         // Decompress failed
673         //
674         DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
675         return EFI_NOT_FOUND;
676       }
677       break;
678     } else {
679       //
680       // PcdDxeIplSupportUefiDecompress is FALSE
681       // Don't support UEFI decompression algorithm.
682       //
683       ASSERT (FALSE);
684       return EFI_NOT_FOUND;
685     }
686 
687   case EFI_NOT_COMPRESSED:
688     //
689     // Allocate destination buffer
690     //
691     DstBufferSize = UncompressedLength;
692     DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
693     if (DstBuffer == NULL) {
694       return EFI_OUT_OF_RESOURCES;
695     }
696     //
697     // Adjust DstBuffer offset, skip EFI section header
698     // to make section data at page alignment.
699     //
700     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
701     //
702     // stream is not actually compressed, just encapsulated.  So just copy it.
703     //
704     CopyMem (DstBuffer, CompressionSource, DstBufferSize);
705     break;
706 
707   default:
708     //
709     // Don't support other unknown compression type.
710     //
711     ASSERT (FALSE);
712     return EFI_NOT_FOUND;
713   }
714 
715   *OutputSize = DstBufferSize;
716   *OutputBuffer = DstBuffer;
717 
718   return EFI_SUCCESS;
719 }
720 
721 
722 /**
723    Updates the Stack HOB passed to DXE phase.
724 
725    This function traverses the whole HOB list and update the stack HOB to
726    reflect the real stack that is used by DXE core.
727 
728    @param BaseAddress           The lower address of stack used by DxeCore.
729    @param Length                The length of stack used by DxeCore.
730 
731 **/
732 VOID
UpdateStackHob(IN EFI_PHYSICAL_ADDRESS BaseAddress,IN UINT64 Length)733 UpdateStackHob (
734   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
735   IN UINT64                      Length
736   )
737 {
738   EFI_PEI_HOB_POINTERS           Hob;
739 
740   Hob.Raw = GetHobList ();
741   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
742     if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
743       //
744       // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to
745       // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some
746       // PEIMs may also keep key information on stack
747       //
748       BuildMemoryAllocationHob (
749         Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
750         Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
751         EfiBootServicesData
752         );
753       //
754       // Update the BSP Stack Hob to reflect the new stack info.
755       //
756       Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
757       Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
758       break;
759     }
760     Hob.Raw = GET_NEXT_HOB (Hob);
761   }
762 }
763