]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/DxeIplX64Peim/DxeLoadX64.c
Fix gcc warnings -- please review affected files.
[mirror_edk2.git] / EdkModulePkg / Core / DxeIplX64Peim / DxeLoadX64.c
CommitLineData
3005648d 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
0cc82df1 25#ifndef __GNUC__\r
3005648d 26#pragma warning( disable : 4305 )\r
0cc82df1 27#endif\r
3005648d 28\r
29BOOLEAN gInMemory = FALSE;\r
30\r
3005648d 31//\r
32// Module Globals used in the DXE to PEI handoff\r
33// These must be module globals, so the stack can be switched\r
34//\r
35static EFI_DXE_IPL_PPI mDxeIplPpi = {\r
36 DxeLoadCore\r
37};\r
38\r
39static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {\r
40 DxeIplLoadFile\r
41};\r
42\r
43static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = {\r
44 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
45 &gEfiPeiFvFileLoaderPpiGuid,\r
46 &mLoadFilePpi\r
47};\r
48\r
49static EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
50 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
51 &gEfiDxeIplPpiGuid,\r
52 &mDxeIplPpi\r
53};\r
54\r
55static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = {\r
56 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
57 &gPeiInMemoryGuid,\r
58 NULL\r
59};\r
60\r
61static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {\r
62 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
63 &gEfiEndOfPeiSignalPpiGuid,\r
64 NULL\r
65};\r
66\r
e29d7096 67GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gEfiDecompress = {\r
3005648d 68 UefiDecompressGetInfo,\r
69 UefiDecompress\r
70};\r
71\r
e29d7096 72GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gTianoDecompress = {\r
3005648d 73 TianoDecompressGetInfo,\r
74 TianoDecompress\r
75};\r
76\r
e29d7096 77GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY gCustomDecompress = {\r
3005648d 78 CustomDecompressGetInfo,\r
79 CustomDecompress\r
80};\r
81\r
82STATIC\r
83UINTN\r
84GetOccupiedSize (\r
85 IN UINTN ActualSize,\r
86 IN UINTN Alignment\r
87 )\r
88{\r
89 UINTN OccupiedSize;\r
90\r
91 OccupiedSize = ActualSize;\r
92 while ((OccupiedSize & (Alignment - 1)) != 0) {\r
93 OccupiedSize++;\r
94 }\r
95\r
96 return OccupiedSize;\r
97}\r
98\r
99EFI_STATUS\r
100EFIAPI\r
101PeimInitializeDxeIpl (\r
102 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
103 IN EFI_PEI_SERVICES **PeiServices\r
104 )\r
105/*++\r
106\r
107Routine Description:\r
108\r
109 Initializes the Dxe Ipl PPI\r
110\r
111Arguments:\r
112\r
113 FfsHeader - Pointer to FFS file header\r
114 PeiServices - General purpose services available to every PEIM.\r
115\r
116Returns:\r
117\r
118 EFI_SUCCESS\r
119\r
120--*/\r
121{\r
122 EFI_STATUS Status;\r
123 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
124 EFI_BOOT_MODE BootMode;\r
125\r
84a99d48 126 Status = PeiServicesGetBootMode (&BootMode);\r
3005648d 127\r
128 ASSERT_EFI_ERROR (Status);\r
129\r
84a99d48 130 Status = PeiServicesLocatePpi (\r
3005648d 131 &gPeiInMemoryGuid,\r
132 0,\r
133 NULL,\r
134 NULL\r
135 );\r
136\r
137 if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) { \r
138 //\r
139 // The DxeIpl has not yet been shadowed\r
140 //\r
141 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
142\r
143 //\r
144 // Shadow DxeIpl and then re-run its entry point\r
145 //\r
146 Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);\r
147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150\r
151 } else {\r
152 if (BootMode != BOOT_ON_S3_RESUME) {\r
153 //\r
154 // The DxeIpl has been shadowed\r
155 //\r
156 gInMemory = TRUE;\r
157\r
158 //\r
159 // Install LoadFile PPI\r
160 //\r
84a99d48 161 Status = PeiServicesInstallPpi (&mPpiLoadFile);\r
3005648d 162\r
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
166 }\r
167 //\r
168 // Install DxeIpl PPI\r
169 //\r
84a99d48 170 PeiServicesInstallPpi (&mPpiList);\r
3005648d 171\r
172 if (EFI_ERROR (Status)) {\r
173 return Status;\r
174 }\r
175\r
176 }\r
177\r
178 return EFI_SUCCESS;\r
179}\r
180\r
181EFI_STATUS\r
182EFIAPI\r
183DxeLoadCore (\r
184 IN EFI_DXE_IPL_PPI *This,\r
185 IN EFI_PEI_SERVICES **PeiServices,\r
186 IN EFI_PEI_HOB_POINTERS HobList\r
187 )\r
188/*++\r
189\r
190Routine Description:\r
191\r
192 Main entry point to last PEIM\r
193\r
194Arguments:\r
195\r
196 This - Entry point for DXE IPL PPI\r
197 PeiServices - General purpose services available to every PEIM.\r
198 HobList - Address to the Pei HOB list\r
199\r
200Returns:\r
201\r
202 EFI_SUCCESS - DEX core was successfully loaded.\r
203 EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core.\r
204\r
205--*/\r
206{\r
207 EFI_STATUS Status;\r
208 EFI_PHYSICAL_ADDRESS TopOfStack;\r
209 EFI_PHYSICAL_ADDRESS BaseOfStack;\r
210 EFI_PHYSICAL_ADDRESS BspStore;\r
211 EFI_GUID DxeCoreFileName;\r
d6697471 212 EFI_GUID FirmwareFileName;\r
3005648d 213 VOID *DxeCorePe32Data;\r
d6697471 214 VOID *FvImageData; \r
3005648d 215 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
216 UINT64 DxeCoreSize;\r
217 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
218 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
219 EFI_BOOT_MODE BootMode;\r
220 EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;\r
221 EFI_PEI_S3_RESUME_PPI *S3Resume;\r
222 EFI_PHYSICAL_ADDRESS PageTables;\r
223 \r
224 TopOfStack = 0;\r
225 BaseOfStack = 0;\r
226 BspStore = 0;\r
227 Status = EFI_SUCCESS;\r
228\r
229 //\r
230 // if in S3 Resume, restore configure\r
231 //\r
84a99d48 232 Status = PeiServicesGetBootMode (&BootMode);\r
3005648d 233\r
234 if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {\r
84a99d48 235 Status = PeiServicesLocatePpi (\r
3005648d 236 &gEfiPeiS3ResumePpiGuid,\r
237 0,\r
238 NULL,\r
239 (VOID **)&S3Resume\r
240 );\r
241\r
242 ASSERT_EFI_ERROR (Status);\r
243\r
244 Status = S3Resume->S3RestoreConfig (PeiServices);\r
245\r
246 ASSERT_EFI_ERROR (Status);\r
247 }\r
248\r
249 Status = EFI_SUCCESS;\r
250\r
251 //\r
252 // Install the PEI Protocols that are shared between PEI and DXE\r
253 //\r
fc198a79 254 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
a61513d6 255 ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
3005648d 256\r
3005648d 257 //\r
258 // Allocate 128KB for the Stack\r
259 //\r
84a99d48 260 PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
3005648d 261 ASSERT (BaseOfStack != 0);\r
262\r
263 //\r
3e025b69
LG
264 // Compute the top of the stack we were allocated, which is used to load X64 dxe core. \r
265 // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
3005648d 266 //\r
9723bdde
LG
267 // The first four parameters to a function are passed in rcx, rdx, r8 and r9. \r
268 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the \r
269 // register parameters is reserved on the stack, in case the called function \r
270 // wants to spill them; this is important if the function is variadic. \r
271 //\r
272 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
3005648d 273\r
3e025b69
LG
274 //\r
275 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
276 //\r
5ab95f33 277 TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);\r
3e025b69 278\r
3005648d 279 //\r
280 // Add architecture-specifc HOBs (including the BspStore HOB)\r
281 //\r
282 Status = CreateArchSpecificHobs (&BspStore);\r
283 ASSERT_EFI_ERROR (Status);\r
284\r
285 //\r
286 // See if we are in crisis recovery\r
287 //\r
84a99d48 288 Status = PeiServicesGetBootMode (&BootMode);\r
3005648d 289 if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {\r
84a99d48 290 Status = PeiServicesLocatePpi (\r
3005648d 291 &gEfiPeiRecoveryModulePpiGuid,\r
292 0,\r
293 NULL,\r
294 (VOID **)&PeiRecovery\r
295 );\r
296\r
297 ASSERT_EFI_ERROR (Status);\r
298 Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);\r
f78797d5
LG
299 if (EFI_ERROR (Status)) {\r
300 DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
301 CpuDeadLoop ();\r
302 }\r
3005648d 303 }\r
304\r
d6697471
LG
305 //\r
306 // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file\r
307 // The file found will be processed by PeiProcessFile: It will first be decompressed to\r
308 // a normal FV, then a corresponding FV type hob will be built. \r
309 //\r
310 Status = PeiFindFile (\r
311 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
312 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
313 &FirmwareFileName,\r
314 &FvImageData\r
315 );\r
316\r
3005648d 317 //\r
318 // Find the DXE Core in a Firmware Volume\r
319 //\r
320 Status = PeiFindFile (\r
321 EFI_FV_FILETYPE_DXE_CORE,\r
322 EFI_SECTION_PE32,\r
323 &DxeCoreFileName,\r
324 &DxeCorePe32Data\r
325 );\r
326 ASSERT_EFI_ERROR (Status);\r
327\r
3005648d 328 //\r
5ab95f33 329 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
3005648d 330 // memory, it may be corrupted when copying FV to high-end memory \r
5ab95f33 331 //\r
3005648d 332 LoadGo64Gdt();\r
333\r
334 //\r
335 // Limit to 36 bits of addressing for debug. Should get it from CPU\r
336 //\r
337 PageTables = CreateIdentityMappingPageTables (36);\r
338\r
339\r
340 //\r
341 // Load the DXE Core from a Firmware Volume\r
342 //\r
fc198a79 343 Status = PeiLoadPeImage (\r
3005648d 344 PeiEfiPeiPeCoffLoader,\r
345 DxeCorePe32Data,\r
346 EfiBootServicesData,\r
347 &DxeCoreAddress,\r
348 &DxeCoreSize,\r
349 &DxeCoreEntryPoint\r
350 );\r
351 ASSERT_EFI_ERROR (Status);\r
352\r
a61513d6
LG
353 //\r
354 // Transfer control to the DXE Core\r
355 // The handoff state is simply a pointer to the HOB list\r
356 //\r
357\r
358 Status = PeiServicesInstallPpi (&mPpiSignal);\r
359 ASSERT_EFI_ERROR (Status);\r
360\r
3005648d 361 //\r
362 //\r
363 // Add HOB for the DXE Core\r
364 //\r
365 BuildModuleHob (\r
366 &DxeCoreFileName,\r
367 DxeCoreAddress,\r
368 DxeCoreSize,\r
369 DxeCoreEntryPoint\r
370 );\r
371\r
372 //\r
373 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
374 //\r
375 REPORT_STATUS_CODE (\r
376 EFI_PROGRESS_CODE,\r
377 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT\r
378 );\r
379\r
380 DEBUG ((EFI_D_INFO, "DXE Core Entry\n"));\r
381 //\r
382 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.\r
383 // Call x64 drivers passing in single argument, a pointer to the HOBs.\r
384 //\r
385 ActivateLongMode (\r
386 PageTables, \r
387 (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), \r
388 TopOfStack,\r
389 0x00000000,\r
390 DxeCoreEntryPoint\r
391 );\r
392\r
393 //\r
394 // If we get here, then the DXE Core returned. This is an error\r
f78797d5 395 // Dxe Core should not return.\r
3005648d 396 //\r
f78797d5
LG
397 ASSERT (FALSE);\r
398 CpuDeadLoop ();\r
3005648d 399\r
400 return EFI_OUT_OF_RESOURCES;\r
401}\r
402\r
403EFI_STATUS\r
404PeiFindFile (\r
405 IN UINT8 Type,\r
406 IN UINT16 SectionType,\r
407 OUT EFI_GUID *FileName,\r
408 OUT VOID **Pe32Data\r
409 )\r
410/*++\r
411\r
412Routine Description:\r
413\r
414 Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes\r
415 described in the HOB list. Able to search in a compression set in a FFS file.\r
416 But only one level of compression is supported, that is, not able to search\r
417 in a compression set that is within another compression set.\r
418\r
419Arguments:\r
420\r
421 Type - The Type of file to retrieve\r
422\r
423 SectionType - The type of section to retrieve from a file\r
424\r
425 FileName - The name of the file found in the Firmware Volume\r
426\r
427 Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume\r
428\r
429Returns:\r
430\r
431 EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to\r
432 the PE/COFF image is returned in Pe32Data\r
433\r
434 EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List\r
435\r
436--*/\r
437{\r
438 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
439 EFI_FFS_FILE_HEADER *FfsFileHeader;\r
440 VOID *SectionData;\r
441 EFI_STATUS Status;\r
442 EFI_PEI_HOB_POINTERS Hob;\r
443\r
444\r
445 FwVolHeader = NULL;\r
446 FfsFileHeader = NULL;\r
447 SectionData = NULL;\r
d6697471 448 Status = EFI_SUCCESS;\r
3005648d 449\r
450 //\r
d6697471
LG
451 // For each Firmware Volume, look for a specified type\r
452 // of file and break out until no one is found \r
3005648d 453 //\r
454 Hob.Raw = GetHobList ();\r
455 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {\r
456 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress);\r
84a99d48 457 Status = PeiServicesFfsFindNextFile (\r
3005648d 458 Type,\r
459 FwVolHeader,\r
460 &FfsFileHeader\r
461 );\r
462 if (!EFI_ERROR (Status)) {\r
3005648d 463 Status = PeiProcessFile (\r
464 SectionType,\r
d6697471 465 FfsFileHeader,\r
2ea767cc 466 Pe32Data,\r
467 &Hob\r
3005648d 468 );\r
6326ee4e 469 CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
d6697471
LG
470 if (!EFI_ERROR (Status)) {\r
471 return EFI_SUCCESS;\r
472 }\r
3005648d 473 }\r
474 Hob.Raw = GET_NEXT_HOB (Hob);\r
475 }\r
476 return EFI_NOT_FOUND;\r
477}\r
478\r
479EFI_STATUS\r
fc198a79 480PeiLoadPeImage (\r
3005648d 481 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader,\r
482 IN VOID *Pe32Data,\r
483 IN EFI_MEMORY_TYPE MemoryType,\r
484 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
485 OUT UINT64 *ImageSize,\r
486 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
487 )\r
488/*++\r
489\r
490Routine Description:\r
491\r
492 Loads and relocates a PE/COFF image into memory.\r
493\r
494Arguments:\r
495\r
496 PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol\r
497\r
498 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
499\r
500 ImageAddress - The base address of the relocated PE/COFF image\r
501\r
502 ImageSize - The size of the relocated PE/COFF image\r
503\r
504 EntryPoint - The entry point of the relocated PE/COFF image\r
505\r
506Returns:\r
507\r
508 EFI_SUCCESS - The file was loaded and relocated\r
509 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
510\r
511--*/\r
512{\r
513 EFI_STATUS Status;\r
514 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
515 EFI_PHYSICAL_ADDRESS MemoryBuffer;\r
516\r
517 ZeroMem (&ImageContext, sizeof (ImageContext));\r
518 ImageContext.Handle = Pe32Data;\r
519 Status = GetImageReadFunction (&ImageContext);\r
520\r
521 ASSERT_EFI_ERROR (Status);\r
522\r
523 Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext);\r
524 if (EFI_ERROR (Status)) {\r
525 return Status;\r
526 }\r
527 //\r
528 // Allocate Memory for the image\r
529 //\r
530 //\r
531 // Allocate Memory for the image\r
532 //\r
84a99d48 533 PeiServicesAllocatePages (MemoryType, EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), &MemoryBuffer);\r
3005648d 534 ImageContext.ImageAddress = MemoryBuffer;\r
535 ASSERT (ImageContext.ImageAddress != 0);\r
536\r
537 //\r
538 // Load the image to our new buffer\r
539 //\r
540\r
541 Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext);\r
542 if (EFI_ERROR (Status)) {\r
543 return Status;\r
544 }\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 //\r
610 // Relocate DxeIpl into memory by using loadfile service\r
611 //\r
fc198a79 612 Status = PeiLoadPeImage (\r
3005648d 613 PeiEfiPeiPeCoffLoader,\r
614 (VOID *) (Section + 1),\r
615 EfiBootServicesData,\r
616 &DxeIplAddress,\r
617 &DxeIplSize,\r
618 &DxeIplEntryPoint\r
619 );\r
620 \r
621 if (Status == EFI_SUCCESS) {\r
622 //\r
623 // Install PeiInMemory to indicate the Dxeipl is shadowed\r
624 //\r
84a99d48 625 Status = PeiServicesInstallPpi (&mPpiPeiInMemory);\r
3005648d 626\r
627 if (EFI_ERROR (Status)) {\r
628 return Status;\r
629 }\r
630\r
631 Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());\r
632 }\r
633\r
634 return Status;\r
635}\r
636\r
637EFI_STATUS\r
638EFIAPI\r
639DxeIplLoadFile (\r
640 IN EFI_PEI_FV_FILE_LOADER_PPI *This,\r
641 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
642 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
643 OUT UINT64 *ImageSize,\r
644 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
645 )\r
646/*++\r
647\r
648Routine Description:\r
649\r
650 Given a pointer to an FFS file containing a PE32 image, get the\r
651 information on the PE32 image, and then "load" it so that it\r
652 can be executed.\r
653\r
654Arguments:\r
655\r
656 This - pointer to our file loader protocol\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 ImageAddress - returned address where the PE32 image is loaded\r
660 ImageSize - returned size of the loaded PE32 image\r
661 EntryPoint - entry point to the loaded PE32 image\r
662\r
663Returns:\r
664 \r
665 EFI_SUCCESS - The FFS file was successfully loaded.\r
666 EFI_ERROR - Unable to load the FFS file.\r
667\r
668--*/\r
669{\r
670 EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader;\r
671 EFI_STATUS Status;\r
672 VOID *Pe32Data;\r
673\r
674 Pe32Data = NULL;\r
675 PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
676\r
677 //\r
678 // Preprocess the FFS file to get a pointer to the PE32 information\r
679 // in the enclosed PE32 image.\r
680 //\r
681 Status = PeiProcessFile (\r
682 EFI_SECTION_PE32,\r
d6697471 683 FfsHeader,\r
2ea767cc 684 &Pe32Data,\r
685 NULL\r
3005648d 686 );\r
687\r
688 if (EFI_ERROR (Status)) {\r
689 return Status;\r
690 }\r
691 //\r
692 // Load the PE image from the FFS file\r
693 //\r
fc198a79 694 Status = PeiLoadPeImage (\r
3005648d 695 PeiEfiPeiPeCoffLoader,\r
696 Pe32Data,\r
697 EfiBootServicesData,\r
698 ImageAddress,\r
699 ImageSize,\r
700 EntryPoint\r
701 );\r
702\r
703 return Status;\r
704}\r
705\r
706EFI_STATUS\r
707PeiProcessFile (\r
6326ee4e 708 IN UINT16 SectionType,\r
d6697471 709 IN EFI_FFS_FILE_HEADER *FfsFileHeader,\r
2ea767cc 710 OUT VOID **Pe32Data,\r
711 IN EFI_PEI_HOB_POINTERS *OrigHob\r
3005648d 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
d6697471 759 UINT32 FvAlignment;\r
3005648d 760\r
84a99d48 761 Status = PeiServicesFfsFindSectionData (\r
3005648d 762 EFI_SECTION_COMPRESSION,\r
763 FfsFileHeader,\r
764 &SectionData\r
765 );\r
766\r
767 //\r
d6697471 768 // First process the compression section\r
3005648d 769 //\r
770 if (!EFI_ERROR (Status)) {\r
771 //\r
772 // Yes, there is a compression section, so extract the contents\r
773 // Decompress the image here\r
774 //\r
775 Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
776\r
777 do {\r
778 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
779 OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
780\r
781 //\r
782 // Was the DXE Core file encapsulated in a GUID'd section?\r
783 //\r
784 if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
785 //\r
786 // Locate the GUID'd Section Extractor\r
787 //\r
788 GuidedSectionHeader = (VOID *) (Section + 1);\r
789\r
790 //\r
791 // This following code constitutes the addition of the security model\r
792 // to the DXE IPL.\r
793 //\r
794 //\r
795 // Set a default authenticatino state\r
796 //\r
797 AuthenticationStatus = 0;\r
798\r
84a99d48 799 Status = PeiServicesLocatePpi (\r
3005648d 800 &gEfiPeiSectionExtractionPpiGuid,\r
801 0,\r
802 NULL,\r
803 (VOID **)&SectionExtract\r
804 );\r
805\r
806 if (EFI_ERROR (Status)) {\r
807 return Status;\r
808 }\r
809 //\r
810 // Verify Authentication State\r
811 //\r
812 CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));\r
813\r
814 Status = SectionExtract->PeiGetSection (\r
815 GetPeiServicesTablePointer(),\r
816 SectionExtract,\r
817 (EFI_SECTION_TYPE *) &SectionType,\r
818 &TempGuid,\r
819 0,\r
820 (VOID **) &Buffer,\r
821 &BufferSize,\r
822 &AuthenticationStatus\r
823 );\r
824\r
825 if (EFI_ERROR (Status)) {\r
826 return Status;\r
827 }\r
828 //\r
829 // If not ask the Security PPI, if exists, for disposition\r
830 //\r
831 //\r
84a99d48 832 Status = PeiServicesLocatePpi (\r
3005648d 833 &gEfiPeiSecurityPpiGuid,\r
834 0,\r
835 NULL,\r
836 (VOID **)&Security\r
837 );\r
838 if (EFI_ERROR (Status)) {\r
839 return Status;\r
840 }\r
841\r
842 Status = Security->AuthenticationState (\r
843 GetPeiServicesTablePointer(),\r
844 (struct _EFI_PEI_SECURITY_PPI *) Security,\r
845 AuthenticationStatus,\r
846 FfsFileHeader,\r
847 &StartCrisisRecovery\r
848 );\r
849\r
850 if (EFI_ERROR (Status)) {\r
851 return Status;\r
852 }\r
853 //\r
854 // If there is a security violation, report to caller and have\r
855 // the upper-level logic possible engender a crisis recovery\r
856 //\r
857 if (StartCrisisRecovery) {\r
858 return EFI_SECURITY_VIOLATION;\r
859 }\r
860 }\r
861\r
862 if (Section->Type == EFI_SECTION_PE32) {\r
863 //\r
864 // This is what we want\r
865 //\r
866 *Pe32Data = (VOID *) (Section + 1);\r
867 return EFI_SUCCESS;\r
868 } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
869 //\r
870 // This is a compression set, expand it\r
871 //\r
872 CompressionSection = (EFI_COMPRESSION_SECTION *) Section;\r
873\r
874 switch (CompressionSection->CompressionType) {\r
875 case EFI_STANDARD_COMPRESSION:\r
e29d7096 876 if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {\r
877 DecompressLibrary = &gTianoDecompress;\r
878 } else {\r
879 ASSERT (FALSE);\r
880 return EFI_NOT_FOUND;\r
881 }\r
3005648d 882 break;\r
883\r
884 case EFI_CUSTOMIZED_COMPRESSION:\r
885 //\r
886 // Load user customized compression protocol.\r
887 //\r
e29d7096 888 if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {\r
889 DecompressLibrary = &gCustomDecompress;\r
890 } else {\r
891 ASSERT (FALSE);\r
892 return EFI_NOT_FOUND;\r
893 }\r
3005648d 894 break;\r
895\r
896 case EFI_NOT_COMPRESSED:\r
897 default:\r
898 //\r
899 // Need to support not compressed file\r
900 //\r
901 ASSERT_EFI_ERROR (Status);\r
902 return EFI_NOT_FOUND;\r
903 }\r
904\r
905 Status = DecompressLibrary->GetInfo (\r
906 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
907 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
908 &DstBufferSize,\r
909 &ScratchBufferSize\r
910 );\r
911 if (EFI_ERROR (Status)) {\r
912 //\r
913 // GetInfo failed\r
914 //\r
915 return EFI_NOT_FOUND;\r
916 }\r
917\r
918 //\r
919 // Allocate scratch buffer\r
920 //\r
921 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
922 if (ScratchBuffer == NULL) {\r
923 return EFI_OUT_OF_RESOURCES;\r
924 }\r
925\r
926 //\r
927 // Allocate destination buffer\r
928 //\r
929 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
930 if (DstBuffer == NULL) {\r
931 return EFI_OUT_OF_RESOURCES;\r
932 }\r
933\r
934 //\r
935 // Call decompress function\r
936 //\r
937 Status = DecompressLibrary->Decompress (\r
938 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
939 DstBuffer,\r
940 ScratchBuffer\r
941 );\r
942\r
943 CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
d6697471
LG
944 if (CmpSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
945 // \r
946 // Firmware Volume Image in this Section\r
947 // Skip the section header to get FvHeader\r
3005648d 948 //\r
d6697471 949 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
3005648d 950\r
d6697471
LG
951 if (FvHeader->Signature == EFI_FVH_SIGNATURE) { \r
952 //\r
953 // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header\r
954 //\r
955 \r
956 //\r
957 // When FvImage support Alignment, we need to check whether \r
958 // its alignment is correct. \r
959 //\r
960 if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {\r
961 \r
962 //\r
963 // Calculate the mini alignment for this FvImage\r
964 //\r
965 FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1);\r
966 \r
967 //\r
968 // If current FvImage base address doesn't meet the its alignment,\r
969 // we need to reload this FvImage to another correct memory address.\r
970 //\r
971 if (((UINTN) FvHeader % FvAlignment) != 0) {\r
972 DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment);\r
973 if (DstBuffer == NULL) {\r
974 return EFI_OUT_OF_RESOURCES;\r
975 }\r
976 CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength);\r
977 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer; \r
978 }\r
3005648d 979 }\r
d6697471
LG
980 //\r
981 // Build new FvHob for new decompressed Fv image.\r
982 //\r
983 BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
984 \r
985 //\r
986 // Set the original FvHob to unused.\r
987 //\r
2ea767cc 988 if (OrigHob != NULL) {\r
2ea767cc 989 OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;\r
990 }\r
991 \r
6326ee4e 992 //\r
d6697471 993 // when search FvImage Section return true.\r
6326ee4e 994 //\r
d6697471
LG
995 if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
996 *Pe32Data = (VOID *) FvHeader;\r
997 return EFI_SUCCESS;\r
998 } else {\r
999 return EFI_NOT_FOUND;\r
1000 }\r
1001\r
3005648d 1002 }\r
1003 }\r
1004 //\r
1005 // Decompress successfully.\r
1006 // Loop the decompressed data searching for expected section.\r
1007 //\r
1008 CmpFileData = (VOID *) DstBuffer;\r
1009 CmpFileSize = DstBufferSize;\r
1010 do {\r
1011 CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
1012 if (CmpSection->Type == EFI_SECTION_PE32) {\r
1013 //\r
1014 // This is what we want\r
1015 //\r
1016 *Pe32Data = (VOID *) (CmpSection + 1);\r
1017 return EFI_SUCCESS;\r
1018 }\r
1019\r
1020 OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4);\r
1021 CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
1022 } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
1023 }\r
d6697471
LG
1024 //\r
1025 // End of the decompression activity\r
1026 //\r
3005648d 1027\r
1028 Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
1029 FileSize = FfsFileHeader->Size[0] & 0xFF;\r
1030 FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
1031 FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
1032 FileSize &= 0x00FFFFFF;\r
1033 } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
d6697471 1034 \r
3005648d 1035 //\r
d6697471
LG
1036 // search all sections (compression and non compression) in this FFS, don't \r
1037 // find expected section.\r
3005648d 1038 //\r
d6697471 1039 return EFI_NOT_FOUND;\r
3005648d 1040 } else {\r
d6697471
LG
1041 //\r
1042 // For those FFS that doesn't contain compression section, directly search \r
1043 // PE or TE section in this FFS.\r
1044 //\r
3005648d 1045\r
84a99d48 1046 Status = PeiServicesFfsFindSectionData (\r
3005648d 1047 EFI_SECTION_PE32,\r
1048 FfsFileHeader,\r
1049 &SectionData\r
1050 );\r
1051\r
1052 if (EFI_ERROR (Status)) {\r
84a99d48 1053 Status = PeiServicesFfsFindSectionData (\r
3005648d 1054 EFI_SECTION_TE,\r
1055 FfsFileHeader,\r
1056 &SectionData\r
1057 );\r
1058 if (EFI_ERROR (Status)) {\r
1059 return Status;\r
1060 }\r
1061 }\r
1062 }\r
1063\r
1064 *Pe32Data = SectionData;\r
1065\r
1066 return EFI_SUCCESS;\r
5ab95f33
LG
1067}\r
1068\r