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