]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
Fix capitalization issues.
[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
122 Status = PeiCoreGetBootMode (&BootMode);\r
123\r
124 ASSERT_EFI_ERROR (Status);\r
125\r
126 Status = PeiCoreLocatePpi (\r
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
157 Status = PeiCoreInstallPpi (&mPpiLoadFile);\r
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
166 PeiCoreInstallPpi (&mPpiList);\r
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
226 Status = PeiCoreGetBootMode (&BootMode);\r
227\r
228 if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {\r
229 Status = PeiCoreLocatePpi (\r
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
310 Status = PeiCoreGetBootMode (&BootMode);\r
311\r
312 if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {\r
313\r
314 Status = PeiCoreLocatePpi (\r
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
376 Status = PeiCoreInstallPpi (&mPpiSignal);\r
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
467 Status = PeiCoreFfsFindNextFile (\r
468 Type,\r
469 FwVolHeader,\r
470 &FfsFileHeader\r
471 );\r
472 if (!EFI_ERROR (Status)) {\r
473 CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
474 Status = PeiProcessFile (\r
475 SectionType,\r
476 FfsFileHeader,\r
477 Pe32Data\r
478 );\r
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
623 Status = PeiCoreInstallPpi (&mPpiPeiInMemory);\r
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
686 FfsHeader,\r
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
709 IN UINT16 SectionType,\r
710 IN EFI_FFS_FILE_HEADER *FfsFileHeader,\r
711 OUT VOID **Pe32Data\r
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
759\r
760 Status = PeiCoreFfsFindSectionData (\r
761 EFI_SECTION_COMPRESSION,\r
762 FfsFileHeader,\r
763 &SectionData\r
764 );\r
765\r
766 //\r
767 // Upon finding a DXE Core file, see if there is first a compression section\r
768 //\r
769 if (!EFI_ERROR (Status)) {\r
770 //\r
771 // Yes, there is a compression section, so extract the contents\r
772 // Decompress the image here\r
773 //\r
774 Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
775\r
776 do {\r
777 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
778 OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
779\r
780 //\r
781 // Was the DXE Core file encapsulated in a GUID'd section?\r
782 //\r
783 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
784 //\r
785 // Locate the GUID'd Section Extractor\r
786 //\r
787 GuidedSectionHeader = (VOID *) (Section + 1);\r
788\r
789 //\r
790 // This following code constitutes the addition of the security model\r
791 // to the DXE IPL.\r
792 //\r
793 //\r
794 // Set a default authenticatino state\r
795 //\r
796 AuthenticationStatus = 0;\r
797\r
798 Status = PeiCoreLocatePpi (\r
799 &gEfiPeiSectionExtractionPpiGuid,\r
800 0,\r
801 NULL,\r
802 (VOID **)&SectionExtract\r
803 );\r
804\r
805 if (EFI_ERROR (Status)) {\r
806 return Status;\r
807 }\r
808 //\r
809 // Verify Authentication State\r
810 //\r
811 CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));\r
812\r
813 Status = SectionExtract->PeiGetSection (\r
814 GetPeiServicesTablePointer(),\r
815 SectionExtract,\r
816 (EFI_SECTION_TYPE *) &SectionType,\r
817 &TempGuid,\r
818 0,\r
819 (VOID **) &Buffer,\r
820 &BufferSize,\r
821 &AuthenticationStatus\r
822 );\r
823\r
824 if (EFI_ERROR (Status)) {\r
825 return Status;\r
826 }\r
827 //\r
828 // If not ask the Security PPI, if exists, for disposition\r
829 //\r
830 //\r
831 Status = PeiCoreLocatePpi (\r
832 &gEfiPeiSecurityPpiGuid,\r
833 0,\r
834 NULL,\r
835 (VOID **)&Security\r
836 );\r
837 if (EFI_ERROR (Status)) {\r
838 return Status;\r
839 }\r
840\r
841 Status = Security->AuthenticationState (\r
842 GetPeiServicesTablePointer(),\r
843 (struct _EFI_PEI_SECURITY_PPI *) Security,\r
844 AuthenticationStatus,\r
845 FfsFileHeader,\r
846 &StartCrisisRecovery\r
847 );\r
848\r
849 if (EFI_ERROR (Status)) {\r
850 return Status;\r
851 }\r
852 //\r
853 // If there is a security violation, report to caller and have\r
854 // the upper-level logic possible engender a crisis recovery\r
855 //\r
856 if (StartCrisisRecovery) {\r
857 return EFI_SECURITY_VIOLATION;\r
858 }\r
859 }\r
860\r
861 if (Section->Type == EFI_SECTION_PE32) {\r
862 //\r
863 // This is what we want\r
864 //\r
865 *Pe32Data = (VOID *) (Section + 1);\r
866 return EFI_SUCCESS;\r
867 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
868 //\r
869 // This is a compression set, expand it\r
870 //\r
871 CompressionSection = (EFI_COMPRESSION_SECTION *) Section;\r
872\r
873 switch (CompressionSection->CompressionType) {\r
874 case EFI_STANDARD_COMPRESSION:\r
875 DecompressLibrary = &gTianoDecompress;\r
876 break;\r
877\r
878 case EFI_CUSTOMIZED_COMPRESSION:\r
879 //\r
880 // Load user customized compression protocol.\r
881 //\r
882 DecompressLibrary = &gCustomDecompress;\r
883 break;\r
884\r
885 case EFI_NOT_COMPRESSED:\r
886 default:\r
887 //\r
888 // Need to support not compressed file\r
889 //\r
890 ASSERT_EFI_ERROR (Status);\r
891 return EFI_NOT_FOUND;\r
892 }\r
893\r
894 Status = DecompressLibrary->GetInfo (\r
895 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
896 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
897 &DstBufferSize,\r
898 &ScratchBufferSize\r
899 );\r
900 if (EFI_ERROR (Status)) {\r
901 //\r
902 // GetInfo failed\r
903 //\r
904 return EFI_NOT_FOUND;\r
905 }\r
906\r
907 //\r
908 // Allocate scratch buffer\r
909 //\r
910 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
911 if (ScratchBuffer == NULL) {\r
912 return EFI_OUT_OF_RESOURCES;\r
913 }\r
914\r
915 //\r
916 // Allocate destination buffer\r
917 //\r
918 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
919 if (DstBuffer == NULL) {\r
920 return EFI_OUT_OF_RESOURCES;\r
921 }\r
922\r
923 //\r
924 // Call decompress function\r
925 //\r
926 Status = DecompressLibrary->Decompress (\r
927 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
928 DstBuffer,\r
929 ScratchBuffer\r
930 );\r
931\r
932 CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
933 if (CmpSection->Type == EFI_SECTION_RAW) {\r
934 //\r
935 // Skip the section header and\r
936 // adjust the pointer alignment to 16\r
937 //\r
938 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);\r
939\r
940 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
941 FfsFileHeader = NULL;\r
942 BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
943 Status = PeiCoreFfsFindNextFile (\r
944 EFI_FV_FILETYPE_DXE_CORE,\r
945 FvHeader,\r
946 &FfsFileHeader\r
947 );\r
948\r
949 if (EFI_ERROR (Status)) {\r
950 return EFI_NOT_FOUND;\r
951 }\r
952\r
953 return PeiProcessFile (SectionType, FfsFileHeader, Pe32Data);\r
954 }\r
955 }\r
956 //\r
957 // Decompress successfully.\r
958 // Loop the decompressed data searching for expected section.\r
959 //\r
960 CmpFileData = (VOID *) DstBuffer;\r
961 CmpFileSize = DstBufferSize;\r
962 do {\r
963 CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
964 if (CmpSection->Type == EFI_SECTION_PE32) {\r
965 //\r
966 // This is what we want\r
967 //\r
968 *Pe32Data = (VOID *) (CmpSection + 1);\r
969 return EFI_SUCCESS;\r
970 }\r
971\r
972 OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);\r
973 CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
974 } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
975 }\r
976\r
977 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
978 FileSize = FfsFileHeader->Size[0] & 0xFF;\r
979 FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
980 FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
981 FileSize &= 0x00FFFFFF;\r
982 } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
983\r
984 //\r
985 // End of the decompression activity\r
986 //\r
987 } else {\r
988\r
989 Status = PeiCoreFfsFindSectionData (\r
990 EFI_SECTION_PE32,\r
991 FfsFileHeader,\r
992 &SectionData\r
993 );\r
994\r
995 if (EFI_ERROR (Status)) {\r
996 Status = PeiCoreFfsFindSectionData (\r
997 EFI_SECTION_TE,\r
998 FfsFileHeader,\r
999 &SectionData\r
1000 );\r
1001 if (EFI_ERROR (Status)) {\r
1002 return Status;\r
1003 }\r
1004 }\r
1005 }\r
1006\r
1007 *Pe32Data = SectionData;\r
1008\r
1009 return EFI_SUCCESS;\r
1010}\r