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