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