]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
3988d9cb608927cb656aa2ed315942ff1cb85e17
[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 InputSection 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 @retval 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 *InputSection,
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 if (!EFI_ERROR (Status)) {
280 DataSize = sizeof (MemoryData);
281 Status = Variable->GetVariable (
282 Variable,
283 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
284 &gEfiMemoryTypeInformationGuid,
285 NULL,
286 &DataSize,
287 &MemoryData
288 );
289 if (!EFI_ERROR (Status)) {
290 //
291 // Build the GUID'd HOB for DXE
292 //
293 BuildGuidDataHob (
294 &gEfiMemoryTypeInformationGuid,
295 MemoryData,
296 DataSize
297 );
298 }
299 }
300
301 //
302 // Look in all the FVs present in PEI and find the DXE Core
303 //
304 FileHandle = NULL;
305 Status = DxeIplFindDxeCore (&FileHandle);
306 ASSERT_EFI_ERROR (Status);
307
308 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));
309
310 //
311 // Load the DXE Core from a Firmware Volume, may use LoadFile ppi to do this for save code size.
312 //
313 Status = PeiLoadFile (
314 FileHandle,
315 &DxeCoreAddress,
316 &DxeCoreSize,
317 &DxeCoreEntryPoint
318 );
319
320 ASSERT_EFI_ERROR (Status);
321
322 //
323 // Add HOB for the DXE Core
324 //
325 BuildModuleHob (
326 &DxeCoreFileName,
327 DxeCoreAddress,
328 EFI_SIZE_TO_PAGES ((UINT32) DxeCoreSize) * EFI_PAGE_SIZE,
329 DxeCoreEntryPoint
330 );
331
332 //
333 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
334 //
335 REPORT_STATUS_CODE (
336 EFI_PROGRESS_CODE,
337 PcdGet32(PcdStatusCodeValuePeiHandoffToDxe)
338 );
339
340 DEBUG_CODE_BEGIN ();
341
342 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;
343 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);
344
345 if (PtrPeImage.Pe32->FileHeader.Machine != IMAGE_FILE_MACHINE_IA64) {
346 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, (VOID *)(UINTN)DxeCoreEntryPoint));
347 } else {
348 //
349 // For IPF Image, the real entry point should be print.
350 //
351 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)DxeCoreEntryPoint)));
352 }
353
354 DEBUG_CODE_END ();
355 //
356 // Transfer control to the DXE Core
357 // The handoff state is simply a pointer to the HOB list
358 //
359 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);
360 //
361 // If we get here, then the DXE Core returned. This is an error
362 // Dxe Core should not return.
363 //
364 ASSERT (FALSE);
365 CpuDeadLoop ();
366
367 return EFI_OUT_OF_RESOURCES;
368 }
369
370
371
372
373 /**
374 Find DxeCore driver from all First Volumes.
375
376 @param FileHandle Pointer to FFS file to search.
377
378 @return EFI_SUCESS Success to find the FFS in specificed FV
379 @return others Fail to find the FFS in specificed FV
380
381 **/
382 EFI_STATUS
383 DxeIplFindDxeCore (
384 OUT EFI_PEI_FILE_HANDLE *FileHandle
385 )
386 {
387 EFI_STATUS Status;
388 EFI_STATUS FileStatus;
389 UINTN Instance;
390 EFI_PEI_FV_HANDLE VolumeHandle;
391
392 Instance = 0;
393 *FileHandle = NULL;
394
395 do {
396 Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);
397 if (!EFI_ERROR (Status)) {
398 FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);
399 if (!EFI_ERROR (FileStatus)) {
400 return FileStatus;
401 }
402 }
403 } while (!EFI_ERROR (Status));
404
405 return EFI_NOT_FOUND;
406 }
407
408
409
410
411 /**
412 Loads and relocates a PE/COFF image into memory.
413
414 @param FileHandle The image file handle
415 @param ImageAddress The base address of the relocated PE/COFF image
416 @param ImageSize The size of the relocated PE/COFF image
417 @param EntryPoint The entry point of the relocated PE/COFF image
418
419 @return EFI_SUCCESS The file was loaded and relocated
420 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
421
422 **/
423 EFI_STATUS
424 PeiLoadFile (
425 IN EFI_PEI_FILE_HANDLE FileHandle,
426 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
427 OUT UINT64 *ImageSize,
428 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
429 )
430 {
431
432 EFI_STATUS Status;
433 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
434 VOID *Pe32Data;
435 //
436 // First try to find the PE32 section in this ffs file.
437 //
438 Status = PeiServicesFfsFindSectionData (
439 EFI_SECTION_PE32,
440 FileHandle,
441 &Pe32Data
442 );
443
444 if (EFI_ERROR (Status)) {
445 //
446 // NO image types we support so exit.
447 //
448 return Status;
449 }
450
451 ZeroMem (&ImageContext, sizeof (ImageContext));
452 ImageContext.Handle = Pe32Data;
453 Status = GetImageReadFunction (&ImageContext);
454
455 ASSERT_EFI_ERROR (Status);
456
457 Status = PeCoffLoaderGetImageInfo (&ImageContext);
458 if (EFI_ERROR (Status)) {
459 return Status;
460 }
461 //
462 // Allocate Memory for the image
463 //
464 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
465 ASSERT (ImageContext.ImageAddress != 0);
466
467 //
468 // Load the image to our new buffer
469 //
470 Status = PeCoffLoaderLoadImage (&ImageContext);
471 if (EFI_ERROR (Status)) {
472 return Status;
473 }
474 //
475 // Relocate the image in our new buffer
476 //
477 Status = PeCoffLoaderRelocateImage (&ImageContext);
478 if (EFI_ERROR (Status)) {
479 return Status;
480 }
481
482 //
483 // Flush the instruction cache so the image data is written before we execute it
484 //
485 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
486
487 *ImageAddress = ImageContext.ImageAddress;
488 *ImageSize = ImageContext.ImageSize;
489 *EntryPoint = ImageContext.EntryPoint;
490
491 return EFI_SUCCESS;
492 }
493
494
495
496
497 /**
498 The ExtractSection() function processes the input section and
499 returns a pointer to the section contents. If the section being
500 extracted does not require processing (if the section
501 GuidedSectionHeader.Attributes has the
502 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
503 OutputBuffer is just updated to point to the start of the
504 section's contents. Otherwise, *Buffer must be allocated
505 from PEI permanent memory.
506
507 @param This Indicates the
508 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
509 Buffer containing the input GUIDed section to be
510 processed. OutputBuffer OutputBuffer is
511 allocated from PEI permanent memory and contains
512 the new section stream.
513 @param InputSection A pointer to the input buffer, which contains
514 the input section to be processed.
515 @param OutputBuffer A pointer to a caller-allocated buffer, whose
516 size is specified by the contents of OutputSize.
517 @param OutputSize A pointer to a caller-allocated
518 UINTN in which the size of *OutputBuffer
519 allocation is stored. If the function
520 returns anything other than EFI_SUCCESS,
521 the value of OutputSize is undefined.
522 @param AuthenticationStatus A pointer to a caller-allocated
523 UINT32 that indicates the
524 authentication status of the
525 output buffer. If the input
526 section's GuidedSectionHeader.
527 Attributes field has the
528 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
529 bit as clear,
530 AuthenticationStatus must return
531 zero. These bits reflect the
532 status of the extraction
533 operation. If the function
534 returns anything other than
535 EFI_SUCCESS, the value of
536 AuthenticationStatus is
537 undefined.
538
539 @retval EFI_SUCCESS The InputSection was
540 successfully processed and the
541 section contents were returned.
542
543 @retval EFI_OUT_OF_RESOURCES The system has insufficient
544 resources to process the request.
545
546 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
547 not match this instance of the
548 GUIDed Section Extraction PPI.
549
550 **/
551 EFI_STATUS
552 CustomGuidedSectionExtract (
553 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
554 IN CONST VOID *InputSection,
555 OUT VOID **OutputBuffer,
556 OUT UINTN *OutputSize,
557 OUT UINT32 *AuthenticationStatus
558 )
559 {
560 EFI_STATUS Status;
561 UINT8 *ScratchBuffer;
562 UINT32 ScratchBufferSize;
563 UINT32 OutputBufferSize;
564 UINT16 SectionAttribute;
565
566 //
567 // Init local variable
568 //
569 ScratchBuffer = NULL;
570
571 //
572 // Call GetInfo to get the size and attribute of input guided section data.
573 //
574 Status = ExtractGuidedSectionGetInfo (
575 InputSection,
576 &OutputBufferSize,
577 &ScratchBufferSize,
578 &SectionAttribute
579 );
580
581 if (EFI_ERROR (Status)) {
582 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
583 return Status;
584 }
585
586 if (ScratchBufferSize != 0) {
587 //
588 // Allocate scratch buffer
589 //
590 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
591 if (ScratchBuffer == NULL) {
592 return EFI_OUT_OF_RESOURCES;
593 }
594 }
595
596 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
597 //
598 // Allocate output buffer
599 //
600 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
601 if (*OutputBuffer == NULL) {
602 return EFI_OUT_OF_RESOURCES;
603 }
604 DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
605 //
606 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
607 // skip EFI section header to make section data at page alignment.
608 //
609 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
610 }
611
612 Status = ExtractGuidedSectionDecode (
613 InputSection,
614 OutputBuffer,
615 ScratchBuffer,
616 AuthenticationStatus
617 );
618
619 if (EFI_ERROR (Status)) {
620 //
621 // Decode failed
622 //
623 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
624 return Status;
625 }
626
627 *OutputSize = (UINTN) OutputBufferSize;
628
629 return EFI_SUCCESS;
630 }
631
632
633
634 /**
635 Decompresses a section to the output buffer.
636
637 This function lookes up the compression type field in the input section and
638 applies the appropriate compression algorithm to compress the section to a
639 callee allocated buffer.
640
641 @param This Points to this instance of the
642 EFI_PEI_DECOMPRESS_PEI PPI.
643 @param CompressionSection Points to the compressed section.
644 @param OutputBuffer Holds the returned pointer to the decompressed
645 sections.
646 @param OutputSize Holds the returned size of the decompress
647 section streams.
648
649 @retval EFI_SUCCESS The section was decompressed successfully.
650 OutputBuffer contains the resulting data and
651 OutputSize contains the resulting size.
652
653 **/
654 EFI_STATUS
655 EFIAPI
656 Decompress (
657 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
658 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
659 OUT VOID **OutputBuffer,
660 OUT UINTN *OutputSize
661 )
662 {
663 EFI_STATUS Status;
664 UINT8 *DstBuffer;
665 UINT8 *ScratchBuffer;
666 UINTN DstBufferSize;
667 UINT32 ScratchBufferSize;
668 EFI_COMMON_SECTION_HEADER *Section;
669 UINTN SectionLength;
670
671 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
672 ASSERT (FALSE);
673 return EFI_INVALID_PARAMETER;
674 }
675
676 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;
677 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
678
679 //
680 // This is a compression set, expand it
681 //
682 switch (CompressionSection->CompressionType) {
683 case EFI_STANDARD_COMPRESSION:
684 //
685 // Load EFI standard compression.
686 // For compressed data, decompress them to dstbuffer.
687 //
688 Status = UefiDecompressGetInfo (
689 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
690 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
691 (UINT32 *) &DstBufferSize,
692 &ScratchBufferSize
693 );
694 if (EFI_ERROR (Status)) {
695 //
696 // GetInfo failed
697 //
698 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
699 return EFI_NOT_FOUND;
700 }
701 //
702 // Allocate scratch buffer
703 //
704 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
705 if (ScratchBuffer == NULL) {
706 return EFI_OUT_OF_RESOURCES;
707 }
708 //
709 // Allocate destination buffer, extra one page for adjustment
710 //
711 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
712 if (DstBuffer == NULL) {
713 return EFI_OUT_OF_RESOURCES;
714 }
715 //
716 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
717 // to make section data at page alignment.
718 //
719 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
720 //
721 // Call decompress function
722 //
723 Status = UefiDecompress (
724 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
725 DstBuffer,
726 ScratchBuffer
727 );
728 if (EFI_ERROR (Status)) {
729 //
730 // Decompress failed
731 //
732 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
733 return EFI_NOT_FOUND;
734 }
735 break;
736
737 case EFI_NOT_COMPRESSED:
738 //
739 // Allocate destination buffer
740 //
741 DstBufferSize = CompressionSection->UncompressedLength;
742 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
743 if (DstBuffer == NULL) {
744 return EFI_OUT_OF_RESOURCES;
745 }
746 //
747 // Adjust DstBuffer offset, skip EFI section header
748 // to make section data at page alignment.
749 //
750 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
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
771
772
773
774 /**
775 Updates the Stack HOB passed to DXE phase.
776
777 This function traverses the whole HOB list and update the stack HOB to
778 reflect the real stack that is used by DXE core.
779
780 @param BaseAddress The lower address of stack used by DxeCore.
781 @param Length The length of stack used by DxeCore.
782
783 **/
784 VOID
785 UpdateStackHob (
786 IN EFI_PHYSICAL_ADDRESS BaseAddress,
787 IN UINT64 Length
788 )
789 {
790 EFI_PEI_HOB_POINTERS Hob;
791
792 Hob.Raw = GetHobList ();
793 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
794 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
795 //
796 // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type
797 // to be reclaimed by DXE core.
798 //
799 BuildMemoryAllocationHob (
800 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
801 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
802 EfiConventionalMemory
803 );
804 //
805 // Update the BSP Stack Hob to reflect the new stack info.
806 //
807 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
808 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
809 break;
810 }
811 Hob.Raw = GET_NEXT_HOB (Hob);
812 }
813 }