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