]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Use PeiPiLib's PeiPiLibBuildPiFvInfoPpi interface instead of installing EFI_PEI_FIRM...
[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_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
178 EFI_BOOT_MODE BootMode;
179 EFI_PEI_FV_HANDLE VolumeHandle;
180 EFI_PEI_FILE_HANDLE FileHandle;
181 UINTN Instance;
182
183 //
184 // if in S3 Resume, restore configure
185 //
186 Status = PeiServicesGetBootMode (&BootMode);
187 ASSERT_EFI_ERROR(Status);
188
189 if (BootMode == BOOT_ON_S3_RESUME) {
190 Status = AcpiS3ResumeOs();
191 ASSERT_EFI_ERROR (Status);
192 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
193 Status = PeiRecoverFirmware ();
194 if (EFI_ERROR (Status)) {
195 DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
196 CpuDeadLoop ();
197 }
198
199 //
200 // Now should have a HOB with the DXE core w/ the old HOB destroyed
201 //
202 }
203
204 //
205 // Install the PEI Protocols that are shared between PEI and DXE
206 //
207 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *) GetPeCoffLoaderProtocol ();
208 ASSERT (PeiEfiPeiPeCoffLoader != NULL);
209
210 //
211 // If any FV contains an encapsulated FV extract that FV
212 //
213 DxeIplAddEncapsulatedFirmwareVolumes ();
214
215 //
216 // Look in all the FVs present in PEI and find the DXE Core
217 //
218 Instance = 0;
219 Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
220 ASSERT_EFI_ERROR (Status);
221
222 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));
223
224 //
225 // Load the DXE Core from a Firmware Volume
226 //
227 Status = PeiLoadFile (
228 FileHandle,
229 &DxeCoreAddress,
230 &DxeCoreSize,
231 &DxeCoreEntryPoint
232 );
233
234 ASSERT_EFI_ERROR (Status);
235
236 //
237 // Add HOB for the DXE Core
238 //
239 BuildModuleHob (
240 &DxeCoreFileName,
241 DxeCoreAddress,
242 DxeCoreSize,
243 DxeCoreEntryPoint
244 );
245
246 //
247 // Add HOB for the PE/COFF Loader Protocol
248 //
249 BuildGuidDataHob (
250 &gEfiPeiPeCoffLoaderGuid,
251 (VOID *)&PeiEfiPeiPeCoffLoader,
252 sizeof (VOID *)
253 );
254 //
255 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
256 //
257 REPORT_STATUS_CODE (
258 EFI_PROGRESS_CODE,
259 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT
260 );
261
262 //
263 // Transfer control to the DXE Core
264 // The handoff state is simply a pointer to the HOB list
265 //
266 DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint));
267 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);
268 //
269 // If we get here, then the DXE Core returned. This is an error
270 // Dxe Core should not return.
271 //
272 ASSERT (FALSE);
273 CpuDeadLoop ();
274
275 return EFI_OUT_OF_RESOURCES;
276 }
277
278
279 STATIC
280 EFI_STATUS
281 GetFvAlignment (
282 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
283 OUT UINT32 *FvAlignment
284 )
285 {
286 //
287 // Because FvLength in FvHeader is UINT64 type,
288 // so FvHeader must meed at least 8 bytes alignment.
289 // Get the appropriate alignment requirement.
290 //
291 if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) {
292 return EFI_UNSUPPORTED;
293 }
294
295 *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
296 return EFI_SUCCESS;
297 }
298
299 /**
300 Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand
301 as memory FV
302
303 @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV
304 @return EFI_SUCESS Sucess to find the FV
305 **/
306 EFI_STATUS
307 DxeIplAddEncapsulatedFirmwareVolumes (
308 VOID
309 )
310 {
311 EFI_STATUS Status;
312 EFI_STATUS VolumeStatus;
313 UINTN Index;
314 EFI_FV_INFO VolumeInfo;
315 EFI_PEI_FV_HANDLE VolumeHandle;
316 EFI_PEI_FILE_HANDLE FileHandle;
317 UINT32 SectionLength;
318 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
319 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader;
320 VOID *DstBuffer;
321 UINT32 FvAlignment;
322
323 Status = EFI_NOT_FOUND;
324 Index = 0;
325
326 do {
327 VolumeStatus = DxeIplFindFirmwareVolumeInstance (
328 &Index,
329 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
330 &VolumeHandle,
331 &FileHandle
332 );
333
334 if (!EFI_ERROR (VolumeStatus)) {
335 Status = PeiServicesFfsFindSectionData (
336 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
337 (EFI_FFS_FILE_HEADER *)FileHandle,
338 (VOID **)&FvHeader
339 );
340
341 if (!EFI_ERROR (Status)) {
342 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
343 //
344 // Because FvLength in FvHeader is UINT64 type,
345 // so FvHeader must meed at least 8 bytes alignment.
346 // If current FvImage base address doesn't meet its alignment,
347 // we need to reload this FvImage to another correct memory address.
348 //
349 Status = GetFvAlignment(FvHeader, &FvAlignment);
350 if (EFI_ERROR(Status)) {
351 return Status;
352 }
353 if (((UINTN) FvHeader % FvAlignment) != 0) {
354 SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
355 SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF;
356
357 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment);
358 if (DstBuffer == NULL) {
359 return EFI_OUT_OF_RESOURCES;
360 }
361 CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER));
362 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
363 }
364
365 //
366 // This new Firmware Volume comes from a firmware file within a firmware volume.
367 // Record the original Firmware Volume Name.
368 //
369 PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo);
370
371 PeiPiLibBuildPiFvInfoPpi (
372 (EFI_PHYSICAL_ADDRESS) FvHeader,
373 FvHeader->FvLength,
374 &(VolumeInfo.FvName),
375 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)
376 );
377
378 ASSERT_EFI_ERROR (Status);
379
380 //
381 // Makes the encapsulated volume show up in DXE phase to skip processing of
382 // encapsulated file again.
383 //
384 BuildFv2Hob (
385 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
386 FvHeader->FvLength,
387 &VolumeInfo.FvName,
388 &(((EFI_FFS_FILE_HEADER *)FileHandle)->Name)
389 );
390 return Status;
391 }
392 }
393 }
394 } while (!EFI_ERROR (VolumeStatus));
395
396 return Status;
397 }
398
399 /**
400 Find the First Volume that contains the first FileType.
401
402 @param Instance The Fv instance.
403 @param SeachType The type of file to search.
404 @param VolumeHandle Pointer to Fv which contains the file to search.
405 @param FileHandle Pointer to FFS file to search.
406
407 @return EFI_SUCESS Success to find the FFS in specificed FV
408 @return others Fail to find the FFS in specificed FV
409 */
410 EFI_STATUS
411 DxeIplFindFirmwareVolumeInstance (
412 IN OUT UINTN *Instance,
413 IN EFI_FV_FILETYPE SeachType,
414 OUT EFI_PEI_FV_HANDLE *VolumeHandle,
415 OUT EFI_PEI_FILE_HANDLE *FileHandle
416 )
417 {
418 EFI_STATUS Status;
419 EFI_STATUS VolumeStatus;
420
421 do {
422 VolumeStatus = PeiServicesFfsFindNextVolume (*Instance, VolumeHandle);
423 if (!EFI_ERROR (VolumeStatus)) {
424 *FileHandle = NULL;
425 Status = PeiServicesFfsFindNextFile (SeachType, *VolumeHandle, FileHandle);
426 if (!EFI_ERROR (Status)) {
427 return Status;
428 }
429 }
430 *Instance += 1;
431 } while (!EFI_ERROR (VolumeStatus));
432
433 return VolumeStatus;
434 }
435
436 /**
437 Loads and relocates a PE/COFF image into memory.
438
439 @param FileHandle The image file handle
440 @param ImageAddress The base address of the relocated PE/COFF image
441 @param ImageSize The size of the relocated PE/COFF image
442 @param EntryPoint The entry point of the relocated PE/COFF image
443
444 @return EFI_SUCCESS The file was loaded and relocated
445 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
446 **/
447 EFI_STATUS
448 PeiLoadFile (
449 IN EFI_PEI_FILE_HANDLE FileHandle,
450 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
451 OUT UINT64 *ImageSize,
452 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
453 )
454 {
455
456 EFI_STATUS Status;
457 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
458 VOID *Pe32Data;
459 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;
460
461 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();
462 //
463 // First try to find the required section in this ffs file.
464 //
465 Status = PeiServicesFfsFindSectionData (
466 EFI_SECTION_PE32,
467 FileHandle,
468 &Pe32Data
469 );
470
471 if (EFI_ERROR (Status)) {
472 Status = PeiServicesFfsFindSectionData (
473 EFI_SECTION_TE,
474 FileHandle,
475 &Pe32Data
476 );
477 }
478
479 if (EFI_ERROR (Status)) {
480 //
481 // NO image types we support so exit.
482 //
483 return Status;
484 }
485
486 ZeroMem (&ImageContext, sizeof (ImageContext));
487 ImageContext.Handle = Pe32Data;
488 Status = GetImageReadFunction (&ImageContext);
489
490 ASSERT_EFI_ERROR (Status);
491
492 Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);
493 if (EFI_ERROR (Status)) {
494 return Status;
495 }
496 //
497 // Allocate Memory for the image
498 //
499 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
500 ASSERT (ImageContext.ImageAddress != 0);
501
502 //
503 // Load the image to our new buffer
504 //
505 Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509 //
510 // Relocate the image in our new buffer
511 //
512 Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);
513 if (EFI_ERROR (Status)) {
514 return Status;
515 }
516
517 //
518 // Flush the instruction cache so the image data is written before we execute it
519 //
520 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
521
522 *ImageAddress = ImageContext.ImageAddress;
523 *ImageSize = ImageContext.ImageSize;
524 *EntryPoint = ImageContext.EntryPoint;
525
526 return EFI_SUCCESS;
527 }
528
529 /**
530 The ExtractSection() function processes the input section and
531 returns a pointer to the section contents. If the section being
532 extracted does not require processing (if the section
533 GuidedSectionHeader.Attributes has the
534 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
535 OutputBuffer is just updated to point to the start of the
536 section's contents. Otherwise, *Buffer must be allocated
537 from PEI permanent memory.
538
539 @param This Indicates the
540 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
541 Buffer containing the input GUIDed section to be
542 processed. OutputBuffer OutputBuffer is
543 allocated from PEI permanent memory and contains
544 the new section stream.
545
546 @param OutputSize A pointer to a caller-allocated
547 UINTN in which the size of *OutputBuffer
548 allocation is stored. If the function
549 returns anything other than EFI_SUCCESS,
550 the value of OutputSize is undefined.
551
552 @param AuthenticationStatus A pointer to a caller-allocated
553 UINT32 that indicates the
554 authentication status of the
555 output buffer. If the input
556 section's GuidedSectionHeader.
557 Attributes field has the
558 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
559 bit as clear,
560 AuthenticationStatus must return
561 zero. These bits reflect the
562 status of the extraction
563 operation. If the function
564 returns anything other than
565 EFI_SUCCESS, the value of
566 AuthenticationStatus is
567 undefined.
568
569 @retval EFI_SUCCESS The InputSection was
570 successfully processed and the
571 section contents were returned.
572
573 @retval EFI_OUT_OF_RESOURCES The system has insufficient
574 resources to process the request.
575
576 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does
577 not match this instance of the
578 GUIDed Section Extraction PPI.
579 **/
580 EFI_STATUS
581 CustomDecompressExtractSection (
582 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
583 IN CONST VOID *InputSection,
584 OUT VOID **OutputBuffer,
585 OUT UINTN *OutputSize,
586 OUT UINT32 *AuthenticationStatus
587 )
588 {
589 EFI_STATUS Status;
590 UINT8 *ScratchBuffer;
591 UINT32 ScratchSize;
592 UINT32 SectionLength;
593 UINT32 DestinationSize;
594
595 //
596 // Set authentic value to zero.
597 //
598 *AuthenticationStatus = 0;
599 //
600 // Calculate Section data Size
601 //
602 SectionLength = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;
603 //
604 // Get compressed data information
605 //
606 Status = CustomDecompressGetInfo (
607 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
608 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
609 SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),
610 &DestinationSize,
611 &ScratchSize
612 );
613 if (EFI_ERROR (Status)) {
614 //
615 // GetInfo failed
616 //
617 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
618 return Status;
619 }
620
621 //
622 // Allocate scratch buffer
623 //
624 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize));
625 if (ScratchBuffer == NULL) {
626 return EFI_OUT_OF_RESOURCES;
627 }
628 //
629 // Allocate destination buffer
630 //
631 *OutputSize = (UINTN) DestinationSize;
632 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));
633 if (*OutputBuffer == NULL) {
634 return EFI_OUT_OF_RESOURCES;
635 }
636
637 //
638 // Call decompress function
639 //
640 Status = CustomDecompress (
641 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),
642 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),
643 *OutputBuffer,
644 ScratchBuffer
645 );
646
647 if (EFI_ERROR (Status)) {
648 //
649 // Decompress failed
650 //
651 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
652 return Status;
653 }
654
655 return EFI_SUCCESS;
656 }
657
658 STATIC
659 EFI_STATUS
660 EFIAPI
661 Decompress (
662 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
663 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
664 OUT VOID **OutputBuffer,
665 OUT UINTN *OutputSize
666 )
667 {
668 EFI_STATUS Status;
669 UINT8 *DstBuffer;
670 UINT8 *ScratchBuffer;
671 UINTN DstBufferSize;
672 UINT32 ScratchBufferSize;
673 EFI_COMMON_SECTION_HEADER *Section;
674 UINTN SectionLength;
675
676 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
677 ASSERT (FALSE);
678 return EFI_INVALID_PARAMETER;
679 }
680
681 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;
682 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
683
684 //
685 // This is a compression set, expand it
686 //
687 switch (CompressionSection->CompressionType) {
688 case EFI_STANDARD_COMPRESSION:
689 //
690 // Load EFI standard compression.
691 // For compressed data, decompress them to dstbuffer.
692 //
693 Status = UefiDecompressGetInfo (
694 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
695 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
696 (UINT32 *) &DstBufferSize,
697 &ScratchBufferSize
698 );
699 if (EFI_ERROR (Status)) {
700 //
701 // GetInfo failed
702 //
703 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
704 return EFI_NOT_FOUND;
705 }
706 //
707 // Allocate scratch buffer
708 //
709 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
710 if (ScratchBuffer == NULL) {
711 return EFI_OUT_OF_RESOURCES;
712 }
713 //
714 // Allocate destination buffer
715 //
716 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
717 if (DstBuffer == NULL) {
718 return EFI_OUT_OF_RESOURCES;
719 }
720 //
721 // Call decompress function
722 //
723 Status = UefiDecompress (
724 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
725 DstBuffer,
726 ScratchBuffer
727 );
728 if (EFI_ERROR (Status)) {
729 //
730 // Decompress failed
731 //
732 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
733 return EFI_NOT_FOUND;
734 }
735 break;
736
737 // porting note the original branch for customized compress is removed, it should be change to use GUID compress
738
739 case EFI_NOT_COMPRESSED:
740 //
741 // Allocate destination buffer
742 //
743 DstBufferSize = CompressionSection->UncompressedLength;
744 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
745 if (DstBuffer == NULL) {
746 return EFI_OUT_OF_RESOURCES;
747 }
748 //
749 // stream is not actually compressed, just encapsulated. So just copy it.
750 //
751 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
752 break;
753
754 default:
755 //
756 // Don't support other unknown compression type.
757 //
758 ASSERT (FALSE);
759 return EFI_NOT_FOUND;
760 }
761
762 *OutputSize = DstBufferSize;
763 *OutputBuffer = DstBuffer;
764
765 return EFI_SUCCESS;
766 }
767