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