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