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