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