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