]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Add missing status code in several modules.
[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 - 2012, Intel Corporation. All rights reserved.<BR>
6 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
18
19 //
20 // Module Globals used in the DXE to PEI hand off
21 // These must be module globals, so the stack can be switched
22 //
23 CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
24 DxeLoadCore
25 };
26
27 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
28 CustomGuidedSectionExtract
29 };
30
31 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
32 Decompress
33 };
34
35 CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
36 {
37 EFI_PEI_PPI_DESCRIPTOR_PPI,
38 &gEfiDxeIplPpiGuid,
39 (VOID *) &mDxeIplPpi
40 },
41 {
42 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
43 &gEfiPeiDecompressPpiGuid,
44 (VOID *) &mDecompressPpi
45 }
46 };
47
48 CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
49 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
50 &gEfiEndOfPeiSignalPpiGuid,
51 NULL
52 };
53
54 /**
55 Entry point of DXE IPL PEIM.
56
57 This function installs DXE IPL PPI and Decompress PPI. It also reloads
58 itself to memory on non-S3 resume boot path.
59
60 @param FileHandle Handle of the file being invoked.
61 @param PeiServices Describes the list of possible PEI Services.
62
63 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
64 @retval Others Some error occurs during the execution of this function.
65
66 **/
67 EFI_STATUS
68 EFIAPI
69 PeimInitializeDxeIpl (
70 IN EFI_PEI_FILE_HANDLE FileHandle,
71 IN CONST EFI_PEI_SERVICES **PeiServices
72 )
73 {
74 EFI_STATUS Status;
75 EFI_BOOT_MODE BootMode;
76 EFI_GUID *ExtractHandlerGuidTable;
77 UINTN ExtractHandlerNumber;
78 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
79
80 BootMode = GetBootModeHob ();
81
82 if (BootMode != BOOT_ON_S3_RESUME) {
83 Status = PeiServicesRegisterForShadow (FileHandle);
84 if (Status == EFI_SUCCESS) {
85 //
86 // EFI_SUCESS means it is the first time to call register for shadow.
87 //
88 return Status;
89 }
90
91 //
92 // Ensure that DXE IPL is shadowed to permanent memory.
93 //
94 ASSERT (Status == EFI_ALREADY_STARTED);
95
96 //
97 // Get custom extract guided section method guid list
98 //
99 ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
100
101 //
102 // Install custom extraction guid PPI
103 //
104 if (ExtractHandlerNumber > 0) {
105 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
106 ASSERT (GuidPpi != NULL);
107 while (ExtractHandlerNumber-- > 0) {
108 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
109 GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;
110 GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
111 Status = PeiServicesInstallPpi (GuidPpi++);
112 ASSERT_EFI_ERROR(Status);
113 }
114 }
115
116 }
117
118 //
119 // Install DxeIpl and Decompress PPIs.
120 //
121 Status = PeiServicesInstallPpi (mPpiList);
122 ASSERT_EFI_ERROR(Status);
123
124 return Status;
125 }
126
127 /**
128 Validate variable data for the MemoryTypeInformation.
129
130 @param MemoryData Variable data.
131 @param MemoryDataSize Variable data length.
132
133 @return TRUE The variable data is valid.
134 @return FALSE The variable data is invalid.
135
136 **/
137 BOOLEAN
138 ValidateMemoryTypeInfoVariable (
139 IN EFI_MEMORY_TYPE_INFORMATION *MemoryData,
140 IN UINTN MemoryDataSize
141 )
142 {
143 UINTN Count;
144 UINTN Index;
145
146 // Check the input parameter.
147 if (MemoryData == NULL) {
148 return FALSE;
149 }
150
151 // Get Count
152 Count = MemoryDataSize / sizeof (*MemoryData);
153
154 // Check Size
155 if (Count * sizeof(*MemoryData) != MemoryDataSize) {
156 return FALSE;
157 }
158
159 // Check last entry type filed.
160 if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
161 return FALSE;
162 }
163
164 // Check the type filed.
165 for (Index = 0; Index < Count - 1; Index++) {
166 if (MemoryData[Index].Type >= EfiMaxMemoryType) {
167 return FALSE;
168 }
169 }
170
171 return TRUE;
172 }
173
174 /**
175 Main entry point to last PEIM.
176
177 This function finds DXE Core in the firmware volume and transfer the control to
178 DXE core.
179
180 @param This Entry point for DXE IPL PPI.
181 @param PeiServices General purpose services available to every PEIM.
182 @param HobList Address to the Pei HOB list.
183
184 @return EFI_SUCCESS DXE core was successfully loaded.
185 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
186
187 **/
188 EFI_STATUS
189 EFIAPI
190 DxeLoadCore (
191 IN CONST EFI_DXE_IPL_PPI *This,
192 IN EFI_PEI_SERVICES **PeiServices,
193 IN EFI_PEI_HOB_POINTERS HobList
194 )
195 {
196 EFI_STATUS Status;
197 EFI_FV_FILE_INFO DxeCoreFileInfo;
198 EFI_PHYSICAL_ADDRESS DxeCoreAddress;
199 UINT64 DxeCoreSize;
200 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;
201 EFI_BOOT_MODE BootMode;
202 EFI_PEI_FILE_HANDLE FileHandle;
203 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;
204 EFI_PEI_LOAD_FILE_PPI *LoadFile;
205 UINTN Instance;
206 UINT32 AuthenticationState;
207 UINTN DataSize;
208 EFI_PEI_S3_RESUME2_PPI *S3Resume;
209 EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;
210 EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];
211
212 //
213 // if in S3 Resume, restore configure
214 //
215 BootMode = GetBootModeHob ();
216
217 if (BootMode == BOOT_ON_S3_RESUME) {
218 Status = PeiServicesLocatePpi (
219 &gEfiPeiS3Resume2PpiGuid,
220 0,
221 NULL,
222 (VOID **) &S3Resume
223 );
224 if (EFI_ERROR (Status)) {
225 //
226 // Report Status code that S3Resume PPI can not be found
227 //
228 REPORT_STATUS_CODE (
229 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
230 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)
231 );
232 }
233 ASSERT_EFI_ERROR (Status);
234
235 Status = S3Resume->S3RestoreConfig2 (S3Resume);
236 ASSERT_EFI_ERROR (Status);
237 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
238 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));
239 Status = PeiServicesLocatePpi (
240 &gEfiPeiRecoveryModulePpiGuid,
241 0,
242 NULL,
243 (VOID **) &PeiRecovery
244 );
245 //
246 // Report Status code the failure of locating Recovery PPI
247 //
248 REPORT_STATUS_CODE (
249 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
250 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
251 );
252 ASSERT_EFI_ERROR (Status);
253 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));
254 Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
255 if (EFI_ERROR (Status)) {
256 DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
257 //
258 // Report Status code that S3Resume PPI can not be found
259 //
260 REPORT_STATUS_CODE (
261 EFI_ERROR_CODE | EFI_ERROR_MAJOR,
262 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
263 );
264 CpuDeadLoop ();
265 }
266 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
267 //
268 // Now should have a HOB with the DXE core
269 //
270 }
271
272 Status = PeiServicesLocatePpi (
273 &gEfiPeiReadOnlyVariable2PpiGuid,
274 0,
275 NULL,
276 (VOID **)&Variable
277 );
278 if (!EFI_ERROR (Status)) {
279 DataSize = sizeof (MemoryData);
280 Status = Variable->GetVariable (
281 Variable,
282 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
283 &gEfiMemoryTypeInformationGuid,
284 NULL,
285 &DataSize,
286 &MemoryData
287 );
288 if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {
289 //
290 // Build the GUID'd HOB for DXE
291 //
292 BuildGuidDataHob (
293 &gEfiMemoryTypeInformationGuid,
294 MemoryData,
295 DataSize
296 );
297 }
298 }
299
300 //
301 // Look in all the FVs present in PEI and find the DXE Core FileHandle
302 //
303 FileHandle = DxeIplFindDxeCore ();
304
305 //
306 // Load the DXE Core from a Firmware Volume.
307 //
308 Instance = 0;
309 do {
310 Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);
311 //
312 // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.
313 //
314 ASSERT_EFI_ERROR (Status);
315
316 Status = LoadFile->LoadFile (
317 LoadFile,
318 FileHandle,
319 &DxeCoreAddress,
320 &DxeCoreSize,
321 &DxeCoreEntryPoint,
322 &AuthenticationState
323 );
324 } while (EFI_ERROR (Status));
325
326 //
327 // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.
328 //
329 Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);
330 ASSERT_EFI_ERROR (Status);
331
332 //
333 // Add HOB for the DXE Core
334 //
335 BuildModuleHob (
336 &DxeCoreFileInfo.FileName,
337 DxeCoreAddress,
338 ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),
339 DxeCoreEntryPoint
340 );
341
342 //
343 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
344 //
345 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));
346
347 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
348
349 //
350 // Transfer control to the DXE Core
351 // The hand off state is simply a pointer to the HOB list
352 //
353 HandOffToDxeCore (DxeCoreEntryPoint, HobList);
354 //
355 // If we get here, then the DXE Core returned. This is an error
356 // DxeCore should not return.
357 //
358 ASSERT (FALSE);
359 CpuDeadLoop ();
360
361 return EFI_OUT_OF_RESOURCES;
362 }
363
364
365 /**
366 Searches DxeCore in all firmware Volumes and loads the first
367 instance that contains DxeCore.
368
369 @return FileHandle of DxeCore to load DxeCore.
370
371 **/
372 EFI_PEI_FILE_HANDLE
373 DxeIplFindDxeCore (
374 VOID
375 )
376 {
377 EFI_STATUS Status;
378 UINTN Instance;
379 EFI_PEI_FV_HANDLE VolumeHandle;
380 EFI_PEI_FILE_HANDLE FileHandle;
381
382 Instance = 0;
383 while (TRUE) {
384 //
385 // Traverse all firmware volume instances
386 //
387 Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
388 //
389 // If some error occurs here, then we cannot find any firmware
390 // volume that may contain DxeCore.
391 //
392 if (EFI_ERROR (Status)) {
393 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
394 }
395 ASSERT_EFI_ERROR (Status);
396
397 //
398 // Find the DxeCore file type from the beginning in this firmware volume.
399 //
400 FileHandle = NULL;
401 Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
402 if (!EFI_ERROR (Status)) {
403 //
404 // Find DxeCore FileHandle in this volume, then we skip other firmware volume and
405 // return the FileHandle.
406 //
407 return FileHandle;
408 }
409 //
410 // We cannot find DxeCore in this firmware volume, then search the next volume.
411 //
412 Instance++;
413 }
414 }
415
416
417
418 /**
419 The ExtractSection() function processes the input section and
420 returns a pointer to the section contents. If the section being
421 extracted does not require processing (if the section
422 GuidedSectionHeader.Attributes has the
423 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
424 OutputBuffer is just updated to point to the start of the
425 section's contents. Otherwise, *Buffer must be allocated
426 from PEI permanent memory.
427
428 @param This Indicates the
429 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
430 Buffer containing the input GUIDed section to be
431 processed. OutputBuffer OutputBuffer is
432 allocated from PEI permanent memory and contains
433 the new section stream.
434 @param InputSection A pointer to the input buffer, which contains
435 the input section to be processed.
436 @param OutputBuffer A pointer to a caller-allocated buffer, whose
437 size is specified by the contents of OutputSize.
438 @param OutputSize A pointer to a caller-allocated
439 UINTN in which the size of *OutputBuffer
440 allocation is stored. If the function
441 returns anything other than EFI_SUCCESS,
442 the value of OutputSize is undefined.
443 @param AuthenticationStatus A pointer to a caller-allocated
444 UINT32 that indicates the
445 authentication status of the
446 output buffer. If the input
447 section's GuidedSectionHeader.
448 Attributes field has the
449 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
450 bit as clear,
451 AuthenticationStatus must return
452 zero. These bits reflect the
453 status of the extraction
454 operation. If the function
455 returns anything other than
456 EFI_SUCCESS, the value of
457 AuthenticationStatus is
458 undefined.
459
460 @retval EFI_SUCCESS The InputSection was
461 successfully processed and the
462 section contents were returned.
463
464 @retval EFI_OUT_OF_RESOURCES The system has insufficient
465 resources to process the request.
466
467 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
468 not match this instance of the
469 GUIDed Section Extraction PPI.
470
471 **/
472 EFI_STATUS
473 EFIAPI
474 CustomGuidedSectionExtract (
475 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
476 IN CONST VOID *InputSection,
477 OUT VOID **OutputBuffer,
478 OUT UINTN *OutputSize,
479 OUT UINT32 *AuthenticationStatus
480 )
481 {
482 EFI_STATUS Status;
483 UINT8 *ScratchBuffer;
484 UINT32 ScratchBufferSize;
485 UINT32 OutputBufferSize;
486 UINT16 SectionAttribute;
487
488 //
489 // Init local variable
490 //
491 ScratchBuffer = NULL;
492
493 //
494 // Call GetInfo to get the size and attribute of input guided section data.
495 //
496 Status = ExtractGuidedSectionGetInfo (
497 InputSection,
498 &OutputBufferSize,
499 &ScratchBufferSize,
500 &SectionAttribute
501 );
502
503 if (EFI_ERROR (Status)) {
504 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
505 return Status;
506 }
507
508 if (ScratchBufferSize != 0) {
509 //
510 // Allocate scratch buffer
511 //
512 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
513 if (ScratchBuffer == NULL) {
514 return EFI_OUT_OF_RESOURCES;
515 }
516 }
517
518 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
519 //
520 // Allocate output buffer
521 //
522 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
523 if (*OutputBuffer == NULL) {
524 return EFI_OUT_OF_RESOURCES;
525 }
526 DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
527 //
528 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
529 // skip EFI section header to make section data at page alignment.
530 //
531 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
532 }
533
534 Status = ExtractGuidedSectionDecode (
535 InputSection,
536 OutputBuffer,
537 ScratchBuffer,
538 AuthenticationStatus
539 );
540 if (EFI_ERROR (Status)) {
541 //
542 // Decode failed
543 //
544 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
545 return Status;
546 }
547
548 *OutputSize = (UINTN) OutputBufferSize;
549
550 return EFI_SUCCESS;
551 }
552
553
554
555 /**
556 Decompresses a section to the output buffer.
557
558 This function looks up the compression type field in the input section and
559 applies the appropriate compression algorithm to compress the section to a
560 callee allocated buffer.
561
562 @param This Points to this instance of the
563 EFI_PEI_DECOMPRESS_PEI PPI.
564 @param CompressionSection Points to the compressed section.
565 @param OutputBuffer Holds the returned pointer to the decompressed
566 sections.
567 @param OutputSize Holds the returned size of the decompress
568 section streams.
569
570 @retval EFI_SUCCESS The section was decompressed successfully.
571 OutputBuffer contains the resulting data and
572 OutputSize contains the resulting size.
573
574 **/
575 EFI_STATUS
576 EFIAPI
577 Decompress (
578 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
579 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
580 OUT VOID **OutputBuffer,
581 OUT UINTN *OutputSize
582 )
583 {
584 EFI_STATUS Status;
585 UINT8 *DstBuffer;
586 UINT8 *ScratchBuffer;
587 UINT32 DstBufferSize;
588 UINT32 ScratchBufferSize;
589 VOID *CompressionSource;
590 UINT32 CompressionSourceSize;
591 UINT32 UncompressedLength;
592 UINT8 CompressionType;
593
594 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
595 ASSERT (FALSE);
596 return EFI_INVALID_PARAMETER;
597 }
598
599 if (IS_SECTION2 (CompressionSection)) {
600 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
601 CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
602 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
603 CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
604 } else {
605 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
606 CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
607 UncompressedLength = CompressionSection->UncompressedLength;
608 CompressionType = CompressionSection->CompressionType;
609 }
610
611 //
612 // This is a compression set, expand it
613 //
614 switch (CompressionType) {
615 case EFI_STANDARD_COMPRESSION:
616 if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {
617 //
618 // Load EFI standard compression.
619 // For compressed data, decompress them to destination buffer.
620 //
621 Status = UefiDecompressGetInfo (
622 CompressionSource,
623 CompressionSourceSize,
624 &DstBufferSize,
625 &ScratchBufferSize
626 );
627 if (EFI_ERROR (Status)) {
628 //
629 // GetInfo failed
630 //
631 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
632 return EFI_NOT_FOUND;
633 }
634 //
635 // Allocate scratch buffer
636 //
637 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
638 if (ScratchBuffer == NULL) {
639 return EFI_OUT_OF_RESOURCES;
640 }
641 //
642 // Allocate destination buffer, extra one page for adjustment
643 //
644 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
645 if (DstBuffer == NULL) {
646 return EFI_OUT_OF_RESOURCES;
647 }
648 //
649 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
650 // to make section data at page alignment.
651 //
652 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
653 //
654 // Call decompress function
655 //
656 Status = UefiDecompress (
657 CompressionSource,
658 DstBuffer,
659 ScratchBuffer
660 );
661 if (EFI_ERROR (Status)) {
662 //
663 // Decompress failed
664 //
665 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
666 return EFI_NOT_FOUND;
667 }
668 break;
669 } else {
670 //
671 // PcdDxeIplSupportUefiDecompress is FALSE
672 // Don't support UEFI decompression algorithm.
673 //
674 ASSERT (FALSE);
675 return EFI_NOT_FOUND;
676 }
677
678 case EFI_NOT_COMPRESSED:
679 //
680 // Allocate destination buffer
681 //
682 DstBufferSize = UncompressedLength;
683 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
684 if (DstBuffer == NULL) {
685 return EFI_OUT_OF_RESOURCES;
686 }
687 //
688 // Adjust DstBuffer offset, skip EFI section header
689 // to make section data at page alignment.
690 //
691 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
692 //
693 // stream is not actually compressed, just encapsulated. So just copy it.
694 //
695 CopyMem (DstBuffer, CompressionSource, DstBufferSize);
696 break;
697
698 default:
699 //
700 // Don't support other unknown compression type.
701 //
702 ASSERT (FALSE);
703 return EFI_NOT_FOUND;
704 }
705
706 *OutputSize = DstBufferSize;
707 *OutputBuffer = DstBuffer;
708
709 return EFI_SUCCESS;
710 }
711
712
713 /**
714 Updates the Stack HOB passed to DXE phase.
715
716 This function traverses the whole HOB list and update the stack HOB to
717 reflect the real stack that is used by DXE core.
718
719 @param BaseAddress The lower address of stack used by DxeCore.
720 @param Length The length of stack used by DxeCore.
721
722 **/
723 VOID
724 UpdateStackHob (
725 IN EFI_PHYSICAL_ADDRESS BaseAddress,
726 IN UINT64 Length
727 )
728 {
729 EFI_PEI_HOB_POINTERS Hob;
730
731 Hob.Raw = GetHobList ();
732 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
733 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
734 //
735 // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to
736 // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some
737 // PEIMs may also keep key information on stack
738 //
739 BuildMemoryAllocationHob (
740 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
741 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
742 EfiBootServicesData
743 );
744 //
745 // Update the BSP Stack Hob to reflect the new stack info.
746 //
747 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
748 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
749 break;
750 }
751 Hob.Raw = GET_NEXT_HOB (Hob);
752 }
753 }