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