]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
Partially make EdkModulePkg pass intel IPF compiler with /W4 /WX switched on.
[mirror_edk2.git] / EdkModulePkg / Core / DxeIplPeim / DxeLoad.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 DxeLoad.c\r
15\r
16Abstract:\r
17\r
18 Last PEIM.\r
19 Responsibility of this module is to load the DXE Core from a Firmware Volume.\r
20\r
21--*/\r
22\r
abb26634 23#include "DxeIpl.h"\r
24\r
878ddf1f 25BOOLEAN gInMemory = FALSE;\r
26\r
27//\r
28// Module Globals used in the DXE to PEI handoff\r
29// These must be module globals, so the stack can be switched\r
30//\r
31static EFI_DXE_IPL_PPI mDxeIplPpi = {\r
32 DxeLoadCore\r
33};\r
34\r
35static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {\r
36 DxeIplLoadFile\r
37};\r
38\r
abb26634 39static EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
40 {\r
41 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
878ddf1f 42 &gEfiPeiFvFileLoaderPpiGuid,\r
43 &mLoadFilePpi\r
abb26634 44 },\r
45 {\r
878ddf1f 46 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
47 &gEfiDxeIplPpiGuid,\r
48 &mDxeIplPpi\r
abb26634 49 }\r
878ddf1f 50};\r
51\r
52static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {\r
53 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
54 &gEfiEndOfPeiSignalPpiGuid,\r
55 NULL\r
56};\r
57\r
abb26634 58GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = {\r
878ddf1f 59 UefiDecompressGetInfo,\r
60 UefiDecompress\r
61};\r
62\r
abb26634 63GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress = {\r
878ddf1f 64 TianoDecompressGetInfo,\r
65 TianoDecompress\r
66};\r
67\r
abb26634 68GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = {\r
878ddf1f 69 CustomDecompressGetInfo,\r
70 CustomDecompress\r
71};\r
72\r
878ddf1f 73EFI_STATUS\r
74EFIAPI\r
75PeimInitializeDxeIpl (\r
76 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
77 IN EFI_PEI_SERVICES **PeiServices\r
78 )\r
79/*++\r
80\r
81Routine Description:\r
82\r
83 Initializes the Dxe Ipl PPI\r
84\r
85Arguments:\r
86\r
87 FfsHeader - Pointer to FFS file header\r
88 PeiServices - General purpose services available to every PEIM.\r
89\r
90Returns:\r
91\r
92 EFI_SUCCESS\r
93\r
94--*/\r
95{\r
96 EFI_STATUS Status;\r
97 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
98 EFI_BOOT_MODE BootMode;\r
99\r
84a99d48 100 Status = PeiServicesGetBootMode (&BootMode);\r
878ddf1f 101 ASSERT_EFI_ERROR (Status);\r
102\r
abb26634 103 if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) { \r
878ddf1f 104 //\r
105 // The DxeIpl has not yet been shadowed\r
106 //\r
107 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
108\r
109 //\r
110 // Shadow DxeIpl and then re-run its entry point\r
111 //\r
112 Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);\r
878ddf1f 113 } else {\r
878ddf1f 114 //\r
abb26634 115 // Install FvFileLoader and DxeIpl PPIs.\r
878ddf1f 116 //\r
abb26634 117 Status = PeiServicesInstallPpi (mPpiList);\r
118 ASSERT_EFI_ERROR(Status);\r
878ddf1f 119 }\r
abb26634 120 \r
121 return Status;\r
878ddf1f 122}\r
123\r
124EFI_STATUS\r
125EFIAPI\r
126DxeLoadCore (\r
127 IN EFI_DXE_IPL_PPI *This,\r
128 IN EFI_PEI_SERVICES **PeiServices,\r
129 IN EFI_PEI_HOB_POINTERS HobList\r
130 )\r
131/*++\r
132\r
133Routine Description:\r
134\r
135 Main entry point to last PEIM\r
136\r
137Arguments:\r
138 This - Entry point for DXE IPL PPI\r
139 PeiServices - General purpose services available to every PEIM.\r
140 HobList - Address to the Pei HOB list\r
141\r
142Returns:\r
143\r
144 EFI_SUCCESS - DEX core was successfully loaded.\r
145 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.\r
146\r
147--*/\r
148{\r
149 EFI_STATUS Status;\r
878ddf1f 150 EFI_GUID DxeCoreFileName;\r
151 EFI_GUID FirmwareFileName;\r
152 VOID *Pe32Data;\r
abb26634 153 VOID *FvImageData; \r
878ddf1f 154 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
155 UINT64 DxeCoreSize;\r
156 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
157 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
158 EFI_BOOT_MODE BootMode;\r
159 EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;\r
160 EFI_PEI_S3_RESUME_PPI *S3Resume;\r
161\r
162// PERF_START (PeiServices, L"DxeIpl", NULL, 0);\r
878ddf1f 163\r
164 //\r
165 // if in S3 Resume, restore configure\r
166 //\r
84a99d48 167 Status = PeiServicesGetBootMode (&BootMode);\r
abb26634 168 ASSERT_EFI_ERROR(Status);\r
878ddf1f 169\r
abb26634 170 if (BootMode == BOOT_ON_S3_RESUME) {\r
84a99d48 171 Status = PeiServicesLocatePpi (\r
878ddf1f 172 &gEfiPeiS3ResumePpiGuid,\r
173 0,\r
174 NULL,\r
175 (VOID **)&S3Resume\r
176 );\r
878ddf1f 177 ASSERT_EFI_ERROR (Status);\r
178\r
179 Status = S3Resume->S3RestoreConfig (PeiServices);\r
878ddf1f 180 ASSERT_EFI_ERROR (Status);\r
abb26634 181 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
878ddf1f 182\r
84a99d48 183 Status = PeiServicesLocatePpi (\r
878ddf1f 184 &gEfiPeiRecoveryModulePpiGuid,\r
185 0,\r
186 NULL,\r
187 (VOID **)&PeiRecovery\r
188 );\r
878ddf1f 189 ASSERT_EFI_ERROR (Status);\r
abb26634 190\r
878ddf1f 191 Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);\r
f78797d5
LG
192 if (EFI_ERROR (Status)) {\r
193 DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
194 CpuDeadLoop ();\r
195 }\r
878ddf1f 196\r
197 //\r
198 // Now should have a HOB with the DXE core w/ the old HOB destroyed\r
199 //\r
200 }\r
201\r
202 //\r
abb26634 203 // Install the PEI Protocols that are shared between PEI and DXE\r
204 //\r
205 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
206 ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
207\r
abb26634 208\r
209 //\r
210 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file\r
878ddf1f 211 // The file found will be processed by PeiProcessFile: It will first be decompressed to\r
abb26634 212 // a normal FV, then a corresponding FV type hob will be built. \r
878ddf1f 213 //\r
214 Status = PeiFindFile (\r
abb26634 215 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
216 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
217 &FirmwareFileName,\r
218 &FvImageData\r
219 );\r
878ddf1f 220\r
221 //\r
222 // Find the DXE Core in a Firmware Volume\r
223 //\r
224 Status = PeiFindFile (\r
225 EFI_FV_FILETYPE_DXE_CORE,\r
226 EFI_SECTION_PE32,\r
227 &DxeCoreFileName,\r
228 &Pe32Data\r
229 );\r
878ddf1f 230 ASSERT_EFI_ERROR (Status);\r
231\r
232 //\r
233 // Load the DXE Core from a Firmware Volume\r
234 //\r
235 Status = PeiLoadFile (\r
abb26634 236 PeiEfiPeiPeCoffLoader,\r
237 Pe32Data,\r
238 &DxeCoreAddress,\r
239 &DxeCoreSize,\r
240 &DxeCoreEntryPoint\r
241 );\r
878ddf1f 242 ASSERT_EFI_ERROR (Status);\r
243\r
878ddf1f 244 //\r
245 // Add HOB for the DXE Core\r
246 //\r
247 BuildModuleHob (\r
248 &DxeCoreFileName,\r
249 DxeCoreAddress,\r
250 DxeCoreSize,\r
251 DxeCoreEntryPoint\r
252 );\r
253\r
254 //\r
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
657d3918 262 if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs)) {\r
263 if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress)) {\r
264 //\r
265 // Add HOB for the EFI Decompress Protocol\r
266 //\r
267 BuildGuidDataHob (\r
268 &gEfiDecompressProtocolGuid,\r
269 (VOID *)&gEfiDecompress,\r
270 sizeof (gEfiDecompress)\r
271 );\r
272 }\r
273 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {\r
274 //\r
275 // Add HOB for the Tiano Decompress Protocol\r
276 //\r
277 BuildGuidDataHob (\r
278 &gEfiTianoDecompressProtocolGuid,\r
279 (VOID *)&gTianoDecompress,\r
280 sizeof (gTianoDecompress)\r
281 );\r
282 }\r
283 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {\r
284 //\r
285 // Add HOB for the user customized Decompress Protocol\r
286 //\r
287 BuildGuidDataHob (\r
288 &gEfiCustomizedDecompressProtocolGuid,\r
289 (VOID *)&gCustomDecompress,\r
290 sizeof (gCustomDecompress)\r
291 );\r
292 }\r
abb26634 293\r
294 //\r
295 // Add HOB for the PE/COFF Loader Protocol\r
296 //\r
297 BuildGuidDataHob (\r
298 &gEfiPeiPeCoffLoaderGuid,\r
299 (VOID *)&PeiEfiPeiPeCoffLoader,\r
300 sizeof (VOID *)\r
301 );\r
657d3918 302 }\r
303\r
3d109491 304 //\r
305 // Transfer control to the DXE Core\r
306 // The handoff state is simply a pointer to the HOB list\r
307 //\r
308\r
b32a39b3 309 DEBUG ((EFI_D_INFO, "DXE Core Entry Point 0x%08x\n", (UINTN) DxeCoreEntryPoint));\r
3d109491 310 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
878ddf1f 311 //\r
312 // If we get here, then the DXE Core returned. This is an error\r
f78797d5 313 // Dxe Core should not return.\r
878ddf1f 314 //\r
f78797d5
LG
315 ASSERT (FALSE);\r
316 CpuDeadLoop ();\r
878ddf1f 317\r
318 return EFI_OUT_OF_RESOURCES;\r
319}\r
320\r
321EFI_STATUS\r
322PeiFindFile (\r
323 IN UINT8 Type,\r
324 IN UINT16 SectionType,\r
325 OUT EFI_GUID *FileName,\r
326 OUT VOID **Pe32Data\r
327 )\r
328/*++\r
329\r
330Routine Description:\r
331\r
332 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes\r
333 described in the HOB list. Able to search in a compression set in a FFS file.\r
334 But only one level of compression is supported, that is, not able to search\r
335 in a compression set that is within another compression set.\r
336\r
337Arguments:\r
338\r
339 Type - The Type of file to retrieve\r
340\r
341 SectionType - The type of section to retrieve from a file\r
342\r
343 FileName - The name of the file found in the Firmware Volume\r
344\r
345 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume\r
346\r
347Returns:\r
348\r
349 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to\r
350 the PE/COFF image is returned in Pe32Data\r
351\r
352 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List\r
353\r
354--*/\r
355{\r
356 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
357 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
878ddf1f 358 EFI_STATUS Status;\r
359 EFI_PEI_HOB_POINTERS Hob;\r
360\r
361\r
362 FwVolHeader = NULL;\r
363 FfsFileHeader = NULL;\r
abb26634 364 Status = EFI_SUCCESS;\r
878ddf1f 365\r
366 //\r
abb26634 367 // For each Firmware Volume, look for a specified type\r
368 // of file and break out until no one is found \r
878ddf1f 369 //\r
370 Hob.Raw = GetHobList ();\r
371 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {\r
372 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);\r
84a99d48 373 Status = PeiServicesFfsFindNextFile (\r
878ddf1f 374 Type,\r
375 FwVolHeader,\r
376 &FfsFileHeader\r
377 );\r
378 if (!EFI_ERROR (Status)) {\r
878ddf1f 379 Status = PeiProcessFile (\r
380 SectionType,\r
abb26634 381 FfsFileHeader,\r
382 Pe32Data,\r
383 &Hob\r
878ddf1f 384 );\r
6326ee4e 385 CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
abb26634 386 if (!EFI_ERROR (Status)) {\r
387 return EFI_SUCCESS;\r
388 }\r
878ddf1f 389 }\r
390 Hob.Raw = GET_NEXT_HOB (Hob);\r
391 }\r
392 return EFI_NOT_FOUND;\r
393}\r
394\r
395EFI_STATUS\r
396PeiLoadFile (\r
397 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,\r
398 IN VOID *Pe32Data,\r
399 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
400 OUT UINT64 *ImageSize,\r
401 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
402 )\r
403/*++\r
404\r
405Routine Description:\r
406\r
407 Loads and relocates a PE/COFF image into memory.\r
408\r
409Arguments:\r
410\r
411 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
412\r
413 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
414\r
415 ImageAddress - The base address of the relocated PE/COFF image\r
416\r
417 ImageSize - The size of the relocated PE/COFF image\r
418\r
419 EntryPoint - The entry point of the relocated PE/COFF image\r
420\r
421Returns:\r
422\r
423 EFI_SUCCESS - The file was loaded and relocated\r
424\r
425 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
426\r
427--*/\r
428{\r
429 EFI_STATUS Status;\r
430 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
431\r
432 ZeroMem (&ImageContext, sizeof (ImageContext));\r
433 ImageContext.Handle = Pe32Data;\r
434 Status = GetImageReadFunction (&ImageContext);\r
435\r
436 ASSERT_EFI_ERROR (Status);\r
437\r
438 Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);\r
439 if (EFI_ERROR (Status)) {\r
440 return Status;\r
441 }\r
442 //\r
443 // Allocate Memory for the image\r
444 //\r
445 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
446 ASSERT (ImageContext.ImageAddress != 0);\r
447\r
448 //\r
449 // Load the image to our new buffer\r
450 //\r
451 Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
452 if (EFI_ERROR (Status)) {\r
453 return Status;\r
454 }\r
455 //\r
456 // Relocate the image in our new buffer\r
457 //\r
458 Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
459 if (EFI_ERROR (Status)) {\r
460 return Status;\r
461 }\r
462\r
463 //\r
464 // Flush the instruction cache so the image data is written before we execute it\r
465 //\r
466 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
467\r
468 *ImageAddress = ImageContext.ImageAddress;\r
469 *ImageSize = ImageContext.ImageSize;\r
470 *EntryPoint = ImageContext.EntryPoint;\r
471\r
472 return EFI_SUCCESS;\r
473}\r
474\r
475EFI_STATUS\r
476ShadowDxeIpl (\r
477 IN EFI_FFS_FILE_HEADER *DxeIplFileHeader,\r
478 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader\r
479 )\r
480/*++\r
481\r
482Routine Description:\r
483\r
484 Shadow the DXE IPL to a different memory location. This occurs after permanent\r
485 memory has been discovered.\r
486\r
487Arguments:\r
488\r
489 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver\r
490\r
491 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
492\r
493Returns:\r
494\r
495 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.\r
496\r
497 EFI_ ERROR - The shadow was unsuccessful.\r
498\r
499\r
500--*/\r
501{\r
502 UINTN SectionLength;\r
503 UINTN OccupiedSectionLength;\r
504 EFI_PHYSICAL_ADDRESS DxeIplAddress;\r
505 UINT64 DxeIplSize;\r
506 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint;\r
507 EFI_STATUS Status;\r
508 EFI_COMMON_SECTION_HEADER *Section;\r
509\r
510 Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1);\r
511\r
512 while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {\r
513 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
abb26634 514 OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
878ddf1f 515 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
516 }\r
517 //\r
518 // Relocate DxeIpl into memory by using loadfile service\r
519 //\r
520 Status = PeiLoadFile (\r
521 PeiEfiPeiPeCoffLoader,\r
522 (VOID *) (Section + 1),\r
523 &DxeIplAddress,\r
524 &DxeIplSize,\r
525 &DxeIplEntryPoint\r
526 );\r
527\r
528 if (Status == EFI_SUCCESS) {\r
529 //\r
abb26634 530 // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.\r
878ddf1f 531 //\r
abb26634 532 *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE;\r
878ddf1f 533 Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());\r
534 }\r
535\r
536 return Status;\r
537}\r
538\r
539EFI_STATUS\r
540EFIAPI\r
541DxeIplLoadFile (\r
542 IN EFI_PEI_FV_FILE_LOADER_PPI *This,\r
543 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
544 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
545 OUT UINT64 *ImageSize,\r
546 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
547 )\r
548/*++\r
549\r
550Routine Description:\r
551\r
552 Given a pointer to an FFS file containing a PE32 image, get the\r
553 information on the PE32 image, and then "load" it so that it\r
554 can be executed.\r
555\r
556Arguments:\r
557\r
558 This - pointer to our file loader protocol\r
559\r
560 FfsHeader - pointer to the FFS file header of the FFS file that\r
561 contains the PE32 image we want to load\r
562\r
563 ImageAddress - returned address where the PE32 image is loaded\r
564\r
565 ImageSize - returned size of the loaded PE32 image\r
566\r
567 EntryPoint - entry point to the loaded PE32 image\r
568\r
569Returns:\r
570\r
571 EFI_SUCCESS - The FFS file was successfully loaded.\r
572\r
573 EFI_ERROR - Unable to load the FFS file.\r
574\r
575--*/\r
576{\r
577 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
578 EFI_STATUS Status;\r
579 VOID *Pe32Data;\r
580\r
581 Pe32Data = NULL;\r
582 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
583\r
584 //\r
585 // Preprocess the FFS file to get a pointer to the PE32 information\r
586 // in the enclosed PE32 image.\r
587 //\r
588 Status = PeiProcessFile (\r
589 EFI_SECTION_PE32,\r
abb26634 590 FfsHeader,\r
591 &Pe32Data,\r
592 NULL\r
878ddf1f 593 );\r
594\r
595 if (EFI_ERROR (Status)) {\r
596 return Status;\r
597 }\r
598 //\r
599 // Load the PE image from the FFS file\r
600 //\r
601 Status = PeiLoadFile (\r
602 PeiEfiPeiPeCoffLoader,\r
603 Pe32Data,\r
604 ImageAddress,\r
605 ImageSize,\r
606 EntryPoint\r
607 );\r
608\r
609 return Status;\r
610}\r
611\r
612EFI_STATUS\r
613PeiProcessFile (\r
6326ee4e 614 IN UINT16 SectionType,\r
abb26634 615 IN EFI_FFS_FILE_HEADER *FfsFileHeader,\r
616 OUT VOID **Pe32Data,\r
617 IN EFI_PEI_HOB_POINTERS *OrigHob\r
878ddf1f 618 )\r
619/*++\r
620\r
621Routine Description:\r
622\r
623Arguments:\r
624\r
625 SectionType - The type of section in the FFS file to process.\r
626\r
627 FfsFileHeader - Pointer to the FFS file to process, looking for the\r
628 specified SectionType\r
629\r
630 Pe32Data - returned pointer to the start of the PE32 image found\r
631 in the FFS file.\r
632\r
633Returns:\r
634\r
635 EFI_SUCCESS - found the PE32 section in the FFS file\r
636\r
637--*/\r
638{\r
639 EFI_STATUS Status;\r
640 VOID *SectionData;\r
641 DECOMPRESS_LIBRARY *DecompressLibrary;\r
642 UINT8 *DstBuffer;\r
643 UINT8 *ScratchBuffer;\r
644 UINT32 DstBufferSize;\r
645 UINT32 ScratchBufferSize;\r
646 EFI_COMMON_SECTION_HEADER *CmpSection;\r
647 UINTN CmpSectionLength;\r
648 UINTN OccupiedCmpSectionLength;\r
649 VOID *CmpFileData;\r
650 UINTN CmpFileSize;\r
651 EFI_COMMON_SECTION_HEADER *Section;\r
652 UINTN SectionLength;\r
653 UINTN OccupiedSectionLength;\r
654 UINT64 FileSize;\r
878ddf1f 655 UINT32 AuthenticationStatus;\r
656 EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;\r
657 UINT32 BufferSize;\r
658 UINT8 *Buffer;\r
659 EFI_PEI_SECURITY_PPI *Security;\r
660 BOOLEAN StartCrisisRecovery;\r
661 EFI_GUID TempGuid;\r
662 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
663 EFI_COMPRESSION_SECTION *CompressionSection;\r
abb26634 664 UINT32 FvAlignment;\r
878ddf1f 665\r
4afc6a7b
LG
666 //\r
667 // Initialize local variables.\r
668 //\r
669 DecompressLibrary = NULL;\r
670 DstBuffer = NULL;\r
671 DstBufferSize = 0;\r
672\r
84a99d48 673 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 674 EFI_SECTION_COMPRESSION,\r
675 FfsFileHeader,\r
676 &SectionData\r
677 );\r
678\r
679 //\r
abb26634 680 // First process the compression section\r
878ddf1f 681 //\r
682 if (!EFI_ERROR (Status)) {\r
683 //\r
684 // Yes, there is a compression section, so extract the contents\r
685 // Decompress the image here\r
686 //\r
687 Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
688\r
689 do {\r
690 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
abb26634 691 OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
878ddf1f 692\r
693 //\r
694 // Was the DXE Core file encapsulated in a GUID'd section?\r
695 //\r
696 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
878ddf1f 697\r
698 //\r
699 // This following code constitutes the addition of the security model\r
700 // to the DXE IPL.\r
701 //\r
702 //\r
703 // Set a default authenticatino state\r
704 //\r
705 AuthenticationStatus = 0;\r
706\r
84a99d48 707 Status = PeiServicesLocatePpi (\r
878ddf1f 708 &gEfiPeiSectionExtractionPpiGuid,\r
709 0,\r
710 NULL,\r
711 (VOID **)&SectionExtract\r
712 );\r
713\r
714 if (EFI_ERROR (Status)) {\r
715 return Status;\r
716 }\r
717 //\r
718 // Verify Authentication State\r
719 //\r
720 CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));\r
721\r
722 Status = SectionExtract->PeiGetSection (\r
723 GetPeiServicesTablePointer(),\r
724 SectionExtract,\r
725 (EFI_SECTION_TYPE *) &SectionType,\r
726 &TempGuid,\r
727 0,\r
728 (VOID **) &Buffer,\r
729 &BufferSize,\r
730 &AuthenticationStatus\r
731 );\r
732\r
733 if (EFI_ERROR (Status)) {\r
734 return Status;\r
735 }\r
736 //\r
737 // If not ask the Security PPI, if exists, for disposition\r
738 //\r
739 //\r
84a99d48 740 Status = PeiServicesLocatePpi (\r
878ddf1f 741 &gEfiPeiSecurityPpiGuid,\r
742 0,\r
743 NULL,\r
744 (VOID **)&Security\r
745 );\r
746 if (EFI_ERROR (Status)) {\r
747 return Status;\r
748 }\r
749\r
750 Status = Security->AuthenticationState (\r
751 GetPeiServicesTablePointer(),\r
752 (struct _EFI_PEI_SECURITY_PPI *) Security,\r
753 AuthenticationStatus,\r
754 FfsFileHeader,\r
755 &StartCrisisRecovery\r
756 );\r
757\r
758 if (EFI_ERROR (Status)) {\r
759 return Status;\r
760 }\r
761 //\r
762 // If there is a security violation, report to caller and have\r
763 // the upper-level logic possible engender a crisis recovery\r
764 //\r
765 if (StartCrisisRecovery) {\r
766 return EFI_SECURITY_VIOLATION;\r
767 }\r
768 }\r
769\r
770 if (Section->Type == EFI_SECTION_PE32) {\r
771 //\r
772 // This is what we want\r
773 //\r
774 *Pe32Data = (VOID *) (Section + 1);\r
775 return EFI_SUCCESS;\r
776 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
777 //\r
778 // This is a compression set, expand it\r
779 //\r
780 CompressionSection = (EFI_COMPRESSION_SECTION *) Section;\r
781\r
782 switch (CompressionSection->CompressionType) {\r
783 case EFI_STANDARD_COMPRESSION:\r
4afc6a7b
LG
784 //\r
785 // Load EFI standard compression.\r
786 //\r
abb26634 787 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {\r
4afc6a7b 788 DecompressLibrary = &gEfiDecompress;\r
abb26634 789 } else {\r
790 ASSERT (FALSE);\r
791 return EFI_NOT_FOUND;\r
792 }\r
878ddf1f 793 break;\r
794\r
795 case EFI_CUSTOMIZED_COMPRESSION:\r
796 //\r
4afc6a7b 797 // Load user customized compression.\r
878ddf1f 798 //\r
abb26634 799 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {\r
800 DecompressLibrary = &gCustomDecompress;\r
801 } else {\r
802 ASSERT (FALSE);\r
803 return EFI_NOT_FOUND;\r
804 }\r
878ddf1f 805 break;\r
806\r
807 case EFI_NOT_COMPRESSED:\r
4afc6a7b
LG
808 //\r
809 // Allocate destination buffer\r
810 //\r
811 DstBufferSize = CompressionSection->UncompressedLength;\r
812 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
813 if (DstBuffer == NULL) {\r
814 return EFI_OUT_OF_RESOURCES;\r
815 }\r
816 //\r
817 // stream is not actually compressed, just encapsulated. So just copy it.\r
818 //\r
819 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
820 break;\r
821\r
878ddf1f 822 default:\r
823 //\r
4afc6a7b 824 // Don't support other unknown compression type.\r
878ddf1f 825 //\r
826 ASSERT_EFI_ERROR (Status);\r
827 return EFI_NOT_FOUND;\r
828 }\r
4afc6a7b
LG
829 \r
830 if (CompressionSection->CompressionType != EFI_NOT_COMPRESSED) {\r
878ddf1f 831 //\r
4afc6a7b 832 // For compressed data, decompress them to dstbuffer.\r
878ddf1f 833 //\r
4afc6a7b
LG
834 Status = DecompressLibrary->GetInfo (\r
835 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
836 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
837 &DstBufferSize,\r
838 &ScratchBufferSize\r
839 );\r
840 if (EFI_ERROR (Status)) {\r
841 //\r
842 // GetInfo failed\r
843 //\r
e75ac0cc 844 DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
4afc6a7b
LG
845 return EFI_NOT_FOUND;\r
846 }\r
847 \r
848 //\r
849 // Allocate scratch buffer\r
850 //\r
851 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
852 if (ScratchBuffer == NULL) {\r
853 return EFI_OUT_OF_RESOURCES;\r
854 }\r
855 \r
856 //\r
857 // Allocate destination buffer\r
858 //\r
859 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
860 if (DstBuffer == NULL) {\r
861 return EFI_OUT_OF_RESOURCES;\r
862 }\r
863 \r
864 //\r
865 // Call decompress function\r
866 //\r
867 Status = DecompressLibrary->Decompress (\r
868 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
869 DstBuffer,\r
870 ScratchBuffer\r
871 );\r
e75ac0cc
LG
872 if (EFI_ERROR (Status)) {\r
873 //\r
874 // Decompress failed\r
875 //\r
876 DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
877 return EFI_NOT_FOUND;\r
878 }\r
878ddf1f 879 }\r
4afc6a7b 880 \r
878ddf1f 881 CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
abb26634 882 if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
883 // \r
884 // Firmware Volume Image in this Section\r
885 // Skip the section header to get FvHeader\r
878ddf1f 886 //\r
abb26634 887 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
878ddf1f 888\r
abb26634 889 if (FvHeader->Signature == EFI_FVH_SIGNATURE) { \r
890 //\r
891 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header\r
892 //\r
893 \r
894 //\r
895 // When FvImage support Alignment, we need to check whether \r
896 // its alignment is correct. \r
897 //\r
898 if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {\r
899 \r
900 //\r
901 // Calculate the mini alignment for this FvImage\r
902 //\r
903 FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1);\r
904 \r
905 //\r
906 // If current FvImage base address doesn't meet the its alignment,\r
907 // we need to reload this FvImage to another correct memory address.\r
908 //\r
909 if (((UINTN) FvHeader % FvAlignment) != 0) {\r
910 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment);\r
911 if (DstBuffer == NULL) {\r
912 return EFI_OUT_OF_RESOURCES;\r
913 }\r
914 CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength);\r
915 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; \r
916 }\r
917 }\r
918 //\r
919 // Build new FvHob for new decompressed Fv image.\r
920 //\r
878ddf1f 921 BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
abb26634 922 \r
923 //\r
924 // Set the original FvHob to unused.\r
925 //\r
926 if (OrigHob != NULL) {\r
927 OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;\r
878ddf1f 928 }\r
abb26634 929 \r
6326ee4e 930 //\r
abb26634 931 // when search FvImage Section return true.\r
6326ee4e 932 //\r
abb26634 933 if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
934 *Pe32Data = (VOID *) FvHeader;\r
935 return EFI_SUCCESS;\r
936 } else {\r
937 return EFI_NOT_FOUND;\r
938 }\r
878ddf1f 939 }\r
940 }\r
941 //\r
942 // Decompress successfully.\r
943 // Loop the decompressed data searching for expected section.\r
944 //\r
945 CmpFileData = (VOID *) DstBuffer;\r
946 CmpFileSize = DstBufferSize;\r
947 do {\r
948 CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
949 if (CmpSection->Type == EFI_SECTION_PE32) {\r
950 //\r
951 // This is what we want\r
952 //\r
953 *Pe32Data = (VOID *) (CmpSection + 1);\r
954 return EFI_SUCCESS;\r
955 }\r
956\r
abb26634 957 OccupiedCmpSectionLength = GET_OCCUPIED_SIZE (CmpSectionLength, 4);\r
878ddf1f 958 CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
959 } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
960 }\r
abb26634 961 //\r
962 // End of the decompression activity\r
963 //\r
878ddf1f 964\r
965 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
966 FileSize = FfsFileHeader->Size[0] & 0xFF;\r
967 FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
968 FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
969 FileSize &= 0x00FFFFFF;\r
970 } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
abb26634 971 \r
878ddf1f 972 //\r
abb26634 973 // search all sections (compression and non compression) in this FFS, don't \r
974 // find expected section.\r
878ddf1f 975 //\r
abb26634 976 return EFI_NOT_FOUND;\r
878ddf1f 977 } else {\r
abb26634 978 //\r
979 // For those FFS that doesn't contain compression section, directly search \r
980 // PE or TE section in this FFS.\r
981 //\r
878ddf1f 982\r
84a99d48 983 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 984 EFI_SECTION_PE32,\r
985 FfsFileHeader,\r
986 &SectionData\r
987 );\r
988\r
989 if (EFI_ERROR (Status)) {\r
84a99d48 990 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 991 EFI_SECTION_TE,\r
992 FfsFileHeader,\r
993 &SectionData\r
994 );\r
995 if (EFI_ERROR (Status)) {\r
996 return Status;\r
997 }\r
998 }\r
999 }\r
1000\r
1001 *Pe32Data = SectionData;\r
1002\r
1003 return EFI_SUCCESS;\r
1004}\r
abb26634 1005\r