]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Merge EDK899: fixed bug to support EFI_HOB_TYPE_MEMORY_ALLOCATION to allocate resour...
[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 (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, may use LoadFile ppi to do this for save code size.\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 EFI_SIZE_TO_PAGES ((UINT32) DxeCoreSize) * EFI_PAGE_SIZE,\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 DEBUG_CODE_BEGIN ();\r
240\r
241 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;\r
242 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);\r
243 \r
244 if (PtrPeImage.Pe32->FileHeader.Machine != IMAGE_FILE_MACHINE_IA64) {\r
245 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, (VOID *)(UINTN)DxeCoreEntryPoint));\r
246 } else {\r
247 //\r
248 // For IPF Image, the real entry point should be print.\r
249 //\r
250 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)DxeCoreEntryPoint)));\r
251 }\r
252\r
253 DEBUG_CODE_END ();\r
254 //\r
255 // Transfer control to the DXE Core\r
256 // The handoff state is simply a pointer to the HOB list\r
257 //\r
258 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
259 //\r
260 // If we get here, then the DXE Core returned. This is an error\r
261 // Dxe Core should not return.\r
262 //\r
263 ASSERT (FALSE);\r
264 CpuDeadLoop ();\r
265\r
266 return EFI_OUT_OF_RESOURCES;\r
267}\r
268\r
269\r
270STATIC\r
271EFI_STATUS\r
272GetFvAlignment (\r
273 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
274 OUT UINT32 *FvAlignment\r
275 )\r
276{\r
277 //\r
278 // Because FvLength in FvHeader is UINT64 type, \r
279 // so FvHeader must meed at least 8 bytes alignment.\r
280 // Get the appropriate alignment requirement.\r
281 // \r
282 if ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) < EFI_FVB2_ALIGNMENT_8) {\r
283 return EFI_UNSUPPORTED;\r
284 }\r
285 \r
286 *FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
287 return EFI_SUCCESS;\r
288}\r
289\r
290/**\r
291 Search EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE image and expand \r
292 as memory FV \r
293 \r
294 @return EFI_OUT_OF_RESOURCES There are no memory space to exstract FV\r
295 @return EFI_SUCESS Sucess to find the FV \r
296**/\r
297EFI_STATUS\r
298DxeIplAddEncapsulatedFirmwareVolumes (\r
299 VOID\r
300 )\r
301{\r
302 EFI_STATUS Status;\r
303 EFI_STATUS VolumeStatus;\r
304 UINTN Index;\r
305 EFI_FV_INFO VolumeInfo; \r
306 EFI_PEI_FV_HANDLE VolumeHandle;\r
307 EFI_PEI_FILE_HANDLE FileHandle;\r
308 UINT32 SectionLength;\r
309 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
310 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *SectionHeader;\r
311 VOID *DstBuffer;\r
312 UINT32 FvAlignment;\r
313\r
314 Status = EFI_NOT_FOUND;\r
315 Index = 0;\r
316\r
317 do {\r
318 VolumeStatus = DxeIplFindFirmwareVolumeInstance (\r
319 &Index, \r
320 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, \r
321 &VolumeHandle, \r
322 &FileHandle\r
323 );\r
324 \r
325 if (!EFI_ERROR (VolumeStatus)) {\r
326 Status = PeiServicesFfsFindSectionData (\r
327 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, \r
328 (EFI_FFS_FILE_HEADER *)FileHandle, \r
329 (VOID **)&FvHeader\r
330 );\r
331 \r
332 if (!EFI_ERROR (Status)) {\r
333 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
334 //\r
335 // Because FvLength in FvHeader is UINT64 type, \r
336 // so FvHeader must meed at least 8 bytes alignment.\r
337 // If current FvImage base address doesn't meet its alignment,\r
338 // we need to reload this FvImage to another correct memory address.\r
339 //\r
340 Status = GetFvAlignment(FvHeader, &FvAlignment); \r
341 if (EFI_ERROR(Status)) {\r
342 return Status;\r
343 }\r
344 if (((UINTN) FvHeader % FvAlignment) != 0) {\r
345 SectionHeader = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)((UINTN)FvHeader - sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION));\r
346 SectionLength = *(UINT32 *)SectionHeader->Size & 0x00FFFFFF;\r
347 \r
348 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), FvAlignment);\r
349 if (DstBuffer == NULL) {\r
350 return EFI_OUT_OF_RESOURCES;\r
351 }\r
352 CopyMem (DstBuffer, FvHeader, (UINTN) SectionLength - sizeof (EFI_COMMON_SECTION_HEADER));\r
353 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; \r
354 }\r
355\r
356 //\r
357 // This new Firmware Volume comes from a firmware file within a firmware volume.\r
358 // Record the original Firmware Volume Name.\r
359 //\r
360 PeiServicesFfsGetVolumeInfo (&VolumeHandle, &VolumeInfo);\r
361\r
362 PiLibInstallFvInfoPpi (\r
363 NULL,\r
364 FvHeader,\r
365 (UINT32) FvHeader->FvLength,\r
366 &(VolumeInfo.FvName),\r
367 &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name)\r
368 );\r
369\r
370 //\r
371 // Inform HOB consumer phase, i.e. DXE core, the existance of this FV\r
372 //\r
373 BuildFvHob (\r
374 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
375 FvHeader->FvLength\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 //\r
460 // First try to find the PE32 section in this ffs file.\r
461 //\r
462 Status = PeiServicesFfsFindSectionData (\r
463 EFI_SECTION_PE32,\r
464 FileHandle,\r
465 &Pe32Data\r
466 );\r
467 \r
468 if (EFI_ERROR (Status)) {\r
469 //\r
470 // NO image types we support so exit.\r
471 //\r
472 return Status;\r
473 }\r
474\r
475 ZeroMem (&ImageContext, sizeof (ImageContext));\r
476 ImageContext.Handle = Pe32Data;\r
477 Status = GetImageReadFunction (&ImageContext);\r
478\r
479 ASSERT_EFI_ERROR (Status);\r
480\r
481 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
482 if (EFI_ERROR (Status)) {\r
483 return Status;\r
484 }\r
485 //\r
486 // Allocate Memory for the image\r
487 //\r
488 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
489 ASSERT (ImageContext.ImageAddress != 0);\r
490\r
491 //\r
492 // Load the image to our new buffer\r
493 //\r
494 Status = PeCoffLoaderLoadImage (&ImageContext);\r
495 if (EFI_ERROR (Status)) {\r
496 return Status;\r
497 }\r
498 //\r
499 // Relocate the image in our new buffer\r
500 //\r
501 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
502 if (EFI_ERROR (Status)) {\r
503 return Status;\r
504 }\r
505\r
506 //\r
507 // Flush the instruction cache so the image data is written before we execute it\r
508 //\r
509 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
510\r
511 *ImageAddress = ImageContext.ImageAddress;\r
512 *ImageSize = ImageContext.ImageSize;\r
513 *EntryPoint = ImageContext.EntryPoint;\r
514\r
515 return EFI_SUCCESS;\r
516}\r
517\r
518/**\r
519 The ExtractSection() function processes the input section and\r
520 returns a pointer to the section contents. If the section being\r
521 extracted does not require processing (if the section\r
522 GuidedSectionHeader.Attributes has the\r
523 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
524 OutputBuffer is just updated to point to the start of the\r
525 section's contents. Otherwise, *Buffer must be allocated\r
526 from PEI permanent memory.\r
527\r
528 @param This Indicates the\r
529 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
530 Buffer containing the input GUIDed section to be\r
531 processed. OutputBuffer OutputBuffer is\r
532 allocated from PEI permanent memory and contains\r
533 the new section stream.\r
534 \r
535 @param OutputSize A pointer to a caller-allocated\r
536 UINTN in which the size of *OutputBuffer\r
537 allocation is stored. If the function\r
538 returns anything other than EFI_SUCCESS,\r
539 the value of OutputSize is undefined.\r
540 \r
541 @param AuthenticationStatus A pointer to a caller-allocated\r
542 UINT32 that indicates the\r
543 authentication status of the\r
544 output buffer. If the input\r
545 section's GuidedSectionHeader.\r
546 Attributes field has the\r
547 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
548 bit as clear,\r
549 AuthenticationStatus must return\r
550 zero. These bits reflect the\r
551 status of the extraction\r
552 operation. If the function\r
553 returns anything other than\r
554 EFI_SUCCESS, the value of\r
555 AuthenticationStatus is\r
556 undefined.\r
557 \r
558 @retval EFI_SUCCESS The InputSection was\r
559 successfully processed and the\r
560 section contents were returned.\r
561 \r
562 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
563 resources to process the request.\r
564 \r
565 @reteval EFI_INVALID_PARAMETER The GUID in InputSection does\r
566 not match this instance of the\r
567 GUIDed Section Extraction PPI.\r
568**/\r
569EFI_STATUS\r
570CustomGuidedSectionExtract (\r
571 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
572 IN CONST VOID *InputSection,\r
573 OUT VOID **OutputBuffer,\r
574 OUT UINTN *OutputSize,\r
575 OUT UINT32 *AuthenticationStatus\r
576)\r
577{\r
578 EFI_STATUS Status;\r
579 UINT8 *ScratchBuffer;\r
580 UINT32 ScratchBufferSize;\r
581 UINT32 OutputBufferSize;\r
582 UINT16 SectionAttribute;\r
583 \r
584 //\r
585 // Init local variable\r
586 //\r
587 ScratchBuffer = NULL;\r
588\r
589 //\r
590 // Call GetInfo to get the size and attribute of input guided section data.\r
591 //\r
592 Status = ExtractGuidedSectionGetInfo (\r
593 InputSection,\r
594 &OutputBufferSize,\r
595 &ScratchBufferSize,\r
596 &SectionAttribute\r
597 );\r
598 \r
599 if (EFI_ERROR (Status)) {\r
600 DEBUG ((EFI_D_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
601 return Status;\r
602 }\r
603 \r
604 if (ScratchBufferSize != 0) {\r
605 //\r
606 // Allocate scratch buffer\r
607 //\r
608 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
609 if (ScratchBuffer == NULL) {\r
610 return EFI_OUT_OF_RESOURCES;\r
611 }\r
612 }\r
613\r
614 if ((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) && OutputBufferSize > 0) { \r
615 //\r
616 // Allocate output buffer\r
617 //\r
618 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize));\r
619 if (*OutputBuffer == NULL) {\r
620 return EFI_OUT_OF_RESOURCES;\r
621 }\r
622 }\r
623 \r
624 Status = ExtractGuidedSectionDecode (\r
625 InputSection, \r
626 OutputBuffer,\r
627 ScratchBuffer,\r
628 AuthenticationStatus\r
629 );\r
630\r
631 if (EFI_ERROR (Status)) {\r
632 //\r
633 // Decode failed\r
634 //\r
635 DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
636 return Status;\r
637 }\r
638 \r
639 *OutputSize = (UINTN) OutputBufferSize;\r
640 \r
641 return EFI_SUCCESS;\r
642}\r
643\r
644STATIC\r
645EFI_STATUS\r
646EFIAPI \r
647Decompress (\r
648 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
649 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
650 OUT VOID **OutputBuffer,\r
651 OUT UINTN *OutputSize\r
652 )\r
653{\r
654 EFI_STATUS Status;\r
655 UINT8 *DstBuffer;\r
656 UINT8 *ScratchBuffer;\r
657 UINTN DstBufferSize;\r
658 UINT32 ScratchBufferSize;\r
659 EFI_COMMON_SECTION_HEADER *Section;\r
660 UINTN SectionLength;\r
661\r
662 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
663 ASSERT (FALSE);\r
664 return EFI_INVALID_PARAMETER;\r
665 }\r
666\r
667 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
668 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
669 \r
670 //\r
671 // This is a compression set, expand it\r
672 //\r
673 switch (CompressionSection->CompressionType) {\r
674 case EFI_STANDARD_COMPRESSION:\r
675 //\r
676 // Load EFI standard compression.\r
677 // For compressed data, decompress them to dstbuffer.\r
678 //\r
679 Status = UefiDecompressGetInfo (\r
680 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
681 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
682 (UINT32 *) &DstBufferSize,\r
683 &ScratchBufferSize\r
684 );\r
685 if (EFI_ERROR (Status)) {\r
686 //\r
687 // GetInfo failed\r
688 //\r
689 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
690 return EFI_NOT_FOUND;\r
691 }\r
692 //\r
693 // Allocate scratch buffer\r
694 //\r
695 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
696 if (ScratchBuffer == NULL) {\r
697 return EFI_OUT_OF_RESOURCES;\r
698 }\r
699 //\r
700 // Allocate destination buffer\r
701 //\r
702 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
703 if (DstBuffer == NULL) {\r
704 return EFI_OUT_OF_RESOURCES;\r
705 }\r
706 //\r
707 // Call decompress function\r
708 //\r
709 Status = UefiDecompress (\r
710 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
711 DstBuffer,\r
712 ScratchBuffer\r
713 );\r
714 if (EFI_ERROR (Status)) {\r
715 //\r
716 // Decompress failed\r
717 //\r
718 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
719 return EFI_NOT_FOUND;\r
720 }\r
721 break;\r
722\r
723 // porting note the original branch for customized compress is removed, it should be change to use GUID compress\r
724\r
725 case EFI_NOT_COMPRESSED:\r
726 //\r
727 // Allocate destination buffer\r
728 //\r
729 DstBufferSize = CompressionSection->UncompressedLength;\r
730 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
731 if (DstBuffer == NULL) {\r
732 return EFI_OUT_OF_RESOURCES;\r
733 }\r
734 //\r
735 // stream is not actually compressed, just encapsulated. So just copy it.\r
736 //\r
737 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
738 break;\r
739\r
740 default:\r
741 //\r
742 // Don't support other unknown compression type.\r
743 //\r
744 ASSERT (FALSE);\r
745 return EFI_NOT_FOUND;\r
746 }\r
747\r
748 *OutputSize = DstBufferSize;\r
749 *OutputBuffer = DstBuffer;\r
750\r
751 return EFI_SUCCESS;\r
752}\r
753\r