Make RTC module pass build.
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Core / DxeIplPeim / DxeLoad.c
1 /** @file\r
2   Last PEIM.\r
3   Responsibility of this module is to load the DXE Core from a Firmware Volume.\r
4 \r
5 Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 #include "DxeIpl.h"\r
17 \r
18 //\r
19 // This global variable indicates whether this module has been shadowed\r
20 // to memory.\r
21 //\r
22 BOOLEAN gInMemory = FALSE;\r
23 \r
24 //\r
25 // Module Globals used in the DXE to PEI handoff\r
26 // These must be module globals, so the stack can be switched\r
27 //\r
28 CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
29   DxeLoadCore\r
30 };\r
31 \r
32 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
33   CustomGuidedSectionExtract\r
34 };\r
35 \r
36 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
37   Decompress\r
38 };\r
39 \r
40 CONST EFI_PEI_PPI_DESCRIPTOR     mPpiList[] = {\r
41   {\r
42     EFI_PEI_PPI_DESCRIPTOR_PPI,\r
43     &gEfiDxeIplPpiGuid,\r
44     &mDxeIplPpi\r
45   },\r
46   {\r
47     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
48     &gEfiPeiDecompressPpiGuid,\r
49     &mDecompressPpi\r
50   }\r
51 };\r
52 \r
53 CONST EFI_PEI_PPI_DESCRIPTOR     mPpiSignal = {\r
54   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
55   &gEfiEndOfPeiSignalPpiGuid,\r
56   NULL\r
57 };\r
58 \r
59 /**\r
60   Initializes the Dxe Ipl PPI\r
61 \r
62   @param  FfsHandle   The handle of FFS file.\r
63   @param  PeiServices General purpose services available to\r
64                       every PEIM.\r
65   @return EFI_SUCESS\r
66 \r
67 **/\r
68 EFI_STATUS\r
69 EFIAPI\r
70 PeimInitializeDxeIpl (\r
71   IN EFI_PEI_FILE_HANDLE       FfsHandle,\r
72   IN EFI_PEI_SERVICES          **PeiServices\r
73   )\r
74 {\r
75   EFI_STATUS                                Status;\r
76   EFI_BOOT_MODE                             BootMode;\r
77   EFI_GUID                                  *ExtractHandlerGuidTable;\r
78   UINTN                                     ExtractHandlerNumber;\r
79   EFI_PEI_PPI_DESCRIPTOR                    *GuidPpi;\r
80   \r
81   BootMode = GetBootModeHob ();\r
82 \r
83   if (BootMode != BOOT_ON_S3_RESUME) {\r
84     Status = PeiServicesRegisterForShadow (FfsHandle);\r
85     if (Status == EFI_SUCCESS) {\r
86       //\r
87       // EFI_SUCESS means the first time call register for shadow \r
88       // \r
89       return Status;\r
90     } else if (Status == EFI_ALREADY_STARTED) {\r
91      \r
92       //\r
93       // Get custom extract guided section method guid list \r
94       //\r
95       ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
96       \r
97       //\r
98       // Install custom extraction guid ppi\r
99       //\r
100       if (ExtractHandlerNumber > 0) {\r
101         GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
102         ASSERT (GuidPpi != NULL);\r
103         while (ExtractHandlerNumber-- > 0) {\r
104           GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
105           GuidPpi->Ppi   = &mCustomGuidedSectionExtractionPpi;\r
106           GuidPpi->Guid  = &(ExtractHandlerGuidTable [ExtractHandlerNumber]);\r
107           Status = PeiServicesInstallPpi (GuidPpi++);\r
108           ASSERT_EFI_ERROR(Status);\r
109         }\r
110       }\r
111     } else {\r
112       ASSERT (FALSE);\r
113     }\r
114   }\r
115   \r
116   //\r
117   // Install DxeIpl and Decompress PPIs.\r
118   //\r
119   Status = PeiServicesInstallPpi (mPpiList);\r
120   ASSERT_EFI_ERROR(Status);\r
121 \r
122   return Status;\r
123 }\r
124 \r
125 /**\r
126    Main entry point to last PEIM. \r
127     \r
128    @param This          Entry point for DXE IPL PPI.\r
129    @param PeiServices   General purpose services available to every PEIM.\r
130    @param HobList       Address to the Pei HOB list.\r
131    \r
132    @return EFI_SUCCESS              DXE core was successfully loaded. \r
133    @return EFI_OUT_OF_RESOURCES     There are not enough resources to load DXE core.\r
134 \r
135 **/\r
136 EFI_STATUS\r
137 EFIAPI\r
138 DxeLoadCore (\r
139   IN EFI_DXE_IPL_PPI       *This,\r
140   IN EFI_PEI_SERVICES      **PeiServices,\r
141   IN EFI_PEI_HOB_POINTERS  HobList\r
142   )\r
143 {\r
144   EFI_STATUS                                Status;\r
145   EFI_GUID                                  DxeCoreFileName;\r
146   EFI_PHYSICAL_ADDRESS                      DxeCoreAddress;\r
147   UINT64                                    DxeCoreSize;\r
148   EFI_PHYSICAL_ADDRESS                      DxeCoreEntryPoint;\r
149   EFI_BOOT_MODE                             BootMode;\r
150   EFI_PEI_FILE_HANDLE                       FileHandle;\r
151   EFI_PEI_READ_ONLY_VARIABLE2_PPI           *Variable;\r
152   UINTN                                     DataSize;\r
153   EFI_MEMORY_TYPE_INFORMATION               MemoryData[EfiMaxMemoryType + 1];\r
154 \r
155   //\r
156   // if in S3 Resume, restore configure\r
157   //\r
158   BootMode = GetBootModeHob ();\r
159 \r
160   if (BootMode == BOOT_ON_S3_RESUME) {\r
161     Status = AcpiS3ResumeOs();\r
162     ASSERT_EFI_ERROR (Status);\r
163   } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
164     Status = PeiRecoverFirmware ();\r
165     if (EFI_ERROR (Status)) {\r
166       DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
167       CpuDeadLoop ();\r
168     }\r
169 \r
170     //\r
171     // Now should have a HOB with the DXE core w/ the old HOB destroyed\r
172     //\r
173   }\r
174 \r
175   Status = PeiServicesLocatePpi (\r
176              &gEfiPeiReadOnlyVariable2PpiGuid,\r
177              0,\r
178              NULL,\r
179              (VOID **)&Variable\r
180              );\r
181   if (!EFI_ERROR (Status)) {\r
182     DataSize = sizeof (MemoryData);\r
183     Status = Variable->GetVariable ( \r
184                          Variable, \r
185                          EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
186                          &gEfiMemoryTypeInformationGuid,\r
187                          NULL,\r
188                          &DataSize,\r
189                          &MemoryData\r
190                          );\r
191     if (!EFI_ERROR (Status)) {\r
192       //\r
193       // Build the GUID'd HOB for DXE\r
194       //\r
195       BuildGuidDataHob (\r
196         &gEfiMemoryTypeInformationGuid,\r
197         MemoryData,\r
198         DataSize\r
199         );\r
200     }\r
201   }\r
202 \r
203   //\r
204   // Look in all the FVs present in PEI and find the DXE Core\r
205   //\r
206   FileHandle = NULL;\r
207   Status = DxeIplFindDxeCore (&FileHandle);\r
208   ASSERT_EFI_ERROR (Status);\r
209 \r
210   CopyGuid(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name));\r
211 \r
212   //\r
213   // Load the DXE Core from a Firmware Volume, may use LoadFile ppi to do this for save code size.\r
214   //\r
215   Status = PeiLoadFile (\r
216              FileHandle,\r
217              &DxeCoreAddress,\r
218              &DxeCoreSize,\r
219              &DxeCoreEntryPoint\r
220              );\r
221   ASSERT_EFI_ERROR (Status);\r
222 \r
223   //\r
224   // Add HOB for the DXE Core\r
225   //\r
226   BuildModuleHob (\r
227     &DxeCoreFileName,\r
228     DxeCoreAddress,\r
229     EFI_SIZE_TO_PAGES ((UINTN) DxeCoreSize) * EFI_PAGE_SIZE,\r
230     DxeCoreEntryPoint\r
231     );\r
232 \r
233   //\r
234   // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
235   //\r
236   REPORT_STATUS_CODE (\r
237     EFI_PROGRESS_CODE,\r
238     PcdGet32(PcdStatusCodeValuePeiHandoffToDxe)\r
239     );\r
240 \r
241   DEBUG_CODE_BEGIN ();\r
242 \r
243     EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION       PtrPeImage;\r
244     PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);\r
245      \r
246     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
247    \r
248 \r
249   DEBUG_CODE_END ();\r
250   //\r
251   // Transfer control to the DXE Core\r
252   // The handoff state is simply a pointer to the HOB list\r
253   //\r
254   HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
255   //\r
256   // If we get here, then the DXE Core returned.  This is an error\r
257   // Dxe Core should not return.\r
258   //\r
259   ASSERT (FALSE);\r
260   CpuDeadLoop ();\r
261 \r
262   return EFI_OUT_OF_RESOURCES;\r
263 }\r
264 \r
265 \r
266 \r
267 \r
268 /**\r
269    Find DxeCore driver from all First Volumes.\r
270 \r
271    @param FileHandle    Pointer to FFS file to search.\r
272    \r
273    @return EFI_SUCESS   Success to find the FFS in specificed FV\r
274    @return others       Fail to find the FFS in specificed FV\r
275 \r
276 **/\r
277 EFI_STATUS\r
278 DxeIplFindDxeCore (\r
279   OUT EFI_PEI_FILE_HANDLE   *FileHandle\r
280   )\r
281 {\r
282   EFI_STATUS        Status;\r
283   EFI_STATUS        FileStatus;\r
284   UINTN             Instance;\r
285   EFI_PEI_FV_HANDLE VolumeHandle;\r
286   \r
287   Instance    = 0;\r
288   *FileHandle = NULL;\r
289 \r
290   do {\r
291     Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
292     if (!EFI_ERROR (Status)) {\r
293       FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);\r
294       if (!EFI_ERROR (FileStatus)) {\r
295         return FileStatus;\r
296       }\r
297     }\r
298   } while (!EFI_ERROR (Status));\r
299 \r
300   return EFI_NOT_FOUND;\r
301 }\r
302 \r
303 \r
304 /**\r
305    Loads and relocates a PE/COFF image into memory.\r
306 \r
307    @param FileHandle        The image file handle\r
308    @param ImageAddress      The base address of the relocated PE/COFF image\r
309    @param ImageSize         The size of the relocated PE/COFF image\r
310    @param EntryPoint        The entry point of the relocated PE/COFF image\r
311    \r
312    @return EFI_SUCCESS           The file was loaded and relocated\r
313    @return EFI_OUT_OF_RESOURCES  There was not enough memory to load and relocate the PE/COFF file\r
314 \r
315 **/\r
316 EFI_STATUS\r
317 PeiLoadFile (\r
318   IN  EFI_PEI_FILE_HANDLE                       FileHandle,\r
319   OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,\r
320   OUT UINT64                                    *ImageSize,\r
321   OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint\r
322   )\r
323 {\r
324 \r
325   EFI_STATUS                        Status;\r
326   PE_COFF_LOADER_IMAGE_CONTEXT      ImageContext;\r
327   VOID                              *Pe32Data;\r
328 \r
329   //\r
330   // First try to find the PE32 section in this ffs file.\r
331   //\r
332   Status = PeiServicesFfsFindSectionData (\r
333              EFI_SECTION_PE32,\r
334              FileHandle,\r
335              &Pe32Data\r
336              );\r
337   if (EFI_ERROR (Status)) {\r
338     //\r
339     // NO image types we support so exit.\r
340     //\r
341     return Status;\r
342   }\r
343 \r
344   ZeroMem (&ImageContext, sizeof (ImageContext));\r
345   ImageContext.Handle = Pe32Data;\r
346   Status              = GetImageReadFunction (&ImageContext);\r
347 \r
348   ASSERT_EFI_ERROR (Status);\r
349 \r
350   Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
351   if (EFI_ERROR (Status)) {\r
352     return Status;\r
353   }\r
354   //\r
355   // Allocate Memory for the image\r
356   //\r
357   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
358   ASSERT (ImageContext.ImageAddress != 0);\r
359 \r
360   //\r
361   // Load the image to our new buffer\r
362   //\r
363   Status = PeCoffLoaderLoadImage (&ImageContext);\r
364   if (EFI_ERROR (Status)) {\r
365     return Status;\r
366   }\r
367   //\r
368   // Relocate the image in our new buffer\r
369   //\r
370   Status = PeCoffLoaderRelocateImage (&ImageContext);\r
371   if (EFI_ERROR (Status)) {\r
372     return Status;\r
373   }\r
374 \r
375   //\r
376   // Flush the instruction cache so the image data is written before we execute it\r
377   //\r
378   InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
379 \r
380   *ImageAddress = ImageContext.ImageAddress;\r
381   *ImageSize    = ImageContext.ImageSize;\r
382   *EntryPoint   = ImageContext.EntryPoint;\r
383 \r
384   return EFI_SUCCESS;\r
385 }\r
386 \r
387 \r
388 \r
389 \r
390 /**\r
391   The ExtractSection() function processes the input section and\r
392   returns a pointer to the section contents. If the section being\r
393   extracted does not require processing (if the section\r
394   GuidedSectionHeader.Attributes has the\r
395   EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
396   OutputBuffer is just updated to point to the start of the\r
397   section's contents. Otherwise, *Buffer must be allocated\r
398   from PEI permanent memory.\r
399 \r
400   @param This                   Indicates the\r
401                                 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
402                                 Buffer containing the input GUIDed section to be\r
403                                 processed. OutputBuffer OutputBuffer is\r
404                                 allocated from PEI permanent memory and contains\r
405                                 the new section stream.\r
406   @param InputSection           A pointer to the input buffer, which contains\r
407                                 the input section to be processed.\r
408   @param OutputBuffer           A pointer to a caller-allocated buffer, whose\r
409                                 size is specified by the contents of OutputSize.\r
410   @param OutputSize             A pointer to a caller-allocated\r
411                                 UINTN in which the size of *OutputBuffer\r
412                                 allocation is stored. If the function\r
413                                 returns anything other than EFI_SUCCESS,\r
414                                 the value of OutputSize is undefined.\r
415   @param AuthenticationStatus   A pointer to a caller-allocated\r
416                                 UINT32 that indicates the\r
417                                 authentication status of the\r
418                                 output buffer. If the input\r
419                                 section's GuidedSectionHeader.\r
420                                 Attributes field has the\r
421                                 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
422                                 bit as clear,\r
423                                 AuthenticationStatus must return\r
424                                 zero. These bits reflect the\r
425                                 status of the extraction\r
426                                 operation. If the function\r
427                                 returns anything other than\r
428                                 EFI_SUCCESS, the value of\r
429                                 AuthenticationStatus is\r
430                                 undefined.\r
431   \r
432   @retval EFI_SUCCESS           The InputSection was\r
433                                 successfully processed and the\r
434                                 section contents were returned.\r
435   \r
436   @retval EFI_OUT_OF_RESOURCES  The system has insufficient\r
437                                 resources to process the request.\r
438   \r
439   @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
440                                 not match this instance of the\r
441                                 GUIDed Section Extraction PPI.\r
442 \r
443 **/\r
444 EFI_STATUS\r
445 CustomGuidedSectionExtract (\r
446   IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
447   IN CONST  VOID                                  *InputSection,\r
448   OUT       VOID                                  **OutputBuffer,\r
449   OUT       UINTN                                 *OutputSize,\r
450   OUT       UINT32                                *AuthenticationStatus\r
451 )\r
452 {\r
453   EFI_STATUS      Status;\r
454   UINT8           *ScratchBuffer;\r
455   UINT32          ScratchBufferSize;\r
456   UINT32          OutputBufferSize;\r
457   UINT16          SectionAttribute;\r
458   \r
459   //\r
460   // Init local variable\r
461   //\r
462   ScratchBuffer = NULL;\r
463 \r
464   //\r
465   // Call GetInfo to get the size and attribute of input guided section data.\r
466   //\r
467   Status = ExtractGuidedSectionGetInfo (\r
468             InputSection,\r
469             &OutputBufferSize,\r
470             &ScratchBufferSize,\r
471             &SectionAttribute\r
472            );\r
473   \r
474   if (EFI_ERROR (Status)) {\r
475     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
476     return Status;\r
477   }\r
478   \r
479   if (ScratchBufferSize != 0) {\r
480     //\r
481     // Allocate scratch buffer\r
482     //\r
483     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
484     if (ScratchBuffer == NULL) {\r
485       return EFI_OUT_OF_RESOURCES;\r
486     }\r
487   }\r
488 \r
489   if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {  \r
490     //\r
491     // Allocate output buffer\r
492     //\r
493     *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
494     if (*OutputBuffer == NULL) {\r
495       return EFI_OUT_OF_RESOURCES;\r
496     }\r
497     DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
498     //\r
499     // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
500     // skip EFI section header to make section data at page alignment.\r
501     //\r
502     *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
503   }\r
504   \r
505   Status = ExtractGuidedSectionDecode (\r
506              InputSection, \r
507              OutputBuffer,\r
508              ScratchBuffer,\r
509              AuthenticationStatus\r
510            );\r
511   if (EFI_ERROR (Status)) {\r
512     //\r
513     // Decode failed\r
514     //\r
515     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
516     return Status;\r
517   }\r
518   \r
519   *OutputSize = (UINTN) OutputBufferSize;\r
520   \r
521   return EFI_SUCCESS;\r
522 }\r
523 \r
524 \r
525 \r
526 /**\r
527    Decompresses a section to the output buffer.\r
528 \r
529    This function lookes up the compression type field in the input section and\r
530    applies the appropriate compression algorithm to compress the section to a\r
531    callee allocated buffer.\r
532     \r
533    @param  This                  Points to this instance of the\r
534                                  EFI_PEI_DECOMPRESS_PEI PPI.\r
535    @param  CompressionSection    Points to the compressed section.\r
536    @param  OutputBuffer          Holds the returned pointer to the decompressed\r
537                                  sections.\r
538    @param  OutputSize            Holds the returned size of the decompress\r
539                                  section streams.\r
540    \r
541    @retval EFI_SUCCESS           The section was decompressed successfully.\r
542                                  OutputBuffer contains the resulting data and\r
543                                  OutputSize contains the resulting size.\r
544 \r
545 **/\r
546 EFI_STATUS\r
547 EFIAPI \r
548 Decompress (\r
549   IN CONST  EFI_PEI_DECOMPRESS_PPI  *This,\r
550   IN CONST  EFI_COMPRESSION_SECTION *CompressionSection,\r
551   OUT       VOID                    **OutputBuffer,\r
552   OUT       UINTN                   *OutputSize\r
553  )\r
554 {\r
555   EFI_STATUS                      Status;\r
556   UINT8                           *DstBuffer;\r
557   UINT8                           *ScratchBuffer;\r
558   UINTN                           DstBufferSize;\r
559   UINT32                          ScratchBufferSize;\r
560   EFI_COMMON_SECTION_HEADER       *Section;\r
561   UINTN                           SectionLength;\r
562 \r
563   if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
564     ASSERT (FALSE);\r
565     return EFI_INVALID_PARAMETER;\r
566   }\r
567 \r
568   Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
569   SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
570   \r
571   //\r
572   // This is a compression set, expand it\r
573   //\r
574   switch (CompressionSection->CompressionType) {\r
575   case EFI_STANDARD_COMPRESSION:\r
576     //\r
577     // Load EFI standard compression.\r
578     // For compressed data, decompress them to dstbuffer.\r
579     //\r
580     Status = UefiDecompressGetInfo (\r
581                (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
582                (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
583                (UINT32 *) &DstBufferSize,\r
584                &ScratchBufferSize\r
585                );\r
586     if (EFI_ERROR (Status)) {\r
587       //\r
588       // GetInfo failed\r
589       //\r
590       DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
591       return EFI_NOT_FOUND;\r
592     }\r
593     //\r
594     // Allocate scratch buffer\r
595     //\r
596     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
597     if (ScratchBuffer == NULL) {\r
598       return EFI_OUT_OF_RESOURCES;\r
599     }\r
600     //\r
601     // Allocate destination buffer, extra one page for adjustment \r
602     //\r
603     DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
604     if (DstBuffer == NULL) {\r
605       return EFI_OUT_OF_RESOURCES;\r
606     }\r
607     //\r
608     // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
609     // to make section data at page alignment.\r
610     //\r
611     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
612     //\r
613     // Call decompress function\r
614     //\r
615     Status = UefiDecompress (\r
616                 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
617                 DstBuffer,\r
618                 ScratchBuffer\r
619                 );\r
620     if (EFI_ERROR (Status)) {\r
621       //\r
622       // Decompress failed\r
623       //\r
624       DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
625       return EFI_NOT_FOUND;\r
626     }\r
627     break;\r
628 \r
629   case EFI_NOT_COMPRESSED:\r
630     //\r
631     // Allocate destination buffer\r
632     //\r
633     DstBufferSize = CompressionSection->UncompressedLength;\r
634     DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
635     if (DstBuffer == NULL) {\r
636       return EFI_OUT_OF_RESOURCES;\r
637     }\r
638     //\r
639     // Adjust DstBuffer offset, skip EFI section header\r
640     // to make section data at page alignment.\r
641     //\r
642     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
643     //\r
644     // stream is not actually compressed, just encapsulated.  So just copy it.\r
645     //\r
646     CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
647     break;\r
648 \r
649   default:\r
650     //\r
651     // Don't support other unknown compression type.\r
652     //\r
653     ASSERT (FALSE);\r
654     return EFI_NOT_FOUND;\r
655   }\r
656 \r
657   *OutputSize = DstBufferSize;\r
658   *OutputBuffer = DstBuffer;\r
659 \r
660   return EFI_SUCCESS;\r
661 }\r
662 \r
663 \r
664 \r
665 \r
666 /**\r
667    Updates the Stack HOB passed to DXE phase.\r
668 \r
669    This function traverses the whole HOB list and update the stack HOB to\r
670    reflect the real stack that is used by DXE core.\r
671 \r
672    @param BaseAddress           The lower address of stack used by DxeCore.\r
673    @param Length                The length of stack used by DxeCore.\r
674 \r
675 **/\r
676 VOID\r
677 UpdateStackHob (\r
678   IN EFI_PHYSICAL_ADDRESS        BaseAddress,\r
679   IN UINT64                      Length\r
680   )\r
681 {\r
682   EFI_PEI_HOB_POINTERS           Hob;\r
683 \r
684   Hob.Raw = GetHobList ();\r
685   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
686     if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
687       //\r
688       // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type\r
689       // to be reclaimed by DXE core.\r
690       //\r
691       BuildMemoryAllocationHob (\r
692         Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
693         Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
694         EfiConventionalMemory\r
695         );\r
696       //\r
697       // Update the BSP Stack Hob to reflect the new stack info.\r
698       //\r
699       Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
700       Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
701       break;\r
702     }\r
703     Hob.Raw = GET_NEXT_HOB (Hob);\r
704   }\r
705 }\r