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