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