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