]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Dxe/Image/Image.c
1. Bug fix for "EDK GenericBds WriteBootToOsPerformanceData() uses AcpiReclaimMemory";
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / Image / Image.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Image.c\r
15\r
16Abstract:\r
17\r
18 Core image handling services\r
19\r
20--*/\r
21\r
22#include <DxeMain.h>\r
23//\r
24// Module Globals\r
25//\r
26\r
27//\r
28// LIST of runtime images that need to be relocated.\r
29//\r
30LIST_ENTRY mRuntimeImageList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeImageList);\r
31\r
32LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;\r
33\r
34LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {\r
35 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,\r
36 NULL,\r
37 {\r
38 CoreLoadImageEx,\r
39 CoreUnloadImageEx\r
40 }\r
41};\r
42\r
43\r
44//\r
45// This code is needed to build the Image handle for the DXE Core\r
46//\r
47LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {\r
48 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature\r
49 NULL, // Image handle\r
50 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type\r
51 TRUE, // If entrypoint has been called\r
52 NULL, // EntryPoint\r
53 {\r
54 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision\r
55 NULL, // Parent handle\r
56 NULL, // System handle\r
57\r
58 NULL, // Device handle\r
59 NULL, // File path\r
60 NULL, // Reserved\r
61\r
62 0, // LoadOptionsSize\r
63 NULL, // LoadOptions\r
64\r
65 NULL, // ImageBase\r
66 0, // ImageSize\r
67 EfiBootServicesCode, // ImageCodeType\r
68 EfiBootServicesData // ImageDataType\r
69 },\r
70 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage\r
71 0, // NumberOfPages\r
72 NULL, // FixupData\r
73 0, // Tpl\r
74 EFI_SUCCESS, // Status\r
75 0, // ExitDataSize\r
76 NULL, // ExitData\r
77 NULL, // JumpContext\r
78 0, // Machine\r
79 NULL, // Ebc\r
80 FALSE, // RuntimeFixupValid\r
81 NULL, // RuntimeFixup\r
82 { NULL, NULL }, // Link\r
83};\r
84\r
85\r
86EFI_STATUS\r
87CoreInitializeImageServices (\r
88 IN VOID *HobStart\r
89 )\r
90/*++\r
91\r
92Routine Description:\r
93\r
94 Add the Image Services to EFI Boot Services Table and install the protocol\r
95 interfaces for this image.\r
96\r
97Arguments:\r
98\r
99 HobStart - The HOB to initialize\r
100\r
101Returns:\r
102\r
103 Status code.\r
104\r
105--*/\r
106{\r
107 EFI_STATUS Status;\r
108 LOADED_IMAGE_PRIVATE_DATA *Image;\r
109 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;\r
110 UINT64 DxeCoreImageLength;\r
111 VOID *DxeCoreEntryPoint;\r
112 EFI_PEI_HOB_POINTERS DxeCoreHob;\r
113 //\r
114 // Searching for image hob\r
115 //\r
116 DxeCoreHob.Raw = HobStart;\r
117 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {\r
118 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {\r
119 //\r
120 // Find Dxe Core HOB\r
121 //\r
122 break;\r
123 }\r
124 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);\r
125 }\r
126 ASSERT (DxeCoreHob.Raw != NULL);\r
127\r
128 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;\r
129 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
130 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
131 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
132 //\r
133 // Initialize the fields for an internal driver\r
134 //\r
135 Image = &mCorePrivateImage;\r
136\r
137 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;\r
138 Image->ImageBasePage = DxeCoreImageBaseAddress;\r
139 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));\r
140 Image->Tpl = gEfiCurrentTpl;\r
141 Image->Info.SystemTable = gST;\r
142 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;\r
143 Image->Info.ImageSize = DxeCoreImageLength;\r
144\r
145 //\r
146 // Install the protocol interfaces for this image\r
147 //\r
148 Status = CoreInstallProtocolInterface (\r
149 &Image->Handle,\r
150 &gEfiLoadedImageProtocolGuid,\r
151 EFI_NATIVE_INTERFACE,\r
152 &Image->Info\r
153 );\r
154 ASSERT_EFI_ERROR (Status);\r
155\r
156 mCurrentImage = Image;\r
157\r
158 //\r
159 // Fill in DXE globals\r
160 //\r
161 gDxeCoreImageHandle = Image->Handle;\r
162 gDxeCoreLoadedImage = &Image->Info;\r
163\r
164 //\r
165 // Export DXE Core PE Loader functionality\r
166 //\r
167 return CoreInstallProtocolInterface (\r
168 &mLoadPe32PrivateData.Handle,\r
169 &gEfiLoadPeImageProtocolGuid,\r
170 EFI_NATIVE_INTERFACE,\r
171 &mLoadPe32PrivateData.Pe32Image\r
172 );\r
173}\r
174\r
175\r
176EFI_STATUS\r
177CoreShutdownImageServices (\r
178 VOID\r
179 )\r
180/*++\r
181\r
182Routine Description:\r
183\r
184 Transfer control of runtime images to runtime service\r
185\r
186Arguments:\r
187\r
188 None\r
189\r
190Returns:\r
191\r
192 EFI_SUCCESS - Function successfully returned\r
193\r
194--*/\r
195{\r
196 LIST_ENTRY *Link;\r
197 LOADED_IMAGE_PRIVATE_DATA *Image;\r
198\r
199 //\r
200 // The Runtime AP is required for the core to function!\r
201 //\r
202 ASSERT (gRuntime != NULL);\r
203\r
204 for (Link = mRuntimeImageList.ForwardLink; Link != &mRuntimeImageList; Link = Link->ForwardLink) {\r
205 Image = CR (Link, LOADED_IMAGE_PRIVATE_DATA, Link, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE);\r
206 if (Image->RuntimeFixupValid) {\r
207 gRuntime->RegisterImage (\r
208 gRuntime,\r
209 (UINT64)(UINTN)(Image->Info.ImageBase),\r
210 (EFI_SIZE_TO_PAGES ((UINTN)Image->Info.ImageSize)),\r
211 Image->RuntimeFixup\r
212 );\r
213 }\r
214 }\r
215\r
216 return EFI_SUCCESS;\r
217}\r
218\r
219\r
220\r
221EFI_STATUS\r
222CoreLoadPeImage (\r
223 IN VOID *Pe32Handle,\r
224 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
225 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
226 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
227 IN UINT32 Attribute\r
228 )\r
229/*++\r
230\r
231Routine Description:\r
232\r
233 Loads, relocates, and invokes a PE/COFF image\r
234\r
235Arguments:\r
236\r
237 Pe32Handle - The handle of PE32 image\r
238 Image - PE image to be loaded\r
239 DstBuffer - The buffer to store the image\r
240 EntryPoint - A pointer to the entry point\r
241 Attribute - The bit mask of attributes to set for the load PE image\r
242\r
243Returns:\r
244\r
245 EFI_SUCCESS - The file was loaded, relocated, and invoked\r
246\r
247 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file\r
248\r
249 EFI_INVALID_PARAMETER - Invalid parameter\r
250\r
251 EFI_BUFFER_TOO_SMALL - Buffer for image is too small\r
252\r
253--*/\r
254{\r
255 EFI_STATUS Status;\r
256 UINTN Size;\r
257\r
258 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
259\r
260 Image->ImageContext.Handle = Pe32Handle;\r
261 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;\r
262\r
263 //\r
264 // Get information about the image being loaded\r
265 //\r
266 Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
267 if (EFI_ERROR (Status)) {\r
268 return Status;\r
269 }\r
270\r
2ce31132 271 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
272 //\r
273 // The PE/COFF loader can support loading image types that can be executed. \r
274 // If we loaded an image type that we can not execute return EFI_UNSUPORTED. \r
275 //\r
276 return EFI_UNSUPPORTED;\r
277 }\r
278\r
279\r
878ddf1f 280 //\r
281 // Allocate memory of the correct memory type aligned on the required image boundry\r
282 //\r
283\r
284 if (DstBuffer == 0) {\r
285 //\r
286 // Allocate Destination Buffer as caller did not pass it in\r
287 //\r
288\r
289 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
290 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
291 } else {\r
292 Size = (UINTN)Image->ImageContext.ImageSize;\r
293 }\r
294\r
295 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
296\r
297 //\r
298 // If the image relocations have not been stripped, then load at any address.\r
299 // Otherwise load at the address at which it was linked.\r
300 //\r
301 Status = CoreAllocatePages (\r
302 (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages,\r
303 Image->ImageContext.ImageCodeMemoryType,\r
304 Image->NumberOfPages,\r
305 &Image->ImageContext.ImageAddress\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 return Status;\r
309 }\r
310\r
311 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
312\r
313 } else {\r
314 //\r
315 // Caller provided the destination buffer\r
316 //\r
317\r
318 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
319 //\r
320 // If the image relocations were stripped, and the caller provided a\r
321 // destination buffer address that does not match the address that the\r
322 // image is linked at, then the image cannot be loaded.\r
323 //\r
324 return EFI_INVALID_PARAMETER;\r
325 }\r
326\r
327 if (Image->NumberOfPages != 0 &&\r
328 Image->NumberOfPages <\r
329 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
330 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
331 return EFI_BUFFER_TOO_SMALL;\r
332 }\r
333\r
334 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
335 Image->ImageContext.ImageAddress = DstBuffer;\r
336 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
337 }\r
338\r
339 Image->ImageContext.ImageAddress =\r
340 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
341 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
342\r
343 //\r
344 // Load the image from the file into the allocated memory\r
345 //\r
346 Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
347 if (EFI_ERROR (Status)) {\r
348 return Status;\r
349 }\r
350\r
351 //\r
352 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
353 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
354 // relocation is done by the Runtime AP.\r
355 //\r
356 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
357 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
358 Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
359 if (Image->ImageContext.FixupData == NULL) {\r
360 Status = EFI_OUT_OF_RESOURCES;\r
361 goto Done;\r
362 }\r
363\r
364 //\r
365 // Make a list off all the RT images so we can let the RT AP know about them\r
366 //\r
367 Image->RuntimeFixupValid = TRUE;\r
368 Image->RuntimeFixup = Image->ImageContext.FixupData;\r
369 InsertTailList (&mRuntimeImageList, &Image->Link);\r
370 }\r
371 }\r
372\r
373 //\r
374 // Relocate the image in memory\r
375 //\r
376 Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
377 if (EFI_ERROR (Status)) {\r
378 return Status;\r
379 }\r
380\r
381 //\r
382 // Flush the Instruction Cache\r
383 //\r
384 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
385\r
386 //\r
387 // Copy the machine type from the context to the image private data. This\r
388 // is needed during image unload to know if we should call an EBC protocol\r
389 // to unload the image.\r
390 //\r
391 Image->Machine = Image->ImageContext.Machine;\r
392\r
393 //\r
394 // Get the image entry point. If it's an EBC image, then call into the\r
395 // interpreter to create a thunk for the entry point and use the returned\r
396 // value for the entry point.\r
397 //\r
398 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
399 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
400 //\r
401 // Locate the EBC interpreter protocol\r
402 //\r
403 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
404 if (EFI_ERROR(Status)) {\r
405 goto Done;\r
406 }\r
407\r
408 //\r
409 // Register a callback for flushing the instruction cache so that created\r
410 // thunks can be flushed.\r
411 //\r
412 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
413 if (EFI_ERROR(Status)) {\r
414 goto Done;\r
415 }\r
416\r
417 //\r
418 // Create a thunk for the image's entry point. This will be the new\r
419 // entry point for the image.\r
420 //\r
421 Status = Image->Ebc->CreateThunk (\r
422 Image->Ebc,\r
423 Image->Handle,\r
424 (VOID *)(UINTN)Image->ImageContext.EntryPoint,\r
425 (VOID **)&Image->EntryPoint\r
426 );\r
427 if (EFI_ERROR(Status)) {\r
428 goto Done;\r
429 }\r
430 }\r
431\r
432 //\r
433 // Fill in the image information for the Loaded Image Protocol\r
434 //\r
435 Image->Type = Image->ImageContext.ImageType;\r
436 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
437 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
438 Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;\r
439 Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;\r
440\r
441 //\r
442 // Fill in the entry point of the image if it is available\r
443 //\r
444 if (EntryPoint != NULL) {\r
445 *EntryPoint = Image->ImageContext.EntryPoint;\r
446 }\r
447\r
448 //\r
449 // Print the load address and the PDB file name if it is available\r
450 //\r
451\r
2ce31132 452 DEBUG_CODE_BEGIN ();\r
453 \r
878ddf1f 454 UINTN Index;\r
455 UINTN StartIndex;\r
456 CHAR8 EfiFileName[256];\r
457\r
458 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint));\r
459 if (Image->ImageContext.PdbPointer != NULL) {\r
460 StartIndex = 0;\r
461 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
462 if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
463 StartIndex = Index + 1;\r
464 }\r
465 }\r
466 //\r
467 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
468 //\r
469 for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
470 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
471 if (EfiFileName[Index] == 0) {\r
472 EfiFileName[Index] = '.';\r
473 }\r
474 if (EfiFileName[Index] == '.') {\r
475 EfiFileName[Index + 1] = 'e';\r
476 EfiFileName[Index + 2] = 'f';\r
477 EfiFileName[Index + 3] = 'i';\r
478 EfiFileName[Index + 4] = 0;\r
479 break;\r
480 }\r
481 }\r
482 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
483 }\r
484 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
2ce31132 485 \r
486 DEBUG_CODE_END ();\r
878ddf1f 487\r
488 return EFI_SUCCESS;\r
489\r
490Done:\r
491 //\r
492 // Free memory\r
493 //\r
494 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
495 return Status;\r
496}\r
497\r
498\r
499LOADED_IMAGE_PRIVATE_DATA *\r
500CoreLoadedImageInfo (\r
501 IN EFI_HANDLE ImageHandle\r
502 )\r
503/*++\r
504\r
505Routine Description:\r
506\r
507 Get the image's private data from its handle.\r
508\r
509Arguments:\r
510\r
511 ImageHandle - The image handle\r
512\r
513Returns:\r
514\r
515 Return the image private data associated with ImageHandle.\r
516\r
517--*/\r
518{\r
519 EFI_STATUS Status;\r
520 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
521 LOADED_IMAGE_PRIVATE_DATA *Image;\r
522\r
523 Status = CoreHandleProtocol (\r
524 ImageHandle,\r
525 &gEfiLoadedImageProtocolGuid,\r
526 (VOID **)&LoadedImage\r
527 );\r
528 if (!EFI_ERROR (Status)) {\r
529 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
530 } else {\r
531 DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));\r
532 Image = NULL;\r
533 }\r
534\r
535 return Image;\r
536}\r
537\r
538\r
539EFI_STATUS\r
540CoreLoadImageCommon (\r
541 IN BOOLEAN BootPolicy,\r
542 IN EFI_HANDLE ParentImageHandle,\r
543 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
544 IN VOID *SourceBuffer OPTIONAL,\r
545 IN UINTN SourceSize,\r
546 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
547 IN OUT UINTN *NumberOfPages OPTIONAL,\r
548 OUT EFI_HANDLE *ImageHandle,\r
549 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
550 IN UINT32 Attribute\r
551 )\r
552/*++\r
553\r
554Routine Description:\r
555\r
556 Loads an EFI image into memory and returns a handle to the image.\r
557\r
558Arguments:\r
559\r
560 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
561 and that the boot manager is attempting to load FilePath as a boot selection.\r
562 ParentImageHandle - The caller's image handle.\r
563 FilePath - The specific file path from which the image is loaded.\r
564 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
565 the image to be loaded.\r
566 SourceSize - The size in bytes of SourceBuffer.\r
567 DstBuffer - The buffer to store the image\r
568 NumberOfPages - If not NULL, a pointer to the image's page number, if this number\r
569 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain\r
570 the required number.\r
571 ImageHandle - Pointer to the returned image handle that is created when the image\r
572 is successfully loaded.\r
573 EntryPoint - A pointer to the entry point\r
574 Attribute - The bit mask of attributes to set for the load PE image\r
575\r
576Returns:\r
577\r
578 EFI_SUCCESS - The image was loaded into memory.\r
579 EFI_NOT_FOUND - The FilePath was not found.\r
580 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
581 EFI_BUFFER_TOO_SMALL - The buffer is too small\r
582 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
583 parsed to locate the proper protocol for loading the file.\r
584 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
585--*/\r
586{\r
587 LOADED_IMAGE_PRIVATE_DATA *Image;\r
588 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
589 IMAGE_FILE_HANDLE FHand;\r
590 EFI_STATUS Status;\r
591 EFI_STATUS SecurityStatus;\r
592 EFI_HANDLE DeviceHandle;\r
593 UINT32 AuthenticationStatus;\r
594 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
595 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
596 UINTN FilePathSize;\r
597\r
598\r
599 ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);\r
600 ParentImage = NULL;\r
601\r
602 //\r
603 // The caller must pass in a valid ParentImageHandle\r
604 //\r
605 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
606 return EFI_INVALID_PARAMETER;\r
607 }\r
608\r
609 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
610 if (ParentImage == NULL) {\r
611 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 //\r
616 // Get simple read access to the source file\r
617 //\r
618 OriginalFilePath = FilePath;\r
619 Status = CoreOpenImageFile (\r
620 BootPolicy,\r
621 SourceBuffer,\r
622 SourceSize,\r
623 FilePath,\r
624 &DeviceHandle,\r
625 &FHand,\r
626 &AuthenticationStatus\r
627 );\r
628 if (Status == EFI_ALREADY_STARTED) {\r
629 Image = NULL;\r
630 goto Done;\r
631 } else if (EFI_ERROR (Status)) {\r
632 return Status;\r
633 }\r
634\r
635 //\r
636 // Verify the Authentication Status through the Security Architectural Protocol\r
637 //\r
638 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
639 SecurityStatus = gSecurity->FileAuthenticationState (\r
640 gSecurity,\r
641 AuthenticationStatus,\r
642 OriginalFilePath\r
643 );\r
644 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
645 Status = SecurityStatus;\r
646 Image = NULL;\r
647 goto Done;\r
648 }\r
649 }\r
650\r
651\r
652 //\r
653 // Allocate a new image structure\r
654 //\r
655 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
656 if (Image == NULL) {\r
657 return EFI_OUT_OF_RESOURCES;\r
658 }\r
659\r
660 //\r
661 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
662 //\r
663 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
664 if (!EFI_ERROR (Status)) {\r
665 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
666 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );\r
667 }\r
668\r
669 //\r
670 // Initialize the fields for an internal driver\r
671 //\r
672 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
673 Image->Info.SystemTable = gST;\r
674 Image->Info.DeviceHandle = DeviceHandle;\r
675 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
676 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);\r
677 Image->Info.ParentHandle = ParentImageHandle;\r
678\r
679 if (NumberOfPages != NULL) {\r
680 Image->NumberOfPages = *NumberOfPages ;\r
681 } else {\r
682 Image->NumberOfPages = 0 ;\r
683 }\r
684\r
685 //\r
686 // Install the protocol interfaces for this image\r
687 // don't fire notifications yet\r
688 //\r
689 Status = CoreInstallProtocolInterfaceNotify (\r
690 &Image->Handle,\r
691 &gEfiLoadedImageProtocolGuid,\r
692 EFI_NATIVE_INTERFACE,\r
693 &Image->Info,\r
694 FALSE\r
695 );\r
696 if (EFI_ERROR (Status)) {\r
697 goto Done;\r
698 }\r
699\r
700 //\r
701 // Load the image. If EntryPoint is Null, it will not be set.\r
702 //\r
703 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);\r
704 if (EFI_ERROR (Status)) {\r
705 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
706 if (NumberOfPages != NULL) {\r
707 *NumberOfPages = Image->NumberOfPages;\r
708 }\r
709 }\r
710 goto Done;\r
711 }\r
712\r
713 //\r
714 // Register the image in the Debug Image Info Table if the attribute is set\r
715 //\r
716 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
717 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
718 }\r
719\r
720 //\r
721 //Reinstall loaded image protocol to fire any notifications\r
722 //\r
723 Status = CoreReinstallProtocolInterface (\r
724 Image->Handle,\r
725 &gEfiLoadedImageProtocolGuid,\r
726 &Image->Info,\r
727 &Image->Info\r
728 );\r
729 if (EFI_ERROR (Status)) {\r
730 goto Done;\r
731 }\r
732\r
733\r
734 //\r
735 // Success. Return the image handle\r
736 //\r
737 *ImageHandle = Image->Handle;\r
738\r
739Done:\r
740 //\r
741 // All done accessing the source file\r
742 // If we allocated the Source buffer, free it\r
743 //\r
744 if (FHand.FreeBuffer) {\r
745 CoreFreePool (FHand.Source);\r
746 }\r
747\r
748 //\r
749 // There was an error. If there's an Image structure, free it\r
750 //\r
751 if (EFI_ERROR (Status)) {\r
752 if (Image != NULL) {\r
753 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
754 *ImageHandle = NULL;\r
755 }\r
756 }\r
757\r
758 return Status;\r
759}\r
760\r
761\r
762\r
763EFI_STATUS\r
764EFIAPI\r
765CoreLoadImage (\r
766 IN BOOLEAN BootPolicy,\r
767 IN EFI_HANDLE ParentImageHandle,\r
768 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
769 IN VOID *SourceBuffer OPTIONAL,\r
770 IN UINTN SourceSize,\r
771 OUT EFI_HANDLE *ImageHandle\r
772 )\r
773/*++\r
774\r
775Routine Description:\r
776\r
777 Loads an EFI image into memory and returns a handle to the image.\r
778\r
779Arguments:\r
780\r
781 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
782 and that the boot manager is attempting to load FilePath as a boot selection.\r
783 ParentImageHandle - The caller's image handle.\r
784 FilePath - The specific file path from which the image is loaded.\r
785 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
786 the image to be loaded.\r
787 SourceSize - The size in bytes of SourceBuffer.\r
788 ImageHandle - Pointer to the returned image handle that is created when the image\r
789 is successfully loaded.\r
790\r
791Returns:\r
792\r
793 EFI_SUCCESS - The image was loaded into memory.\r
794 EFI_NOT_FOUND - The FilePath was not found.\r
795 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
796 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
797 parsed to locate the proper protocol for loading the file.\r
798 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
799--*/\r
800{\r
801 EFI_STATUS Status;\r
802\r
803 PERF_START (NULL, "LoadImage", NULL, 0);\r
804\r
805 Status = CoreLoadImageCommon (\r
806 BootPolicy,\r
807 ParentImageHandle,\r
808 FilePath,\r
809 SourceBuffer,\r
810 SourceSize,\r
811 (EFI_PHYSICAL_ADDRESS)NULL,\r
812 NULL,\r
813 ImageHandle,\r
814 NULL,\r
815 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
816 );\r
817\r
818 PERF_END (NULL, "LoadImage", NULL, 0);\r
819\r
820 return Status;\r
821}\r
822\r
823\r
824EFI_STATUS\r
825EFIAPI\r
826CoreLoadImageEx (\r
827 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
828 IN EFI_HANDLE ParentImageHandle,\r
829 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
830 IN VOID *SourceBuffer OPTIONAL,\r
831 IN UINTN SourceSize,\r
832 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
833 OUT UINTN *NumberOfPages OPTIONAL,\r
834 OUT EFI_HANDLE *ImageHandle,\r
835 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
836 IN UINT32 Attribute\r
837 )\r
838/*++\r
839\r
840Routine Description:\r
841\r
842 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
843\r
844Arguments:\r
845\r
846 This - Calling context\r
847 ParentImageHandle - The caller's image handle.\r
848 FilePath - The specific file path from which the image is loaded.\r
849 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
850 the image to be loaded.\r
851 SourceSize - The size in bytes of SourceBuffer.\r
852 DstBuffer - The buffer to store the image.\r
853 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.\r
854 For output, specifies the actual space size needed.\r
855 ImageHandle - Image handle for output.\r
856 EntryPoint - Image entry point for output.\r
857 Attribute - The bit mask of attributes to set for the load PE image.\r
858\r
859Returns:\r
860\r
861 EFI_SUCCESS - The image was loaded into memory.\r
862 EFI_NOT_FOUND - The FilePath was not found.\r
863 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
864 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
865 parsed to locate the proper protocol for loading the file.\r
866 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
867--*/\r
868{\r
869 return CoreLoadImageCommon (\r
870 TRUE,\r
871 ParentImageHandle,\r
872 FilePath,\r
873 SourceBuffer,\r
874 SourceSize,\r
875 DstBuffer,\r
876 NumberOfPages,\r
877 ImageHandle,\r
878 EntryPoint,\r
879 Attribute\r
880 );\r
881}\r
882\r
883\r
884\r
885\r
886EFI_STATUS\r
887EFIAPI\r
888CoreStartImage (\r
889 IN EFI_HANDLE ImageHandle,\r
890 OUT UINTN *ExitDataSize,\r
891 OUT CHAR16 **ExitData OPTIONAL\r
892 )\r
893/*++\r
894\r
895Routine Description:\r
896\r
897 Transfer control to a loaded image's entry point.\r
898\r
899Arguments:\r
900\r
901 ImageHandle - Handle of image to be started.\r
902\r
903 ExitDataSize - Pointer of the size to ExitData\r
904\r
905 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated\r
906 Unicode string, optionally followed by additional binary data. The string\r
907 is a description that the caller may use to further indicate the reason for\r
908