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