]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
1. Added Non-existing.c in BaseLib to assert no invocations of SwitchStack() on IPF.
[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
eeb1cd5a 133 if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {\r
878ddf1f 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
eeb1cd5a 399 SwitchIplStacks (\r
878ddf1f 400 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
401 HobList.Raw,\r
eeb1cd5a 402 NULL,\r
403 TopOfStack,\r
404 (VOID *) (UINTN) BspStore\r
878ddf1f 405 );\r
406\r
407 //\r
408 // If we get here, then the DXE Core returned. This is an error\r
409 //\r
410 ASSERT_EFI_ERROR (Status);\r
411\r
412 return EFI_OUT_OF_RESOURCES;\r
413}\r
414\r
415EFI_STATUS\r
416PeiFindFile (\r
417 IN UINT8 Type,\r
418 IN UINT16 SectionType,\r
419 OUT EFI_GUID *FileName,\r
420 OUT VOID **Pe32Data\r
421 )\r
422/*++\r
423\r
424Routine Description:\r
425\r
426 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes\r
427 described in the HOB list. Able to search in a compression set in a FFS file.\r
428 But only one level of compression is supported, that is, not able to search\r
429 in a compression set that is within another compression set.\r
430\r
431Arguments:\r
432\r
433 Type - The Type of file to retrieve\r
434\r
435 SectionType - The type of section to retrieve from a file\r
436\r
437 FileName - The name of the file found in the Firmware Volume\r
438\r
439 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume\r
440\r
441Returns:\r
442\r
443 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to\r
444 the PE/COFF image is returned in Pe32Data\r
445\r
446 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List\r
447\r
448--*/\r
449{\r
450 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
451 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
452 VOID *SectionData;\r
453 EFI_STATUS Status;\r
454 EFI_PEI_HOB_POINTERS Hob;\r
455\r
456\r
457 FwVolHeader = NULL;\r
458 FfsFileHeader = NULL;\r
459 SectionData = NULL;\r
460\r
461 //\r
462 // Foreach Firmware Volume, look for a specified type\r
463 // of file and break out when one is found\r
464 //\r
465 Hob.Raw = GetHobList ();\r
466 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {\r
467 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);\r
84a99d48 468 Status = PeiServicesFfsFindNextFile (\r
878ddf1f 469 Type,\r
470 FwVolHeader,\r
471 &FfsFileHeader\r
472 );\r
473 if (!EFI_ERROR (Status)) {\r
878ddf1f 474 Status = PeiProcessFile (\r
475 SectionType,\r
6326ee4e 476 &FfsFileHeader,\r
878ddf1f 477 Pe32Data\r
478 );\r
6326ee4e 479 CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
878ddf1f 480 return Status;\r
481 }\r
482 Hob.Raw = GET_NEXT_HOB (Hob);\r
483 }\r
484 return EFI_NOT_FOUND;\r
485}\r
486\r
487EFI_STATUS\r
488PeiLoadFile (\r
489 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,\r
490 IN VOID *Pe32Data,\r
491 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
492 OUT UINT64 *ImageSize,\r
493 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
494 )\r
495/*++\r
496\r
497Routine Description:\r
498\r
499 Loads and relocates a PE/COFF image into memory.\r
500\r
501Arguments:\r
502\r
503 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
504\r
505 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
506\r
507 ImageAddress - The base address of the relocated PE/COFF image\r
508\r
509 ImageSize - The size of the relocated PE/COFF image\r
510\r
511 EntryPoint - The entry point of the relocated PE/COFF image\r
512\r
513Returns:\r
514\r
515 EFI_SUCCESS - The file was loaded and relocated\r
516\r
517 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
518\r
519--*/\r
520{\r
521 EFI_STATUS Status;\r
522 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
523\r
524 ZeroMem (&ImageContext, sizeof (ImageContext));\r
525 ImageContext.Handle = Pe32Data;\r
526 Status = GetImageReadFunction (&ImageContext);\r
527\r
528 ASSERT_EFI_ERROR (Status);\r
529\r
530 Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);\r
531 if (EFI_ERROR (Status)) {\r
532 return Status;\r
533 }\r
534 //\r
535 // Allocate Memory for the image\r
536 //\r
537 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
538 ASSERT (ImageContext.ImageAddress != 0);\r
539\r
540 //\r
541 // Load the image to our new buffer\r
542 //\r
543 Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
544 if (EFI_ERROR (Status)) {\r
545 return Status;\r
546 }\r
547 //\r
548 // Relocate the image in our new buffer\r
549 //\r
550 Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
551 if (EFI_ERROR (Status)) {\r
552 return Status;\r
553 }\r
554\r
555 //\r
556 // Flush the instruction cache so the image data is written before we execute it\r
557 //\r
558 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
559\r
560 *ImageAddress = ImageContext.ImageAddress;\r
561 *ImageSize = ImageContext.ImageSize;\r
562 *EntryPoint = ImageContext.EntryPoint;\r
563\r
564 return EFI_SUCCESS;\r
565}\r
566\r
567EFI_STATUS\r
568ShadowDxeIpl (\r
569 IN EFI_FFS_FILE_HEADER *DxeIplFileHeader,\r
570 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader\r
571 )\r
572/*++\r
573\r
574Routine Description:\r
575\r
576 Shadow the DXE IPL to a different memory location. This occurs after permanent\r
577 memory has been discovered.\r
578\r
579Arguments:\r
580\r
581 DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver\r
582\r
583 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
584\r
585Returns:\r
586\r
587 EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location.\r
588\r
589 EFI_ ERROR - The shadow was unsuccessful.\r
590\r
591\r
592--*/\r
593{\r
594 UINTN SectionLength;\r
595 UINTN OccupiedSectionLength;\r
596 EFI_PHYSICAL_ADDRESS DxeIplAddress;\r
597 UINT64 DxeIplSize;\r
598 EFI_PHYSICAL_ADDRESS DxeIplEntryPoint;\r
599 EFI_STATUS Status;\r
600 EFI_COMMON_SECTION_HEADER *Section;\r
601\r
602 Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1);\r
603\r
604 while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {\r
605 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
606 OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
607 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
608 }\r
609 //\r
610 // Relocate DxeIpl into memory by using loadfile service\r
611 //\r
612 Status = PeiLoadFile (\r
613 PeiEfiPeiPeCoffLoader,\r
614 (VOID *) (Section + 1),\r
615 &DxeIplAddress,\r
616 &DxeIplSize,\r
617 &DxeIplEntryPoint\r
618 );\r
619\r
620 if (Status == EFI_SUCCESS) {\r
621 //\r
622 // Install PeiInMemory to indicate the Dxeipl is shadowed\r
623 //\r
84a99d48 624 Status = PeiServicesInstallPpi (&mPpiPeiInMemory);\r
878ddf1f 625\r
626 if (EFI_ERROR (Status)) {\r
627 return Status;\r
628 }\r
629\r
630 Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());\r
631 }\r
632\r
633 return Status;\r
634}\r
635\r
636EFI_STATUS\r
637EFIAPI\r
638DxeIplLoadFile (\r
639 IN EFI_PEI_FV_FILE_LOADER_PPI *This,\r
640 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
641 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
642 OUT UINT64 *ImageSize,\r
643 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
644 )\r
645/*++\r
646\r
647Routine Description:\r
648\r
649 Given a pointer to an FFS file containing a PE32 image, get the\r
650 information on the PE32 image, and then "load" it so that it\r
651 can be executed.\r
652\r
653Arguments:\r
654\r
655 This - pointer to our file loader protocol\r
656\r
657 FfsHeader - pointer to the FFS file header of the FFS file that\r
658 contains the PE32 image we want to load\r
659\r
660 ImageAddress - returned address where the PE32 image is loaded\r
661\r
662 ImageSize - returned size of the loaded PE32 image\r
663\r
664 EntryPoint - entry point to the loaded PE32 image\r
665\r
666Returns:\r
667\r
668 EFI_SUCCESS - The FFS file was successfully loaded.\r
669\r
670 EFI_ERROR - Unable to load the FFS file.\r
671\r
672--*/\r
673{\r
674 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
675 EFI_STATUS Status;\r
676 VOID *Pe32Data;\r
677\r
678 Pe32Data = NULL;\r
679 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
680\r
681 //\r
682 // Preprocess the FFS file to get a pointer to the PE32 information\r
683 // in the enclosed PE32 image.\r
684 //\r
685 Status = PeiProcessFile (\r
686 EFI_SECTION_PE32,\r
6326ee4e 687 &FfsHeader,\r
878ddf1f 688 &Pe32Data\r
689 );\r
690\r
691 if (EFI_ERROR (Status)) {\r
692 return Status;\r
693 }\r
694 //\r
695 // Load the PE image from the FFS file\r
696 //\r
697 Status = PeiLoadFile (\r
698 PeiEfiPeiPeCoffLoader,\r
699 Pe32Data,\r
700 ImageAddress,\r
701 ImageSize,\r
702 EntryPoint\r
703 );\r
704\r
705 return Status;\r
706}\r
707\r
708EFI_STATUS\r
709PeiProcessFile (\r
6326ee4e
LG
710 IN UINT16 SectionType,\r
711 IN OUT EFI_FFS_FILE_HEADER **RealFfsFileHeader,\r
712 OUT VOID **Pe32Data\r
878ddf1f 713 )\r
714/*++\r
715\r
716Routine Description:\r
717\r
718Arguments:\r
719\r
720 SectionType - The type of section in the FFS file to process.\r
721\r
722 FfsFileHeader - Pointer to the FFS file to process, looking for the\r
723 specified SectionType\r
724\r
725 Pe32Data - returned pointer to the start of the PE32 image found\r
726 in the FFS file.\r
727\r
728Returns:\r
729\r
730 EFI_SUCCESS - found the PE32 section in the FFS file\r
731\r
732--*/\r
733{\r
734 EFI_STATUS Status;\r
735 VOID *SectionData;\r
736 DECOMPRESS_LIBRARY *DecompressLibrary;\r
737 UINT8 *DstBuffer;\r
738 UINT8 *ScratchBuffer;\r
739 UINT32 DstBufferSize;\r
740 UINT32 ScratchBufferSize;\r
741 EFI_COMMON_SECTION_HEADER *CmpSection;\r
742 UINTN CmpSectionLength;\r
743 UINTN OccupiedCmpSectionLength;\r
744 VOID *CmpFileData;\r
745 UINTN CmpFileSize;\r
746 EFI_COMMON_SECTION_HEADER *Section;\r
747 UINTN SectionLength;\r
748 UINTN OccupiedSectionLength;\r
749 UINT64 FileSize;\r
750 EFI_GUID_DEFINED_SECTION *GuidedSectionHeader;\r
751 UINT32 AuthenticationStatus;\r
752 EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract;\r
753 UINT32 BufferSize;\r
754 UINT8 *Buffer;\r
755 EFI_PEI_SECURITY_PPI *Security;\r
756 BOOLEAN StartCrisisRecovery;\r
757 EFI_GUID TempGuid;\r
758 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
759 EFI_COMPRESSION_SECTION *CompressionSection;\r
6326ee4e 760 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
eeb1cd5a 761\r
6326ee4e 762 FfsFileHeader = *RealFfsFileHeader;\r
878ddf1f 763\r
84a99d48 764 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 765 EFI_SECTION_COMPRESSION,\r
766 FfsFileHeader,\r
767 &SectionData\r
768 );\r
769\r
770 //\r
771 // Upon finding a DXE Core file, see if there is first a compression section\r
772 //\r
773 if (!EFI_ERROR (Status)) {\r
774 //\r
775 // Yes, there is a compression section, so extract the contents\r
776 // Decompress the image here\r
777 //\r
778 Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
779\r
780 do {\r
781 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
782 OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
783\r
784 //\r
785 // Was the DXE Core file encapsulated in a GUID'd section?\r
786 //\r
787 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
788 //\r
789 // Locate the GUID'd Section Extractor\r
790 //\r
791 GuidedSectionHeader = (VOID *) (Section + 1);\r
792\r
793 //\r
794 // This following code constitutes the addition of the security model\r
795 // to the DXE IPL.\r
796 //\r
797 //\r
798 // Set a default authenticatino state\r
799 //\r
800 AuthenticationStatus = 0;\r
801\r
84a99d48 802 Status = PeiServicesLocatePpi (\r
878ddf1f 803 &gEfiPeiSectionExtractionPpiGuid,\r
804 0,\r
805 NULL,\r
806 (VOID **)&SectionExtract\r
807 );\r
808\r
809 if (EFI_ERROR (Status)) {\r
810 return Status;\r
811 }\r
812 //\r
813 // Verify Authentication State\r
814 //\r
815 CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));\r
816\r
817 Status = SectionExtract->PeiGetSection (\r
818 GetPeiServicesTablePointer(),\r
819 SectionExtract,\r
820 (EFI_SECTION_TYPE *) &SectionType,\r
821 &TempGuid,\r
822 0,\r
823 (VOID **) &Buffer,\r
824 &BufferSize,\r
825 &AuthenticationStatus\r
826 );\r
827\r
828 if (EFI_ERROR (Status)) {\r
829 return Status;\r
830 }\r
831 //\r
832 // If not ask the Security PPI, if exists, for disposition\r
833 //\r
834 //\r
84a99d48 835 Status = PeiServicesLocatePpi (\r
878ddf1f 836 &gEfiPeiSecurityPpiGuid,\r
837 0,\r
838 NULL,\r
839 (VOID **)&Security\r
840 );\r
841 if (EFI_ERROR (Status)) {\r
842 return Status;\r
843 }\r
844\r
845 Status = Security->AuthenticationState (\r
846 GetPeiServicesTablePointer(),\r
847 (struct _EFI_PEI_SECURITY_PPI *) Security,\r
848 AuthenticationStatus,\r
849 FfsFileHeader,\r
850 &StartCrisisRecovery\r
851 );\r
852\r
853 if (EFI_ERROR (Status)) {\r
854 return Status;\r
855 }\r
856 //\r
857 // If there is a security violation, report to caller and have\r
858 // the upper-level logic possible engender a crisis recovery\r
859 //\r
860 if (StartCrisisRecovery) {\r
861 return EFI_SECURITY_VIOLATION;\r
862 }\r
863 }\r
864\r
865 if (Section->Type == EFI_SECTION_PE32) {\r
866 //\r
867 // This is what we want\r
868 //\r
869 *Pe32Data = (VOID *) (Section + 1);\r
870 return EFI_SUCCESS;\r
871 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
872 //\r
873 // This is a compression set, expand it\r
874 //\r
875 CompressionSection = (EFI_COMPRESSION_SECTION *) Section;\r
876\r
877 switch (CompressionSection->CompressionType) {\r
878 case EFI_STANDARD_COMPRESSION:\r
879 DecompressLibrary = &gTianoDecompress;\r
880 break;\r
881\r
882 case EFI_CUSTOMIZED_COMPRESSION:\r
883 //\r
884 // Load user customized compression protocol.\r
885 //\r
886 DecompressLibrary = &gCustomDecompress;\r
887 break;\r
888\r
889 case EFI_NOT_COMPRESSED:\r
890 default:\r
891 //\r
892 // Need to support not compressed file\r
893 //\r
894 ASSERT_EFI_ERROR (Status);\r
895 return EFI_NOT_FOUND;\r
896 }\r
897\r
898 Status = DecompressLibrary->GetInfo (\r
899 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
900 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
901 &DstBufferSize,\r
902 &ScratchBufferSize\r
903 );\r
904 if (EFI_ERROR (Status)) {\r
905 //\r
906 // GetInfo failed\r
907 //\r
908 return EFI_NOT_FOUND;\r
909 }\r
910\r
911 //\r
912 // Allocate scratch buffer\r
913 //\r
914 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
915 if (ScratchBuffer == NULL) {\r
916 return EFI_OUT_OF_RESOURCES;\r
917 }\r
918\r
919 //\r
920 // Allocate destination buffer\r
921 //\r
922 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
923 if (DstBuffer == NULL) {\r
924 return EFI_OUT_OF_RESOURCES;\r
925 }\r
926\r
927 //\r
928 // Call decompress function\r
929 //\r
930 Status = DecompressLibrary->Decompress (\r
931 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
932 DstBuffer,\r
933 ScratchBuffer\r
934 );\r
935\r
936 CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
937 if (CmpSection->Type == EFI_SECTION_RAW) {\r
938 //\r
939 // Skip the section header and\r
940 // adjust the pointer alignment to 16\r
941 //\r
942 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16);\r
943\r
944 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
945 FfsFileHeader = NULL;\r
946 BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
84a99d48 947 Status = PeiServicesFfsFindNextFile (\r
878ddf1f 948 EFI_FV_FILETYPE_DXE_CORE,\r
949 FvHeader,\r
950 &FfsFileHeader\r
951 );\r
952\r
953 if (EFI_ERROR (Status)) {\r
954 return EFI_NOT_FOUND;\r
955 }\r
956\r
6326ee4e
LG
957 //\r
958 // Reture the FfsHeader that contain Pe32Data.\r
959 //\r
960 *RealFfsFileHeader = FfsFileHeader;\r
961 return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data);\r
878ddf1f 962 }\r
963 }\r
964 //\r
965 // Decompress successfully.\r
966 // Loop the decompressed data searching for expected section.\r
967 //\r
968 CmpFileData = (VOID *) DstBuffer;\r
969 CmpFileSize = DstBufferSize;\r
970 do {\r
971 CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
972 if (CmpSection->Type == EFI_SECTION_PE32) {\r
973 //\r
974 // This is what we want\r
975 //\r
976 *Pe32Data = (VOID *) (CmpSection + 1);\r
977 return EFI_SUCCESS;\r
978 }\r
979\r
980 OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);\r
981 CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
982 } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
983 }\r
984\r
985 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
986 FileSize = FfsFileHeader->Size[0] & 0xFF;\r
987 FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
988 FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
989 FileSize &= 0x00FFFFFF;\r
990 } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
991\r
992 //\r
993 // End of the decompression activity\r
994 //\r
995 } else {\r
996\r
84a99d48 997 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 998 EFI_SECTION_PE32,\r
999 FfsFileHeader,\r
1000 &SectionData\r
1001 );\r
1002\r
1003 if (EFI_ERROR (Status)) {\r
84a99d48 1004 Status = PeiServicesFfsFindSectionData (\r
878ddf1f 1005 EFI_SECTION_TE,\r
1006 FfsFileHeader,\r
1007 &SectionData\r
1008 );\r
1009 if (EFI_ERROR (Status)) {\r
1010 return Status;\r
1011 }\r
1012 }\r
1013 }\r
1014\r
1015 *Pe32Data = SectionData;\r
1016\r
1017 return EFI_SUCCESS;\r
1018}\r