]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Print real entry point for IPF image.
[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 DEBUG_CODE_BEGIN ();
240
241 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;
242 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);
243
244 if (PtrPeImage.Pe32->FileHeader.Machine != IMAGE_FILE_MACHINE_IA64) {
245 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DXE CORE at 0x%08x EntryPoint=0x%08x\n", (UINTN) DxeCoreAddress, (UINTN) DxeCoreEntryPoint));
246 } else {
247 //
248 // For IPF Image, the real entry point should be print.
249 //
250 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DXE CORE at 0x%08x EntryPoint=0x%08x\n", (UINTN) DxeCoreAddress, (UINTN) (*(UINT64 *)(UINTN)DxeCoreEntryPoint)));
251 }
252
253 DEBUG_CODE_END ();
254 //
255 // Transfer control to the DXE Core
256 // The handoff state is simply a pointer to the HOB list
257 //
258 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);
259 //
260 // If we get here, then the DXE Core returned. This is an error
261 // Dxe Core should not return.
262 //
263 ASSERT (FALSE);
264 CpuDeadLoop ();
265
266 return EFI_OUT_OF_RESOURCES;
267 }
268
269
270 STATIC
271 EFI_STATUS
272 GetFvAlignment (
273 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
274 OUT UINT32 *FvAlignment
275 )
276 {
277 //
278 // Because FvLength in FvHeader is UINT64 type,
279 // so FvHeader must meed at least 8 bytes alignment.
280 // Get the appropriate alignment requirement.
281 //
282 if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) {
283 return EFI_UNSUPPORTED;
284 }
285
286 *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
287 return EFI_SUCCESS;
288 }
289
290 /**
291 Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand
292 as memory FV
293
294 @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV
295 @return EFI_SUCESS Sucess to find the FV
296 **/
297 EFI_STATUS
298 DxeIplAddEncapsulatedFirmwareVolumes (
299 VOID
300 )
301 {
302 EFI_STATUS Status;
303 EFI_STATUS VolumeStatus;
304 UINTN Index;
305 EFI_FV_INFO VolumeInfo;
306 EFI_PEI_FV_HANDLE VolumeHandle;
307 EFI_PEI_FILE_HANDLE FileHandle;
308 UINT32 SectionLength;
309 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
310 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader;
311 VOID *DstBuffer;
312 UINT32 FvAlignment;
313
314 Status = EFI_NOT_FOUND;
315 Index = 0;
316
317 do {
318 VolumeStatus = DxeIplFindFirmwareVolumeInstance (
319 &Index,
320 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
321 &VolumeHandle,
322 &FileHandle
323 );
324
325 if (!EFI_ERROR (VolumeStatus)) {
326 Status = PeiServicesFfsFindSectionData (
327 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
328 (EFI_FFS_FILE_HEADER *)FileHandle,
329 (VOID **)&FvHeader
330 );
331
332 if (!EFI_ERROR (Status)) {
333 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
334 //
335 // Because FvLength in FvHeader is UINT64 type,
336 // so FvHeader must meed at least 8 bytes alignment.
337 // If current FvImage base address doesn't meet its alignment,
338 // we need to reload this FvImage to another correct memory address.
339 //
340 Status = GetFvAlignment(FvHeader, &FvAlignment);
341 if (EFI_ERROR(Status)) {
342 return Status;
343 }
344 if (((UINTN) FvHeader % FvAlignment) != 0) {
345 SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
346 SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF;
347
348 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment);
349 if (DstBuffer == NULL) {
350 return EFI_OUT_OF_RESOURCES;
351 }
352 CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER));
353 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;
354 }
355
356 //
357 // This new Firmware Volume comes from a firmware file within a firmware volume.
358 // Record the original Firmware Volume Name.
359 //
360 PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo);
361
362 PiLibInstallFvInfoPpi (
363 NULL,
364 FvHeader,
365 (UINT32) FvHeader->FvLength,
366 &(VolumeInfo.FvName),
367 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)
368 );
369
370 //
371 // Inform HOB consumer phase, i.e. DXE core, the existance of this FV
372 //
373 BuildFvHob (
374 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
375 FvHeader->FvLength
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 //
460 // First try to find the required section in this ffs file.
461 //
462 Status = PeiServicesFfsFindSectionData (
463 EFI_SECTION_PE32,
464 FileHandle,
465 &Pe32Data
466 );
467
468 if (EFI_ERROR (Status)) {
469 Status = PeiServicesFfsFindSectionData (
470 EFI_SECTION_TE,
471 FileHandle,
472 &Pe32Data
473 );
474 }
475
476 if (EFI_ERROR (Status)) {
477 //
478 // NO image types we support so exit.
479 //
480 return Status;
481 }
482
483 ZeroMem (&ImageContext, sizeof (ImageContext));
484 ImageContext.Handle = Pe32Data;
485 Status = GetImageReadFunction (&ImageContext);
486
487 ASSERT_EFI_ERROR (Status);
488
489 Status = PeCoffLoaderGetImageInfo (&ImageContext);
490 if (EFI_ERROR (Status)) {
491 return Status;
492 }
493 //
494 // Allocate Memory for the image
495 //
496 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
497 ASSERT (ImageContext.ImageAddress != 0);
498
499 //
500 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.
501 //
502 if (ImageContext.IsTeImage) {
503 ImageContext.ImageAddress = ImageContext.ImageAddress +
504 ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -
505 sizeof (EFI_TE_IMAGE_HEADER);
506 }
507
508 //
509 // Load the image to our new buffer
510 //
511 Status = PeCoffLoaderLoadImage (&ImageContext);
512 if (EFI_ERROR (Status)) {
513 return Status;
514 }
515 //
516 // Relocate the image in our new buffer
517 //
518 Status = PeCoffLoaderRelocateImage (&ImageContext);
519 if (EFI_ERROR (Status)) {
520 return Status;
521 }
522
523 //
524 // Flush the instruction cache so the image data is written before we execute it
525 //
526 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
527
528 *ImageAddress = ImageContext.ImageAddress;
529 *ImageSize = ImageContext.ImageSize;
530 *EntryPoint = ImageContext.EntryPoint;
531
532 return EFI_SUCCESS;
533 }
534
535 /**
536 The ExtractSection() function processes the input section and
537 returns a pointer to the section contents. If the section being
538 extracted does not require processing (if the section
539 GuidedSectionHeader.Attributes has the
540 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
541 OutputBuffer is just updated to point to the start of the
542 section's contents. Otherwise, *Buffer must be allocated
543 from PEI permanent memory.
544
545 @param This Indicates the
546 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
547 Buffer containing the input GUIDed section to be
548 processed. OutputBuffer OutputBuffer is
549 allocated from PEI permanent memory and contains
550 the new section stream.
551
552 @param OutputSize A pointer to a caller-allocated
553 UINTN in which the size of *OutputBuffer
554 allocation is stored. If the function
555 returns anything other than EFI_SUCCESS,
556 the value of OutputSize is undefined.
557
558 @param AuthenticationStatus A pointer to a caller-allocated
559 UINT32 that indicates the
560 authentication status of the
561 output buffer. If the input
562 section's GuidedSectionHeader.
563 Attributes field has the
564 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
565 bit as clear,
566 AuthenticationStatus must return
567 zero. These bits reflect the
568 status of the extraction
569 operation. If the function
570 returns anything other than
571 EFI_SUCCESS, the value of
572 AuthenticationStatus is
573 undefined.
574
575 @retval EFI_SUCCESS The InputSection was
576 successfully processed and the
577 section contents were returned.
578
579 @retval EFI_OUT_OF_RESOURCES The system has insufficient
580 resources to process the request.
581
582 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does
583 not match this instance of the
584 GUIDed Section Extraction PPI.
585 **/
586 EFI_STATUS
587 CustomGuidedSectionExtract (
588 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
589 IN CONST VOID *InputSection,
590 OUT VOID **OutputBuffer,
591 OUT UINTN *OutputSize,
592 OUT UINT32 *AuthenticationStatus
593 )
594 {
595 EFI_STATUS Status;
596 UINT8 *ScratchBuffer;
597 UINT32 ScratchBufferSize;
598 UINT32 OutputBufferSize;
599 UINT16 SectionAttribute;
600
601 //
602 // Init local variable
603 //
604 ScratchBuffer = NULL;
605
606 //
607 // Call GetInfo to get the size and attribute of input guided section data.
608 //
609 Status = ExtractGuidedSectionGetInfo (
610 InputSection,
611 &OutputBufferSize,
612 &ScratchBufferSize,
613 &SectionAttribute
614 );
615
616 if (EFI_ERROR (Status)) {
617 DEBUG ((EFI_D_ERROR, "GetInfo from guided section Failed - %r\n", Status));
618 return Status;
619 }
620
621 if (ScratchBufferSize != 0) {
622 //
623 // Allocate scratch buffer
624 //
625 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
626 if (ScratchBuffer == NULL) {
627 return EFI_OUT_OF_RESOURCES;
628 }
629 }
630
631 if ((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) && OutputBufferSize > 0) {
632 //
633 // Allocate output buffer
634 //
635 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize));
636 if (*OutputBuffer == NULL) {
637 return EFI_OUT_OF_RESOURCES;
638 }
639 }
640
641 Status = ExtractGuidedSectionDecode (
642 InputSection,
643 OutputBuffer,
644 ScratchBuffer,
645 AuthenticationStatus
646 );
647
648 if (EFI_ERROR (Status)) {
649 //
650 // Decode failed
651 //
652 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));
653 return Status;
654 }
655
656 *OutputSize = (UINTN) OutputBufferSize;
657
658 return EFI_SUCCESS;
659 }
660
661 STATIC
662 EFI_STATUS
663 EFIAPI
664 Decompress (
665 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
666 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
667 OUT VOID **OutputBuffer,
668 OUT UINTN *OutputSize
669 )
670 {
671 EFI_STATUS Status;
672 UINT8 *DstBuffer;
673 UINT8 *ScratchBuffer;
674 UINTN DstBufferSize;
675 UINT32 ScratchBufferSize;
676 EFI_COMMON_SECTION_HEADER *Section;
677 UINTN SectionLength;
678
679 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
680 ASSERT (FALSE);
681 return EFI_INVALID_PARAMETER;
682 }
683
684 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;
685 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
686
687 //
688 // This is a compression set, expand it
689 //
690 switch (CompressionSection->CompressionType) {
691 case EFI_STANDARD_COMPRESSION:
692 //
693 // Load EFI standard compression.
694 // For compressed data, decompress them to dstbuffer.
695 //
696 Status = UefiDecompressGetInfo (
697 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
698 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
699 (UINT32 *) &DstBufferSize,
700 &ScratchBufferSize
701 );
702 if (EFI_ERROR (Status)) {
703 //
704 // GetInfo failed
705 //
706 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
707 return EFI_NOT_FOUND;
708 }
709 //
710 // Allocate scratch buffer
711 //
712 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
713 if (ScratchBuffer == NULL) {
714 return EFI_OUT_OF_RESOURCES;
715 }
716 //
717 // Allocate destination buffer
718 //
719 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
720 if (DstBuffer == NULL) {
721 return EFI_OUT_OF_RESOURCES;
722 }
723 //
724 // Call decompress function
725 //
726 Status = UefiDecompress (
727 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
728 DstBuffer,
729 ScratchBuffer
730 );
731 if (EFI_ERROR (Status)) {
732 //
733 // Decompress failed
734 //
735 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
736 return EFI_NOT_FOUND;
737 }
738 break;
739
740 // porting note the original branch for customized compress is removed, it should be change to use GUID compress
741
742 case EFI_NOT_COMPRESSED:
743 //
744 // Allocate destination buffer
745 //
746 DstBufferSize = CompressionSection->UncompressedLength;
747 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
748 if (DstBuffer == NULL) {
749 return EFI_OUT_OF_RESOURCES;
750 }
751 //
752 // stream is not actually compressed, just encapsulated. So just copy it.
753 //
754 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
755 break;
756
757 default:
758 //
759 // Don't support other unknown compression type.
760 //
761 ASSERT (FALSE);
762 return EFI_NOT_FOUND;
763 }
764
765 *OutputSize = DstBufferSize;
766 *OutputBuffer = DstBuffer;
767
768 return EFI_SUCCESS;
769 }
770