Temporarily remove the immature "CONST" modifier.
[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 EFI_DXE_IPL_PPI mDxeIplPpi = {\r
29   DxeLoadCore\r
30 };\r
31 \r
32 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
33   CustomGuidedSectionExtract\r
34 };\r
35 \r
36 EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
37   Decompress\r
38 };\r
39 \r
40 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 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 ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
242 \r
243   //\r
244   // Transfer control to the DXE Core\r
245   // The handoff state is simply a pointer to the HOB list\r
246   //\r
247   HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
248   //\r
249   // If we get here, then the DXE Core returned.  This is an error\r
250   // Dxe Core should not return.\r
251   //\r
252   ASSERT (FALSE);\r
253   CpuDeadLoop ();\r
254 \r
255   return EFI_OUT_OF_RESOURCES;\r
256 }\r
257 \r
258 \r
259 \r
260 \r
261 /**\r
262    Find DxeCore driver from all First Volumes.\r
263 \r
264    @param FileHandle    Pointer to FFS file to search.\r
265    \r
266    @return EFI_SUCESS   Success to find the FFS in specificed FV\r
267    @return others       Fail to find the FFS in specificed FV\r
268 \r
269 **/\r
270 EFI_STATUS\r
271 DxeIplFindDxeCore (\r
272   OUT EFI_PEI_FILE_HANDLE   *FileHandle\r
273   )\r
274 {\r
275   EFI_STATUS        Status;\r
276   EFI_STATUS        FileStatus;\r
277   UINTN             Instance;\r
278   EFI_PEI_FV_HANDLE VolumeHandle;\r
279   \r
280   Instance    = 0;\r
281   *FileHandle = NULL;\r
282 \r
283   do {\r
284     Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
285     if (!EFI_ERROR (Status)) {\r
286       FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);\r
287       if (!EFI_ERROR (FileStatus)) {\r
288         return FileStatus;\r
289       }\r
290     }\r
291   } while (!EFI_ERROR (Status));\r
292 \r
293   return EFI_NOT_FOUND;\r
294 }\r
295 \r
296 \r
297 /**\r
298    Loads and relocates a PE/COFF image into memory.\r
299 \r
300    @param FileHandle        The image file handle\r
301    @param ImageAddress      The base address of the relocated PE/COFF image\r
302    @param ImageSize         The size of the relocated PE/COFF image\r
303    @param EntryPoint        The entry point of the relocated PE/COFF image\r
304    \r
305    @return EFI_SUCCESS           The file was loaded and relocated\r
306    @return EFI_OUT_OF_RESOURCES  There was not enough memory to load and relocate the PE/COFF file\r
307 \r
308 **/\r
309 EFI_STATUS\r
310 PeiLoadFile (\r
311   IN  EFI_PEI_FILE_HANDLE                       FileHandle,\r
312   OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,\r
313   OUT UINT64                                    *ImageSize,\r
314   OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint\r
315   )\r
316 {\r
317 \r
318   EFI_STATUS                        Status;\r
319   PE_COFF_LOADER_IMAGE_CONTEXT      ImageContext;\r
320   VOID                              *Pe32Data;\r
321 \r
322   //\r
323   // First try to find the PE32 section in this ffs file.\r
324   //\r
325   Status = PeiServicesFfsFindSectionData (\r
326              EFI_SECTION_PE32,\r
327              FileHandle,\r
328              &Pe32Data\r
329              );\r
330   if (EFI_ERROR (Status)) {\r
331     //\r
332     // NO image types we support so exit.\r
333     //\r
334     return Status;\r
335   }\r
336 \r
337   ZeroMem (&ImageContext, sizeof (ImageContext));\r
338   ImageContext.Handle = Pe32Data;\r
339   Status              = GetImageReadFunction (&ImageContext);\r
340 \r
341   ASSERT_EFI_ERROR (Status);\r
342 \r
343   Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
344   if (EFI_ERROR (Status)) {\r
345     return Status;\r
346   }\r
347   //\r
348   // Allocate Memory for the image\r
349   //\r
350   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
351   ASSERT (ImageContext.ImageAddress != 0);\r
352 \r
353   //\r
354   // Load the image to our new buffer\r
355   //\r
356   Status = PeCoffLoaderLoadImage (&ImageContext);\r
357   if (EFI_ERROR (Status)) {\r
358     return Status;\r
359   }\r
360   //\r
361   // Relocate the image in our new buffer\r
362   //\r
363   Status = PeCoffLoaderRelocateImage (&ImageContext);\r
364   if (EFI_ERROR (Status)) {\r
365     return Status;\r
366   }\r
367 \r
368   //\r
369   // Flush the instruction cache so the image data is written before we execute it\r
370   //\r
371   InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
372 \r
373   *ImageAddress = ImageContext.ImageAddress;\r
374   *ImageSize    = ImageContext.ImageSize;\r
375   *EntryPoint   = ImageContext.EntryPoint;\r
376 \r
377   return EFI_SUCCESS;\r
378 }\r
379 \r
380 \r
381 \r
382 \r
383 /**\r
384   The ExtractSection() function processes the input section and\r
385   returns a pointer to the section contents. If the section being\r
386   extracted does not require processing (if the section\r
387   GuidedSectionHeader.Attributes has the\r
388   EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
389   OutputBuffer is just updated to point to the start of the\r
390   section's contents. Otherwise, *Buffer must be allocated\r
391   from PEI permanent memory.\r
392 \r
393   @param This                   Indicates the\r
394                                 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
395                                 Buffer containing the input GUIDed section to be\r
396                                 processed. OutputBuffer OutputBuffer is\r
397                                 allocated from PEI permanent memory and contains\r
398                                 the new section stream.\r
399   @param InputSection           A pointer to the input buffer, which contains\r
400                                 the input section to be processed.\r
401   @param OutputBuffer           A pointer to a caller-allocated buffer, whose\r
402                                 size is specified by the contents of OutputSize.\r
403   @param OutputSize             A pointer to a caller-allocated\r
404                                 UINTN in which the size of *OutputBuffer\r
405                                 allocation is stored. If the function\r
406                                 returns anything other than EFI_SUCCESS,\r
407                                 the value of OutputSize is undefined.\r
408   @param AuthenticationStatus   A pointer to a caller-allocated\r
409                                 UINT32 that indicates the\r
410                                 authentication status of the\r
411                                 output buffer. If the input\r
412                                 section's GuidedSectionHeader.\r
413                                 Attributes field has the\r
414                                 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
415                                 bit as clear,\r
416                                 AuthenticationStatus must return\r
417                                 zero. These bits reflect the\r
418                                 status of the extraction\r
419                                 operation. If the function\r
420                                 returns anything other than\r
421                                 EFI_SUCCESS, the value of\r
422                                 AuthenticationStatus is\r
423                                 undefined.\r
424   \r
425   @retval EFI_SUCCESS           The InputSection was\r
426                                 successfully processed and the\r
427                                 section contents were returned.\r
428   \r
429   @retval EFI_OUT_OF_RESOURCES  The system has insufficient\r
430                                 resources to process the request.\r
431   \r
432   @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
433                                 not match this instance of the\r
434                                 GUIDed Section Extraction PPI.\r
435 \r
436 **/\r
437 EFI_STATUS\r
438 CustomGuidedSectionExtract (\r
439   IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
440   IN CONST  VOID                                  *InputSection,\r
441   OUT       VOID                                  **OutputBuffer,\r
442   OUT       UINTN                                 *OutputSize,\r
443   OUT       UINT32                                *AuthenticationStatus\r
444 )\r
445 {\r
446   EFI_STATUS      Status;\r
447   UINT8           *ScratchBuffer;\r
448   UINT32          ScratchBufferSize;\r
449   UINT32          OutputBufferSize;\r
450   UINT16          SectionAttribute;\r
451   \r
452   //\r
453   // Init local variable\r
454   //\r
455   ScratchBuffer = NULL;\r
456 \r
457   //\r
458   // Call GetInfo to get the size and attribute of input guided section data.\r
459   //\r
460   Status = ExtractGuidedSectionGetInfo (\r
461             InputSection,\r
462             &OutputBufferSize,\r
463             &ScratchBufferSize,\r
464             &SectionAttribute\r
465            );\r
466   \r
467   if (EFI_ERROR (Status)) {\r
468     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
469     return Status;\r
470   }\r
471   \r
472   if (ScratchBufferSize != 0) {\r
473     //\r
474     // Allocate scratch buffer\r
475     //\r
476     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
477     if (ScratchBuffer == NULL) {\r
478       return EFI_OUT_OF_RESOURCES;\r
479     }\r
480   }\r
481 \r
482   if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {  \r
483     //\r
484     // Allocate output buffer\r
485     //\r
486     *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
487     if (*OutputBuffer == NULL) {\r
488       return EFI_OUT_OF_RESOURCES;\r
489     }\r
490     DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
491     //\r
492     // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
493     // skip EFI section header to make section data at page alignment.\r
494     //\r
495     *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
496   }\r
497   \r
498   Status = ExtractGuidedSectionDecode (\r
499              InputSection, \r
500              OutputBuffer,\r
501              ScratchBuffer,\r
502              AuthenticationStatus\r
503            );\r
504   if (EFI_ERROR (Status)) {\r
505     //\r
506     // Decode failed\r
507     //\r
508     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
509     return Status;\r
510   }\r
511   \r
512   *OutputSize = (UINTN) OutputBufferSize;\r
513   \r
514   return EFI_SUCCESS;\r
515 }\r
516 \r
517 \r
518 \r
519 /**\r
520    Decompresses a section to the output buffer.\r
521 \r
522    This function lookes up the compression type field in the input section and\r
523    applies the appropriate compression algorithm to compress the section to a\r
524    callee allocated buffer.\r
525     \r
526    @param  This                  Points to this instance of the\r
527                                  EFI_PEI_DECOMPRESS_PEI PPI.\r
528    @param  CompressionSection    Points to the compressed section.\r
529    @param  OutputBuffer          Holds the returned pointer to the decompressed\r
530                                  sections.\r
531    @param  OutputSize            Holds the returned size of the decompress\r
532                                  section streams.\r
533    \r
534    @retval EFI_SUCCESS           The section was decompressed successfully.\r
535                                  OutputBuffer contains the resulting data and\r
536                                  OutputSize contains the resulting size.\r
537 \r
538 **/\r
539 EFI_STATUS\r
540 EFIAPI \r
541 Decompress (\r
542   IN CONST  EFI_PEI_DECOMPRESS_PPI  *This,\r
543   IN CONST  EFI_COMPRESSION_SECTION *CompressionSection,\r
544   OUT       VOID                    **OutputBuffer,\r
545   OUT       UINTN                   *OutputSize\r
546  )\r
547 {\r
548   EFI_STATUS                      Status;\r
549   UINT8                           *DstBuffer;\r
550   UINT8                           *ScratchBuffer;\r
551   UINTN                           DstBufferSize;\r
552   UINT32                          ScratchBufferSize;\r
553   EFI_COMMON_SECTION_HEADER       *Section;\r
554   UINTN                           SectionLength;\r
555 \r
556   if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
557     ASSERT (FALSE);\r
558     return EFI_INVALID_PARAMETER;\r
559   }\r
560 \r
561   Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
562   SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
563   \r
564   //\r
565   // This is a compression set, expand it\r
566   //\r
567   switch (CompressionSection->CompressionType) {\r
568   case EFI_STANDARD_COMPRESSION:\r
569     //\r
570     // Load EFI standard compression.\r
571     // For compressed data, decompress them to dstbuffer.\r
572     //\r
573     Status = UefiDecompressGetInfo (\r
574                (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
575                (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
576                (UINT32 *) &DstBufferSize,\r
577                &ScratchBufferSize\r
578                );\r
579     if (EFI_ERROR (Status)) {\r
580       //\r
581       // GetInfo failed\r
582       //\r
583       DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
584       return EFI_NOT_FOUND;\r
585     }\r
586     //\r
587     // Allocate scratch buffer\r
588     //\r
589     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
590     if (ScratchBuffer == NULL) {\r
591       return EFI_OUT_OF_RESOURCES;\r
592     }\r
593     //\r
594     // Allocate destination buffer, extra one page for adjustment \r
595     //\r
596     DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
597     if (DstBuffer == NULL) {\r
598       return EFI_OUT_OF_RESOURCES;\r
599     }\r
600     //\r
601     // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
602     // to make section data at page alignment.\r
603     //\r
604     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
605     //\r
606     // Call decompress function\r
607     //\r
608     Status = UefiDecompress (\r
609                 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
610                 DstBuffer,\r
611                 ScratchBuffer\r
612                 );\r
613     if (EFI_ERROR (Status)) {\r
614       //\r
615       // Decompress failed\r
616       //\r
617       DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
618       return EFI_NOT_FOUND;\r
619     }\r
620     break;\r
621 \r
622   case EFI_NOT_COMPRESSED:\r
623     //\r
624     // Allocate destination buffer\r
625     //\r
626     DstBufferSize = CompressionSection->UncompressedLength;\r
627     DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
628     if (DstBuffer == NULL) {\r
629       return EFI_OUT_OF_RESOURCES;\r
630     }\r
631     //\r
632     // Adjust DstBuffer offset, skip EFI section header\r
633     // to make section data at page alignment.\r
634     //\r
635     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
636     //\r
637     // stream is not actually compressed, just encapsulated.  So just copy it.\r
638     //\r
639     CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
640     break;\r
641 \r
642   default:\r
643     //\r
644     // Don't support other unknown compression type.\r
645     //\r
646     ASSERT (FALSE);\r
647     return EFI_NOT_FOUND;\r
648   }\r
649 \r
650   *OutputSize = DstBufferSize;\r
651   *OutputBuffer = DstBuffer;\r
652 \r
653   return EFI_SUCCESS;\r
654 }\r
655 \r
656 \r
657 \r
658 \r
659 /**\r
660    Updates the Stack HOB passed to DXE phase.\r
661 \r
662    This function traverses the whole HOB list and update the stack HOB to\r
663    reflect the real stack that is used by DXE core.\r
664 \r
665    @param BaseAddress           The lower address of stack used by DxeCore.\r
666    @param Length                The length of stack used by DxeCore.\r
667 \r
668 **/\r
669 VOID\r
670 UpdateStackHob (\r
671   IN EFI_PHYSICAL_ADDRESS        BaseAddress,\r
672   IN UINT64                      Length\r
673   )\r
674 {\r
675   EFI_PEI_HOB_POINTERS           Hob;\r
676 \r
677   Hob.Raw = GetHobList ();\r
678   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
679     if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
680       //\r
681       // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type\r
682       // to be reclaimed by DXE core.\r
683       //\r
684       BuildMemoryAllocationHob (\r
685         Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
686         Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
687         EfiConventionalMemory\r
688         );\r
689       //\r
690       // Update the BSP Stack Hob to reflect the new stack info.\r
691       //\r
692       Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
693       Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
694       break;\r
695     }\r
696     Hob.Raw = GET_NEXT_HOB (Hob);\r
697   }\r
698 }\r