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