]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - 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
1/**@file\r
2 Last PEIM.\r
3 Responsibility of this module is to load the DXE Core from a Firmware Volume.\r
4\r
5Copyright (c) 2006 - 2007 Intel Corporation\r
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
14**/\r
15\r
16#include "DxeIpl.h"\r
17#include <Ppi/GuidedSectionExtraction.h>\r
18#include <FrameworkPei.h>\r
19\r
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
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
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
50STATIC EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = {\r
51 CustomDecompressExtractSection\r
52};\r
53\r
54STATIC EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
55 Decompress\r
56};\r
57\r
58static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
59 {\r
60 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
61 &gEfiDxeIplPpiGuid,\r
62 &mDxeIplPpi\r
63 },\r
64 {\r
65 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
66 &gEfiPeiDecompressPpiGuid,\r
67 &mDecompressPpi\r
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
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
85EFI_STATUS\r
86EFIAPI\r
87PeimInitializeDxeIpl (\r
88 IN EFI_PEI_FILE_HANDLE FfsHandle,\r
89 IN EFI_PEI_SERVICES **PeiServices\r
90 )\r
91{\r
92 EFI_STATUS Status;\r
93 EFI_BOOT_MODE BootMode;\r
94 EFI_GUID **DecompressGuidList;\r
95 UINT32 DecompressMethodNumber;\r
96 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;\r
97 \r
98 Status = PeiServicesGetBootMode (&BootMode);\r
99 ASSERT_EFI_ERROR (Status);\r
100\r
101 if (BootMode != BOOT_ON_S3_RESUME) {\r
102 Status = PeiServicesRegisterForShadow (FfsHandle);\r
103 if (Status == EFI_SUCCESS) {\r
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
109 \r
110 gInMemory = TRUE;\r
111 \r
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
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
122 }\r
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
142 }\r
143 }\r
144 \r
145 //\r
146 // Install FvFileLoader and DxeIpl PPIs.\r
147 //\r
148 Status = PeiServicesInstallPpi (mPpiList);\r
149 ASSERT_EFI_ERROR(Status); \r
150 \r
151 return Status;\r
152}\r
153\r
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
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
171{\r
172 EFI_STATUS Status;\r
173 EFI_GUID DxeCoreFileName;\r
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
179 EFI_PEI_FV_HANDLE VolumeHandle;\r
180 EFI_PEI_FILE_HANDLE FileHandle;\r
181 UINTN Instance;\r
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
190 Status = AcpiS3ResumeOs();\r
191 ASSERT_EFI_ERROR (Status);\r
192 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
193 Status = PeiRecoverFirmware ();\r
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
207 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *) GetPeCoffLoaderProtocol ();\r
208 ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
209 \r
210 //\r
211 // If any FV contains an encapsulated FV extract that FV\r
212 //\r
213 DxeIplAddEncapsulatedFirmwareVolumes ();\r
214 \r
215 //\r
216 // Look in all the FVs present in PEI and find the DXE Core\r
217 //\r
218 Instance = 0;\r
219 Status = DxeIplFindFirmwareVolumeInstance (&Instance, EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);\r
220 ASSERT_EFI_ERROR (Status);\r
221\r
222 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));\r
223\r
224 //\r
225 // Load the DXE Core from a Firmware Volume\r
226 //\r
227 Status = PeiLoadFile (\r
228 FileHandle,\r
229 &DxeCoreAddress,\r
230 &DxeCoreSize,\r
231 &DxeCoreEntryPoint\r
232 );\r
233\r
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
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
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
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
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
278\r
279STATIC\r
280EFI_STATUS\r
281GetFvAlignment (\r
282 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
283 OUT UINT32 *FvAlignment\r
284 )\r
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
298\r
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
322\r
323 Status = EFI_NOT_FOUND;\r
324 Index = 0;\r
325\r
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
364\r
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
370\r
371 PeiPiLibBuildPiFvInfoPpi (\r
372 (EFI_PHYSICAL_ADDRESS) FvHeader,\r
373 FvHeader->FvLength,\r
374 &(VolumeInfo.FvName),\r
375 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)\r
376 );\r
377 \r
378 ASSERT_EFI_ERROR (Status);\r
379\r
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
398\r
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
417{\r
418 EFI_STATUS Status;\r
419 EFI_STATUS VolumeStatus;\r
420\r
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
428 }\r
429 }\r
430 *Instance += 1;\r
431 } while (!EFI_ERROR (VolumeStatus));\r
432\r
433 return VolumeStatus;\r
434}\r
435\r
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
447EFI_STATUS\r
448PeiLoadFile (\r
449 IN EFI_PEI_FILE_HANDLE FileHandle,\r
450 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
451 OUT UINT64 *ImageSize,\r
452 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
453 )\r
454{\r
455\r
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
460\r
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
470\r
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
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
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
592 UINT32 SectionLength;\r
593 UINT32 DestinationSize; \r
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
610 &DestinationSize,\r
611 &ScratchSize\r
612 );\r
613 if (EFI_ERROR (Status)) {\r
614 //\r
615 // GetInfo failed\r
616 //\r
617 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
618 return Status;\r
619 }\r
620\r
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
631 *OutputSize = (UINTN) DestinationSize;\r
632 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));\r
633 if (*OutputBuffer == NULL) {\r
634 return EFI_OUT_OF_RESOURCES;\r
635 }\r
636\r
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
646\r
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
655 return EFI_SUCCESS;\r
656}\r
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