]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
1. Replace PeCoffLoader library by PeCoff lib for PeiCore, DxeIpl and DxeMain.
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / DxeLoad.c
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 - 2007 Intel Corporation
6 All rights reserved. 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 #include <Ppi/GuidedSectionExtraction.h>
18 #include <FrameworkPei.h>
19
20 EFI_STATUS
21 CustomDecompressExtractSection (
22 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
23 IN CONST VOID *InputSection,
24 OUT VOID **OutputBuffer,
25 OUT UINTN *OutputSize,
26 OUT UINT32 *AuthenticationStatus
27 );
28
29 STATIC
30 EFI_STATUS
31 EFIAPI
32 Decompress (
33 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
34 IN CONST EFI_COMPRESSION_SECTION *InputSection,
35 OUT VOID **OutputBuffer,
36 OUT UINTN *OutputSize
37 );
38
39
40 BOOLEAN gInMemory = FALSE;
41
42 //
43 // Module Globals used in the DXE to PEI handoff
44 // These must be module globals, so the stack can be switched
45 //
46 static EFI_DXE_IPL_PPI mDxeIplPpi = {
47 DxeLoadCore
48 };
49
50 STATIC EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = {
51 CustomDecompressExtractSection
52 };
53
54 STATIC EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
55 Decompress
56 };
57
58 static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
59 {
60 EFI_PEI_PPI_DESCRIPTOR_PPI,
61 &gEfiDxeIplPpiGuid,
62 &mDxeIplPpi
63 },
64 {
65 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
66 &gEfiPeiDecompressPpiGuid,
67 &mDecompressPpi
68 }
69 };
70
71 static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
72 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
73 &gEfiEndOfPeiSignalPpiGuid,
74 NULL
75 };
76
77 /**
78 Initializes the Dxe Ipl PPI
79
80 @param FfsHandle The handle of FFS file.
81 @param PeiServices General purpose services available to
82 every PEIM.
83 @return EFI_SUCESS
84 */
85 EFI_STATUS
86 EFIAPI
87 PeimInitializeDxeIpl (
88 IN EFI_PEI_FILE_HANDLE FfsHandle,
89 IN EFI_PEI_SERVICES **PeiServices
90 )
91 {
92 EFI_STATUS Status;
93 EFI_BOOT_MODE BootMode;
94 EFI_GUID **DecompressGuidList;
95 UINT32 DecompressMethodNumber;
96 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
97
98 Status = PeiServicesGetBootMode (&BootMode);
99 ASSERT_EFI_ERROR (Status);
100
101 if (BootMode != BOOT_ON_S3_RESUME) {
102 Status = PeiServicesRegisterForShadow (FfsHandle);
103 if (Status == EFI_SUCCESS) {
104 //
105 // EFI_SUCESS means the first time call register for shadow
106 //
107 return Status;
108 } else if (Status == EFI_ALREADY_STARTED) {
109
110 gInMemory = TRUE;
111
112 //
113 // Get custom decompress method guid list
114 //
115 DecompressGuidList = NULL;
116 DecompressMethodNumber = 0;
117 Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
118 if (Status == EFI_OUT_OF_RESOURCES) {
119 DecompressGuidList = (EFI_GUID **) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_GUID *)));
120 ASSERT (DecompressGuidList != NULL);
121 Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);
122 }
123 ASSERT_EFI_ERROR(Status);
124
125 //
126 // Install custom decompress extraction guid ppi
127 //
128 if (DecompressMethodNumber > 0) {
129 GuidPpi = NULL;
130 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR)));
131 ASSERT (GuidPpi != NULL);
132 while (DecompressMethodNumber-- > 0) {
133 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
134 GuidPpi->Ppi = &mCustomDecompressExtractiongPpi;
135 GuidPpi->Guid = DecompressGuidList [DecompressMethodNumber];
136 Status = PeiServicesInstallPpi (GuidPpi++);
137 ASSERT_EFI_ERROR(Status);
138 }
139 }
140 } else {
141 ASSERT_EFI_ERROR (FALSE);
142 }
143 }
144
145 //
146 // Install FvFileLoader and DxeIpl PPIs.
147 //
148 Status = PeiServicesInstallPpi (mPpiList);
149 ASSERT_EFI_ERROR(Status);
150
151 return Status;
152 }
153
154 /**
155 Main entry point to last PEIM
156
157 @param This Entry point for DXE IPL PPI
158 @param PeiServices General purpose services available to every PEIM.
159 @param HobList Address to the Pei HOB list
160
161 @return EFI_SUCCESS DXE core was successfully loaded.
162 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
163 **/
164 EFI_STATUS
165 EFIAPI
166 DxeLoadCore (
167 IN EFI_DXE_IPL_PPI *This,
168 IN EFI_PEI_SERVICES **PeiServices,
169 IN EFI_PEI_HOB_POINTERS HobList
170 )
171 {
172 EFI_STATUS Status;
173 EFI_GUID DxeCoreFileName;
174 EFI_PHYSICAL_ADDRESS DxeCoreAddress;
175 UINT64 DxeCoreSize;
176 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
177 EFI_BOOT_MODE BootMode;
178 EFI_PEI_FV_HANDLE VolumeHandle;
179 EFI_PEI_FILE_HANDLE FileHandle;
180 UINTN Instance;
181
182 //
183 // if in S3 Resume, restore configure
184 //
185 Status = PeiServicesGetBootMode (&BootMode);
186 ASSERT_EFI_ERROR(Status);
187
188 if (BootMode == BOOT_ON_S3_RESUME) {
189 Status = AcpiS3ResumeOs();
190 ASSERT_EFI_ERROR (Status);
191 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
192 Status = PeiRecoverFirmware ();
193 if (EFI_ERROR (Status)) {
194 DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
195 CpuDeadLoop ();
196 }
197
198 //
199 // Now should have a HOB with the DXE core w/ the old HOB destroyed
200 //
201 }
202
203 //
204 // If any FV contains an encapsulated FV extract that FV
205 //
206 DxeIplAddEncapsulatedFirmwareVolumes ();
207
208 //
209 // Look in all the FVs present in PEI and find the DXE Core
210 //
211 Instance = 0;
212 Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
213 ASSERT_EFI_ERROR (Status);
214
215 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));
216
217 //
218 // Load the DXE Core from a Firmware Volume
219 //
220 Status = PeiLoadFile (
221 FileHandle,
222 &DxeCoreAddress,
223 &DxeCoreSize,
224 &DxeCoreEntryPoint
225 );
226
227 ASSERT_EFI_ERROR (Status);
228
229 //
230 // Add HOB for the DXE Core
231 //
232 BuildModuleHob (
233 &DxeCoreFileName,
234 DxeCoreAddress,
235 DxeCoreSize,
236 DxeCoreEntryPoint
237 );
238
239 //
240 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
241 //
242 REPORT_STATUS_CODE (
243 EFI_PROGRESS_CODE,
244 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
245 );
246
247 //
248 // Transfer control to the DXE Core
249 // The handoff state is simply a pointer to the HOB list
250 //
251 DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint));
252 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);
253 //
254 // If we get here, then the DXE Core returned. This is an error
255 // Dxe Core should not return.
256 //
257 ASSERT (FALSE);
258 CpuDeadLoop ();
259
260 return EFI_OUT_OF_RESOURCES;
261 }
262
263
264 STATIC
265 EFI_STATUS
266 GetFvAlignment (
267 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
268 OUT UINT32 *FvAlignment
269 )
270 {
271 //
272 // Because FvLength in FvHeader is UINT64 type,
273 // so FvHeader must meed at least 8 bytes alignment.
274 // Get the appropriate alignment requirement.
275 //
276 if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) {
277 return EFI_UNSUPPORTED;
278 }
279
280 *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
281 return EFI_SUCCESS;
282 }
283
284 /**
285 Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand
286 as memory FV
287
288 @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV
289 @return EFI_SUCESS Sucess to find the FV
290 **/
291 EFI_STATUS
292 DxeIplAddEncapsulatedFirmwareVolumes (
293 VOID
294 )
295 {
296 EFI_STATUS Status;
297 EFI_STATUS VolumeStatus;
298 UINTN Index;
299 EFI_FV_INFO VolumeInfo;
300 EFI_PEI_FV_HANDLE VolumeHandle;
301 EFI_PEI_FILE_HANDLE FileHandle;
302 UINT32 SectionLength;
303 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
304 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader;
305 VOID *DstBuffer;
306 UINT32 FvAlignment;
307
308 Status = EFI_NOT_FOUND;
309 Index = 0;
310
311 do {
312 VolumeStatus = DxeIplFindFirmwareVolumeInstance (
313 &Index,
314 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
315 &VolumeHandle,
316 &FileHandle
317 );
318
319 if (!EFI_ERROR (VolumeStatus)) {
320 Status = PeiServicesFfsFindSectionData (
321 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
322 (EFI_FFS_FILE_HEADER *)FileHandle,
323 (VOID **)&FvHeader
324 );
325
326 if (!EFI_ERROR (Status)) {
327 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
328 //
329 // Because FvLength in FvHeader is UINT64 type,
330 // so FvHeader must meed at least 8 bytes alignment.
331 // If current FvImage base address doesn't meet its alignment,
332 // we need to reload this FvImage to another correct memory address.
333 //
334 Status = GetFvAlignment(FvHeader, &FvAlignment);
335 if (EFI_ERROR(Status)) {
336 return Status;
337 }
338 if (((UINTN) FvHeader % FvAlignment) != 0) {
339 SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
340 SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF;
341
342 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment);
343 if (DstBuffer == NULL) {
344 return EFI_OUT_OF_RESOURCES;
345 }
346 CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER));
347 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
348 }
349
350 //
351 // This new Firmware Volume comes from a firmware file within a firmware volume.
352 // Record the original Firmware Volume Name.
353 //
354 PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo);
355
356 PeiPiLibBuildPiFvInfoPpi (
357 (EFI_PHYSICAL_ADDRESS) FvHeader,
358 FvHeader->FvLength,
359 &(VolumeInfo.FvName),
360 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)
361 );
362
363 ASSERT_EFI_ERROR (Status);
364
365 //
366 // Makes the encapsulated volume show up in DXE phase to skip processing of
367 // encapsulated file again.
368 //
369 BuildFv2Hob (
370 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
371 FvHeader->FvLength,
372 &VolumeInfo.FvName,
373 &(((EFI_FFS_FILE_HEADER *)FileHandle)->Name)
374 );
375 return Status;
376 }
377 }
378 }
379 } while (!EFI_ERROR (VolumeStatus));
380
381 return Status;
382 }
383
384 /**
385 Find the First Volume that contains the first FileType.
386
387 @param Instance The Fv instance.
388 @param SeachType The type of file to search.
389 @param VolumeHandle Pointer to Fv which contains the file to search.
390 @param FileHandle Pointer to FFS file to search.
391
392 @return EFI_SUCESS Success to find the FFS in specificed FV
393 @return others Fail to find the FFS in specificed FV
394 */
395 EFI_STATUS
396 DxeIplFindFirmwareVolumeInstance (
397 IN OUT UINTN *Instance,
398 IN EFI_FV_FILETYPE SeachType,
399 OUT EFI_PEI_FV_HANDLE *VolumeHandle,
400 OUT EFI_PEI_FILE_HANDLE *FileHandle
401 )
402 {
403 EFI_STATUS Status;
404 EFI_STATUS VolumeStatus;
405
406 do {
407 VolumeStatus = PeiServicesFfsFindNextVolume (*Instance, VolumeHandle);
408 if (!EFI_ERROR (VolumeStatus)) {
409 *FileHandle = NULL;
410 Status = PeiServicesFfsFindNextFile (SeachType, *VolumeHandle, FileHandle);
411 if (!EFI_ERROR (Status)) {
412 return Status;
413 }
414 }
415 *Instance += 1;
416 } while (!EFI_ERROR (VolumeStatus));
417
418 return VolumeStatus;
419 }
420
421 /**
422 Loads and relocates a PE/COFF image into memory.
423
424 @param FileHandle The image file handle
425 @param ImageAddress The base address of the relocated PE/COFF image
426 @param ImageSize The size of the relocated PE/COFF image
427 @param EntryPoint The entry point of the relocated PE/COFF image
428
429 @return EFI_SUCCESS The file was loaded and relocated
430 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
431 **/
432 EFI_STATUS
433 PeiLoadFile (
434 IN EFI_PEI_FILE_HANDLE FileHandle,
435 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
436 OUT UINT64 *ImageSize,
437 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
438 )
439 {
440
441 EFI_STATUS Status;
442 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
443 VOID *Pe32Data;
444 //
445 // First try to find the required section in this ffs file.
446 //
447 Status = PeiServicesFfsFindSectionData (
448 EFI_SECTION_PE32,
449 FileHandle,
450 &Pe32Data
451 );
452
453 if (EFI_ERROR (Status)) {
454 Status = PeiServicesFfsFindSectionData (
455 EFI_SECTION_TE,
456 FileHandle,
457 &Pe32Data
458 );
459 }
460
461 if (EFI_ERROR (Status)) {
462 //
463 // NO image types we support so exit.
464 //
465 return Status;
466 }
467
468 ZeroMem (&ImageContext, sizeof (ImageContext));
469 ImageContext.Handle = Pe32Data;
470 Status = GetImageReadFunction (&ImageContext);
471
472 ASSERT_EFI_ERROR (Status);
473
474 Status = PeCoffLoaderGetImageInfo (&ImageContext);
475 if (EFI_ERROR (Status)) {
476 return Status;
477 }
478 //
479 // Allocate Memory for the image
480 //
481 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
482 ASSERT (ImageContext.ImageAddress != 0);
483
484 //
485 // Load the image to our new buffer
486 //
487 Status = PeCoffLoaderLoadImage (&ImageContext);
488 if (EFI_ERROR (Status)) {
489 return Status;
490 }
491 //
492 // Relocate the image in our new buffer
493 //
494 Status = PeCoffLoaderRelocateImage (&ImageContext);
495 if (EFI_ERROR (Status)) {
496 return Status;
497 }
498
499 //
500 // Flush the instruction cache so the image data is written before we execute it
501 //
502 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
503
504 *ImageAddress = ImageContext.ImageAddress;
505 *ImageSize = ImageContext.ImageSize;
506 *EntryPoint = ImageContext.EntryPoint;
507
508 return EFI_SUCCESS;
509 }
510
511 /**
512 The ExtractSection() function processes the input section and
513 returns a pointer to the section contents. If the section being
514 extracted does not require processing (if the section
515 GuidedSectionHeader.Attributes has the
516 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
517 OutputBuffer is just updated to point to the start of the
518 section's contents. Otherwise, *Buffer must be allocated
519 from PEI permanent memory.
520
521 @param This Indicates the
522 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
523 Buffer containing the input GUIDed section to be
524 processed. OutputBuffer OutputBuffer is
525 allocated from PEI permanent memory and contains
526 the new section stream.
527
528 @param OutputSize A pointer to a caller-allocated
529 UINTN in which the size of *OutputBuffer
530 allocation is stored. If the function
531 returns anything other than EFI_SUCCESS,
532 the value of OutputSize is undefined.
533
534 @param AuthenticationStatus A pointer to a caller-allocated
535 UINT32 that indicates the
536 authentication status of the
537 output buffer. If the input
538 section's GuidedSectionHeader.
539 Attributes field has the
540 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
541 bit as clear,
542 AuthenticationStatus must return
543 zero. These bits reflect the
544 status of the extraction
545 operation. If the function
546 returns anything other than
547 EFI_SUCCESS, the value of
548 AuthenticationStatus is
549 undefined.
550
551 @retval EFI_SUCCESS The InputSection was
552 successfully processed and the
553 section contents were returned.
554
555 @retval EFI_OUT_OF_RESOURCES The system has insufficient
556 resources to process the request.
557
558 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does
559 not match this instance of the
560 GUIDed Section Extraction PPI.
561 **/
562 EFI_STATUS
563 CustomDecompressExtractSection (
564 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
565 IN CONST VOID *InputSection,
566 OUT VOID **OutputBuffer,
567 OUT UINTN *OutputSize,
568 OUT UINT32 *AuthenticationStatus
569 )
570 {
571 EFI_STATUS Status;
572 UINT8 *ScratchBuffer;
573 UINT32 ScratchSize;
574 UINT32 SectionLength;
575 UINT32 DestinationSize;
576
577 //
578 // Set authentic value to zero.
579 //
580 *AuthenticationStatus = 0;
581 //
582 // Calculate Section data Size
583 //
584 SectionLength = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;
585 //
586 // Get compressed data information
587 //
588 Status = CustomDecompressGetInfo (
589 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
590 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
591 SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),
592 &DestinationSize,
593 &ScratchSize
594 );
595 if (EFI_ERROR (Status)) {
596 //
597 // GetInfo failed
598 //
599 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
600 return Status;
601 }
602
603 //
604 // Allocate scratch buffer
605 //
606 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize));
607 if (ScratchBuffer == NULL) {
608 return EFI_OUT_OF_RESOURCES;
609 }
610 //
611 // Allocate destination buffer
612 //
613 *OutputSize = (UINTN) DestinationSize;
614 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));
615 if (*OutputBuffer == NULL) {
616 return EFI_OUT_OF_RESOURCES;
617 }
618
619 //
620 // Call decompress function
621 //
622 Status = CustomDecompress (
623 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
624 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
625 *OutputBuffer,
626 ScratchBuffer
627 );
628
629 if (EFI_ERROR (Status)) {
630 //
631 // Decompress failed
632 //
633 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
634 return Status;
635 }
636
637 return EFI_SUCCESS;
638 }
639
640 STATIC
641 EFI_STATUS
642 EFIAPI
643 Decompress (
644 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
645 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
646 OUT VOID **OutputBuffer,
647 OUT UINTN *OutputSize
648 )
649 {
650 EFI_STATUS Status;
651 UINT8 *DstBuffer;
652 UINT8 *ScratchBuffer;
653 UINTN DstBufferSize;
654 UINT32 ScratchBufferSize;
655 EFI_COMMON_SECTION_HEADER *Section;
656 UINTN SectionLength;
657
658 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
659 ASSERT (FALSE);
660 return EFI_INVALID_PARAMETER;
661 }
662
663 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;
664 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
665
666 //
667 // This is a compression set, expand it
668 //
669 switch (CompressionSection->CompressionType) {
670 case EFI_STANDARD_COMPRESSION:
671 //
672 // Load EFI standard compression.
673 // For compressed data, decompress them to dstbuffer.
674 //
675 Status = UefiDecompressGetInfo (
676 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
677 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
678 (UINT32 *) &DstBufferSize,
679 &ScratchBufferSize
680 );
681 if (EFI_ERROR (Status)) {
682 //
683 // GetInfo failed
684 //
685 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
686 return EFI_NOT_FOUND;
687 }
688 //
689 // Allocate scratch buffer
690 //
691 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
692 if (ScratchBuffer == NULL) {
693 return EFI_OUT_OF_RESOURCES;
694 }
695 //
696 // Allocate destination buffer
697 //
698 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
699 if (DstBuffer == NULL) {
700 return EFI_OUT_OF_RESOURCES;
701 }
702 //
703 // Call decompress function
704 //
705 Status = UefiDecompress (
706 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
707 DstBuffer,
708 ScratchBuffer
709 );
710 if (EFI_ERROR (Status)) {
711 //
712 // Decompress failed
713 //
714 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
715 return EFI_NOT_FOUND;
716 }
717 break;
718
719 // porting note the original branch for customized compress is removed, it should be change to use GUID compress
720
721 case EFI_NOT_COMPRESSED:
722 //
723 // Allocate destination buffer
724 //
725 DstBufferSize = CompressionSection->UncompressedLength;
726 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
727 if (DstBuffer == NULL) {
728 return EFI_OUT_OF_RESOURCES;
729 }
730 //
731 // stream is not actually compressed, just encapsulated. So just copy it.
732 //
733 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
734 break;
735
736 default:
737 //
738 // Don't support other unknown compression type.
739 //
740 ASSERT (FALSE);
741 return EFI_NOT_FOUND;
742 }
743
744 *OutputSize = DstBufferSize;
745 *OutputBuffer = DstBuffer;
746
747 return EFI_SUCCESS;
748 }
749