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