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