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