]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
1. Replace PeCoffLoader library by PeCoff lib for PeiCore, DxeIpl and DxeMain.
[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
LG
20EFI_STATUS\r
21CustomDecompressExtractSection (\r
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
b0d803fe 50STATIC EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = {\r
51 CustomDecompressExtractSection\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
d8c79a81
LG
94 EFI_GUID **DecompressGuidList;\r
95 UINT32 DecompressMethodNumber;\r
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
113 // Get custom decompress method guid list \r
114 //\r
115 DecompressGuidList = NULL;\r
116 DecompressMethodNumber = 0;\r
117 Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);\r
118 if (Status == EFI_OUT_OF_RESOURCES) {\r
d8c79a81
LG
119 DecompressGuidList = (EFI_GUID **) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_GUID *)));\r
120 ASSERT (DecompressGuidList != NULL);\r
121 Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);\r
d8c79a81 122 }\r
b0d803fe 123 ASSERT_EFI_ERROR(Status);\r
124 \r
125 //\r
126 // Install custom decompress extraction guid ppi\r
127 //\r
128 if (DecompressMethodNumber > 0) {\r
129 GuidPpi = NULL;\r
130 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR)));\r
131 ASSERT (GuidPpi != NULL);\r
132 while (DecompressMethodNumber-- > 0) {\r
133 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
134 GuidPpi->Ppi = &mCustomDecompressExtractiongPpi;\r
135 GuidPpi->Guid = DecompressGuidList [DecompressMethodNumber];\r
136 Status = PeiServicesInstallPpi (GuidPpi++);\r
137 ASSERT_EFI_ERROR(Status);\r
138 }\r
139 }\r
140 } else {\r
141 ASSERT_EFI_ERROR (FALSE);\r
d8c79a81 142 }\r
95276127 143 }\r
144 \r
b0d803fe 145 //\r
146 // Install FvFileLoader and DxeIpl PPIs.\r
147 //\r
148 Status = PeiServicesInstallPpi (mPpiList);\r
149 ASSERT_EFI_ERROR(Status); \r
150 \r
95276127 151 return Status;\r
152}\r
153\r
b0d803fe 154/**\r
155 Main entry point to last PEIM \r
156 \r
157 @param This Entry point for DXE IPL PPI\r
158 @param PeiServices General purpose services available to every PEIM.\r
159 @param HobList Address to the Pei HOB list\r
160 \r
161 @return EFI_SUCCESS DXE core was successfully loaded. \r
162 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.\r
163**/\r
95276127 164EFI_STATUS\r
165EFIAPI\r
166DxeLoadCore (\r
167 IN EFI_DXE_IPL_PPI *This,\r
168 IN EFI_PEI_SERVICES **PeiServices,\r
169 IN EFI_PEI_HOB_POINTERS HobList\r
170 )\r
95276127 171{\r
172 EFI_STATUS Status;\r
173 EFI_GUID DxeCoreFileName;\r
95276127 174 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
175 UINT64 DxeCoreSize;\r
176 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
95276127 177 EFI_BOOT_MODE BootMode;\r
b0d803fe 178 EFI_PEI_FV_HANDLE VolumeHandle;\r
179 EFI_PEI_FILE_HANDLE FileHandle;\r
180 UINTN Instance;\r
95276127 181\r
182 //\r
183 // if in S3 Resume, restore configure\r
184 //\r
185 Status = PeiServicesGetBootMode (&BootMode);\r
186 ASSERT_EFI_ERROR(Status);\r
187\r
188 if (BootMode == BOOT_ON_S3_RESUME) {\r
e8da1266 189 Status = AcpiS3ResumeOs();\r
95276127 190 ASSERT_EFI_ERROR (Status);\r
191 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
e8da1266 192 Status = PeiRecoverFirmware ();\r
95276127 193 if (EFI_ERROR (Status)) {\r
194 DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
195 CpuDeadLoop ();\r
196 }\r
197\r
198 //\r
199 // Now should have a HOB with the DXE core w/ the old HOB destroyed\r
200 //\r
201 }\r
b0d803fe 202 \r
95276127 203 //\r
b0d803fe 204 // If any FV contains an encapsulated FV extract that FV\r
95276127 205 //\r
b0d803fe 206 DxeIplAddEncapsulatedFirmwareVolumes ();\r
207 \r
95276127 208 //\r
b0d803fe 209 // Look in all the FVs present in PEI and find the DXE Core\r
95276127 210 //\r
b0d803fe 211 Instance = 0;\r
212 Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);\r
95276127 213 ASSERT_EFI_ERROR (Status);\r
214\r
b0d803fe 215 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));\r
216\r
95276127 217 //\r
218 // Load the DXE Core from a Firmware Volume\r
219 //\r
220 Status = PeiLoadFile (\r
b0d803fe 221 FileHandle,\r
222 &DxeCoreAddress,\r
223 &DxeCoreSize,\r
224 &DxeCoreEntryPoint\r
225 );\r
226\r
95276127 227 ASSERT_EFI_ERROR (Status);\r
228\r
229 //\r
230 // Add HOB for the DXE Core\r
231 //\r
232 BuildModuleHob (\r
233 &DxeCoreFileName,\r
234 DxeCoreAddress,\r
235 DxeCoreSize,\r
236 DxeCoreEntryPoint\r
237 );\r
238\r
239 //\r
240 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
241 //\r
242 REPORT_STATUS_CODE (\r
243 EFI_PROGRESS_CODE,\r
244 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT\r
245 );\r
246\r
95276127 247 //\r
248 // Transfer control to the DXE Core\r
249 // The handoff state is simply a pointer to the HOB list\r
250 //\r
95276127 251 DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint));\r
252 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
253 //\r
254 // If we get here, then the DXE Core returned. This is an error\r
255 // Dxe Core should not return.\r
256 //\r
257 ASSERT (FALSE);\r
258 CpuDeadLoop ();\r
259\r
260 return EFI_OUT_OF_RESOURCES;\r
261}\r
262\r
b0d803fe 263\r
264STATIC\r
95276127 265EFI_STATUS\r
b0d803fe 266GetFvAlignment (\r
267 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
268 OUT UINT32 *FvAlignment\r
95276127 269 )\r
b0d803fe 270{\r
271 //\r
272 // Because FvLength in FvHeader is UINT64 type, \r
273 // so FvHeader must meed at least 8 bytes alignment.\r
274 // Get the appropriate alignment requirement.\r
275 // \r
276 if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) {\r
277 return EFI_UNSUPPORTED;\r
278 }\r
279 \r
280 *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
281 return EFI_SUCCESS;\r
282}\r
95276127 283\r
b0d803fe 284/**\r
285 Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand \r
286 as memory FV \r
287 \r
288 @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV\r
289 @return EFI_SUCESS Sucess to find the FV \r
290**/\r
291EFI_STATUS\r
292DxeIplAddEncapsulatedFirmwareVolumes (\r
293 VOID\r
294 )\r
295{\r
296 EFI_STATUS Status;\r
297 EFI_STATUS VolumeStatus;\r
298 UINTN Index;\r
299 EFI_FV_INFO VolumeInfo; \r
300 EFI_PEI_FV_HANDLE VolumeHandle;\r
301 EFI_PEI_FILE_HANDLE FileHandle;\r
302 UINT32 SectionLength;\r
303 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
304 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader;\r
305 VOID *DstBuffer;\r
306 UINT32 FvAlignment;\r
b0d803fe 307\r
308 Status = EFI_NOT_FOUND;\r
309 Index = 0;\r
95276127 310\r
b0d803fe 311 do {\r
312 VolumeStatus = DxeIplFindFirmwareVolumeInstance (\r
313 &Index, \r
314 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, \r
315 &VolumeHandle, \r
316 &FileHandle\r
317 );\r
318 \r
319 if (!EFI_ERROR (VolumeStatus)) {\r
320 Status = PeiServicesFfsFindSectionData (\r
321 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, \r
322 (EFI_FFS_FILE_HEADER *)FileHandle, \r
323 (VOID **)&FvHeader\r
324 );\r
325 \r
326 if (!EFI_ERROR (Status)) {\r
327 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
328 //\r
329 // Because FvLength in FvHeader is UINT64 type, \r
330 // so FvHeader must meed at least 8 bytes alignment.\r
331 // If current FvImage base address doesn't meet its alignment,\r
332 // we need to reload this FvImage to another correct memory address.\r
333 //\r
334 Status = GetFvAlignment(FvHeader, &FvAlignment); \r
335 if (EFI_ERROR(Status)) {\r
336 return Status;\r
337 }\r
338 if (((UINTN) FvHeader % FvAlignment) != 0) {\r
339 SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));\r
340 SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF;\r
341 \r
342 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment);\r
343 if (DstBuffer == NULL) {\r
344 return EFI_OUT_OF_RESOURCES;\r
345 }\r
346 CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER));\r
347 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; \r
348 }\r
95276127 349\r
b0d803fe 350 //\r
351 // This new Firmware Volume comes from a firmware file within a firmware volume.\r
352 // Record the original Firmware Volume Name.\r
353 //\r
354 PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo);\r
95276127 355\r
64253026 356 PeiPiLibBuildPiFvInfoPpi (\r
357 (EFI_PHYSICAL_ADDRESS) FvHeader,\r
358 FvHeader->FvLength,\r
b0d803fe 359 &(VolumeInfo.FvName),\r
64253026 360 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)\r
b0d803fe 361 );\r
64253026 362 \r
b0d803fe 363 ASSERT_EFI_ERROR (Status);\r
95276127 364\r
b0d803fe 365 //\r
366 // Makes the encapsulated volume show up in DXE phase to skip processing of\r
367 // encapsulated file again.\r
368 //\r
369 BuildFv2Hob (\r
370 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,\r
371 FvHeader->FvLength, \r
372 &VolumeInfo.FvName,\r
373 &(((EFI_FFS_FILE_HEADER *)FileHandle)->Name)\r
374 );\r
375 return Status;\r
376 }\r
377 }\r
378 }\r
379 } while (!EFI_ERROR (VolumeStatus));\r
380 \r
381 return Status;\r
382}\r
95276127 383\r
b0d803fe 384/**\r
385 Find the First Volume that contains the first FileType.\r
386\r
387 @param Instance The Fv instance.\r
388 @param SeachType The type of file to search.\r
389 @param VolumeHandle Pointer to Fv which contains the file to search. \r
390 @param FileHandle Pointer to FFS file to search.\r
391 \r
392 @return EFI_SUCESS Success to find the FFS in specificed FV\r
393 @return others Fail to find the FFS in specificed FV\r
394 */\r
395EFI_STATUS\r
396DxeIplFindFirmwareVolumeInstance (\r
397 IN OUT UINTN *Instance,\r
398 IN EFI_FV_FILETYPE SeachType,\r
399 OUT EFI_PEI_FV_HANDLE *VolumeHandle,\r
400 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
401 )\r
95276127 402{\r
b0d803fe 403 EFI_STATUS Status;\r
404 EFI_STATUS VolumeStatus;\r
95276127 405\r
b0d803fe 406 do {\r
407 VolumeStatus = PeiServicesFfsFindNextVolume (*Instance, VolumeHandle);\r
408 if (!EFI_ERROR (VolumeStatus)) {\r
409 *FileHandle = NULL;\r
410 Status = PeiServicesFfsFindNextFile (SeachType, *VolumeHandle, FileHandle);\r
411 if (!EFI_ERROR (Status)) {\r
412 return Status;\r
95276127 413 }\r
414 }\r
b0d803fe 415 *Instance += 1;\r
416 } while (!EFI_ERROR (VolumeStatus));\r
417\r
418 return VolumeStatus;\r
95276127 419}\r
420\r
b0d803fe 421/**\r
422 Loads and relocates a PE/COFF image into memory.\r
423\r
424 @param FileHandle The image file handle\r
425 @param ImageAddress The base address of the relocated PE/COFF image\r
426 @param ImageSize The size of the relocated PE/COFF image\r
427 @param EntryPoint The entry point of the relocated PE/COFF image\r
428 \r
429 @return EFI_SUCCESS The file was loaded and relocated\r
430 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
431**/\r
95276127 432EFI_STATUS\r
433PeiLoadFile (\r
b0d803fe 434 IN EFI_PEI_FILE_HANDLE FileHandle,\r
95276127 435 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
436 OUT UINT64 *ImageSize,\r
437 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
438 )\r
b0d803fe 439{\r
95276127 440\r
b0d803fe 441 EFI_STATUS Status;\r
442 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
443 VOID *Pe32Data;\r
b0d803fe 444 //\r
445 // First try to find the required section in this ffs file.\r
446 //\r
447 Status = PeiServicesFfsFindSectionData (\r
448 EFI_SECTION_PE32,\r
449 FileHandle,\r
450 &Pe32Data\r
451 );\r
95276127 452\r
b0d803fe 453 if (EFI_ERROR (Status)) {\r
454 Status = PeiServicesFfsFindSectionData (\r
455 EFI_SECTION_TE,\r
456 FileHandle,\r
457 &Pe32Data\r
458 );\r
459 }\r
460 \r
461 if (EFI_ERROR (Status)) {\r
462 //\r
463 // NO image types we support so exit.\r
464 //\r
465 return Status;\r
466 }\r
95276127 467\r
468 ZeroMem (&ImageContext, sizeof (ImageContext));\r
469 ImageContext.Handle = Pe32Data;\r
470 Status = GetImageReadFunction (&ImageContext);\r
471\r
472 ASSERT_EFI_ERROR (Status);\r
473\r
3d7b0992 474 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
95276127 475 if (EFI_ERROR (Status)) {\r
476 return Status;\r
477 }\r
478 //\r
479 // Allocate Memory for the image\r
480 //\r
481 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
482 ASSERT (ImageContext.ImageAddress != 0);\r
483\r
484 //\r
485 // Load the image to our new buffer\r
486 //\r
3d7b0992 487 Status = PeCoffLoaderLoadImage (&ImageContext);\r
95276127 488 if (EFI_ERROR (Status)) {\r
489 return Status;\r
490 }\r
491 //\r
492 // Relocate the image in our new buffer\r
493 //\r
3d7b0992 494 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
95276127 495 if (EFI_ERROR (Status)) {\r
496 return Status;\r
497 }\r
498\r
499 //\r
500 // Flush the instruction cache so the image data is written before we execute it\r
501 //\r
502 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
503\r
504 *ImageAddress = ImageContext.ImageAddress;\r
505 *ImageSize = ImageContext.ImageSize;\r
506 *EntryPoint = ImageContext.EntryPoint;\r
507\r
508 return EFI_SUCCESS;\r
509}\r
510\r
d8c79a81
LG
511/**\r
512 The ExtractSection() function processes the input section and\r
513 returns a pointer to the section contents. If the section being\r
514 extracted does not require processing (if the section\r
515 GuidedSectionHeader.Attributes has the\r
516 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
517 OutputBuffer is just updated to point to the start of the\r
518 section's contents. Otherwise, *Buffer must be allocated\r
519 from PEI permanent memory.\r
520\r
521 @param This Indicates the\r
522 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
523 Buffer containing the input GUIDed section to be\r
524 processed. OutputBuffer OutputBuffer is\r
525 allocated from PEI permanent memory and contains\r
526 the new section stream.\r
527 \r
528 @param OutputSize A pointer to a caller-allocated\r
529 UINTN in which the size of *OutputBuffer\r
530 allocation is stored. If the function\r
531 returns anything other than EFI_SUCCESS,\r
532 the value of OutputSize is undefined.\r
533 \r
534 @param AuthenticationStatus A pointer to a caller-allocated\r
535 UINT32 that indicates the\r
536 authentication status of the\r
537 output buffer. If the input\r
538 section's GuidedSectionHeader.\r
539 Attributes field has the\r
540 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
541 bit as clear,\r
542 AuthenticationStatus must return\r
543 zero. These bits reflect the\r
544 status of the extraction\r
545 operation. If the function\r
546 returns anything other than\r
547 EFI_SUCCESS, the value of\r
548 AuthenticationStatus is\r
549 undefined.\r
550 \r
551 @retval EFI_SUCCESS The InputSection was\r
552 successfully processed and the\r
553 section contents were returned.\r
554 \r
555 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
556 resources to process the request.\r
557 \r
558 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does\r
559 not match this instance of the\r
560 GUIDed Section Extraction PPI.\r
561**/\r
562EFI_STATUS\r
563CustomDecompressExtractSection (\r
564 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
565 IN CONST VOID *InputSection,\r
566 OUT VOID **OutputBuffer,\r
567 OUT UINTN *OutputSize,\r
568 OUT UINT32 *AuthenticationStatus\r
569)\r
570{\r
571 EFI_STATUS Status;\r
572 UINT8 *ScratchBuffer;\r
573 UINT32 ScratchSize;\r
88ce0209
LG
574 UINT32 SectionLength;\r
575 UINT32 DestinationSize; \r
d8c79a81
LG
576 \r
577 //\r
578 // Set authentic value to zero.\r
579 //\r
580 *AuthenticationStatus = 0;\r
581 //\r
582 // Calculate Section data Size\r
583 //\r
584 SectionLength = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;\r
585 //\r
586 // Get compressed data information\r
587 //\r
588 Status = CustomDecompressGetInfo (\r
589 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),\r
590 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),\r
591 SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),\r
88ce0209 592 &DestinationSize,\r
d8c79a81
LG
593 &ScratchSize\r
594 );\r
595 if (EFI_ERROR (Status)) {\r
95276127 596 //\r
d8c79a81 597 // GetInfo failed\r
95276127 598 //\r
d8c79a81
LG
599 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
600 return Status;\r
601 }\r
95276127 602\r
d8c79a81
LG
603 //\r
604 // Allocate scratch buffer\r
605 //\r
606 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize));\r
607 if (ScratchBuffer == NULL) {\r
608 return EFI_OUT_OF_RESOURCES;\r
609 }\r
610 //\r
611 // Allocate destination buffer\r
612 //\r
88ce0209 613 *OutputSize = (UINTN) DestinationSize;\r
d8c79a81
LG
614 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));\r
615 if (*OutputBuffer == NULL) {\r
616 return EFI_OUT_OF_RESOURCES;\r
95276127 617 }\r
618\r
d8c79a81
LG
619 //\r
620 // Call decompress function\r
621 //\r
622 Status = CustomDecompress (\r
623 (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),\r
624 (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),\r
625 *OutputBuffer,\r
626 ScratchBuffer\r
627 );\r
95276127 628\r
d8c79a81
LG
629 if (EFI_ERROR (Status)) {\r
630 //\r
631 // Decompress failed\r
632 //\r
633 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
634 return Status;\r
635 }\r
636 \r
95276127 637 return EFI_SUCCESS;\r
638}\r
b0d803fe 639\r
640STATIC\r
641EFI_STATUS\r
642EFIAPI \r
643Decompress (\r
644 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
645 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
646 OUT VOID **OutputBuffer,\r
647 OUT UINTN *OutputSize\r
648 )\r
649{\r
650 EFI_STATUS Status;\r
651 UINT8 *DstBuffer;\r
652 UINT8 *ScratchBuffer;\r
653 UINTN DstBufferSize;\r
654 UINT32 ScratchBufferSize;\r
655 EFI_COMMON_SECTION_HEADER *Section;\r
656 UINTN SectionLength;\r
657\r
658 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
659 ASSERT (FALSE);\r
660 return EFI_INVALID_PARAMETER;\r
661 }\r
662\r
663 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
664 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
665 \r
666 //\r
667 // This is a compression set, expand it\r
668 //\r
669 switch (CompressionSection->CompressionType) {\r
670 case EFI_STANDARD_COMPRESSION:\r
671 //\r
672 // Load EFI standard compression.\r
673 // For compressed data, decompress them to dstbuffer.\r
674 //\r
675 Status = UefiDecompressGetInfo (\r
676 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
677 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
678 (UINT32 *) &DstBufferSize,\r
679 &ScratchBufferSize\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 //\r
683 // GetInfo failed\r
684 //\r
685 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
686 return EFI_NOT_FOUND;\r
687 }\r
688 //\r
689 // Allocate scratch buffer\r
690 //\r
691 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
692 if (ScratchBuffer == NULL) {\r
693 return EFI_OUT_OF_RESOURCES;\r
694 }\r
695 //\r
696 // Allocate destination buffer\r
697 //\r
698 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
699 if (DstBuffer == NULL) {\r
700 return EFI_OUT_OF_RESOURCES;\r
701 }\r
702 //\r
703 // Call decompress function\r
704 //\r
705 Status = UefiDecompress (\r
706 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
707 DstBuffer,\r
708 ScratchBuffer\r
709 );\r
710 if (EFI_ERROR (Status)) {\r
711 //\r
712 // Decompress failed\r
713 //\r
714 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
715 return EFI_NOT_FOUND;\r
716 }\r
717 break;\r
718\r
719 // porting note the original branch for customized compress is removed, it should be change to use GUID compress\r
720\r
721 case EFI_NOT_COMPRESSED:\r
722 //\r
723 // Allocate destination buffer\r
724 //\r
725 DstBufferSize = CompressionSection->UncompressedLength;\r
726 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
727 if (DstBuffer == NULL) {\r
728 return EFI_OUT_OF_RESOURCES;\r
729 }\r
730 //\r
731 // stream is not actually compressed, just encapsulated. So just copy it.\r
732 //\r
733 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
734 break;\r
735\r
736 default:\r
737 //\r
738 // Don't support other unknown compression type.\r
739 //\r
740 ASSERT (FALSE);\r
741 return EFI_NOT_FOUND;\r
742 }\r
743\r
744 *OutputSize = DstBufferSize;\r
745 *OutputBuffer = DstBuffer;\r
746\r
747 return EFI_SUCCESS;\r
748}\r
749\r