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