Initial import.
[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
271 //\r
272 // Allocate memory of the correct memory type aligned on the required image boundry\r
273 //\r
274\r
275 if (DstBuffer == 0) {\r
276 //\r
277 // Allocate Destination Buffer as caller did not pass it in\r
278 //\r
279\r
280 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
281 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
282 } else {\r
283 Size = (UINTN)Image->ImageContext.ImageSize;\r
284 }\r
285\r
286 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
287\r
288 //\r
289 // If the image relocations have not been stripped, then load at any address.\r
290 // Otherwise load at the address at which it was linked.\r
291 //\r
292 Status = CoreAllocatePages (\r
293 (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages,\r
294 Image->ImageContext.ImageCodeMemoryType,\r
295 Image->NumberOfPages,\r
296 &Image->ImageContext.ImageAddress\r
297 );\r
298 if (EFI_ERROR (Status)) {\r
299 return Status;\r
300 }\r
301\r
302 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
303\r
304 } else {\r
305 //\r
306 // Caller provided the destination buffer\r
307 //\r
308\r
309 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
310 //\r
311 // If the image relocations were stripped, and the caller provided a\r
312 // destination buffer address that does not match the address that the\r
313 // image is linked at, then the image cannot be loaded.\r
314 //\r
315 return EFI_INVALID_PARAMETER;\r
316 }\r
317\r
318 if (Image->NumberOfPages != 0 &&\r
319 Image->NumberOfPages <\r
320 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
321 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
322 return EFI_BUFFER_TOO_SMALL;\r
323 }\r
324\r
325 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
326 Image->ImageContext.ImageAddress = DstBuffer;\r
327 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
328 }\r
329\r
330 Image->ImageContext.ImageAddress =\r
331 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
332 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
333\r
334 //\r
335 // Load the image from the file into the allocated memory\r
336 //\r
337 Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
338 if (EFI_ERROR (Status)) {\r
339 return Status;\r
340 }\r
341\r
342 //\r
343 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
344 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
345 // relocation is done by the Runtime AP.\r
346 //\r
347 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
348 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
349 Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
350 if (Image->ImageContext.FixupData == NULL) {\r
351 Status = EFI_OUT_OF_RESOURCES;\r
352 goto Done;\r
353 }\r
354\r
355 //\r
356 // Make a list off all the RT images so we can let the RT AP know about them\r
357 //\r
358 Image->RuntimeFixupValid = TRUE;\r
359 Image->RuntimeFixup = Image->ImageContext.FixupData;\r
360 InsertTailList (&mRuntimeImageList, &Image->Link);\r
361 }\r
362 }\r
363\r
364 //\r
365 // Relocate the image in memory\r
366 //\r
367 Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
368 if (EFI_ERROR (Status)) {\r
369 return Status;\r
370 }\r
371\r
372 //\r
373 // Flush the Instruction Cache\r
374 //\r
375 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
376\r
377 //\r
378 // Copy the machine type from the context to the image private data. This\r
379 // is needed during image unload to know if we should call an EBC protocol\r
380 // to unload the image.\r
381 //\r
382 Image->Machine = Image->ImageContext.Machine;\r
383\r
384 //\r
385 // Get the image entry point. If it's an EBC image, then call into the\r
386 // interpreter to create a thunk for the entry point and use the returned\r
387 // value for the entry point.\r
388 //\r
389 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
390 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
391 //\r
392 // Locate the EBC interpreter protocol\r
393 //\r
394 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
395 if (EFI_ERROR(Status)) {\r
396 goto Done;\r
397 }\r
398\r
399 //\r
400 // Register a callback for flushing the instruction cache so that created\r
401 // thunks can be flushed.\r
402 //\r
403 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
404 if (EFI_ERROR(Status)) {\r
405 goto Done;\r
406 }\r
407\r
408 //\r
409 // Create a thunk for the image's entry point. This will be the new\r
410 // entry point for the image.\r
411 //\r
412 Status = Image->Ebc->CreateThunk (\r
413 Image->Ebc,\r
414 Image->Handle,\r
415 (VOID *)(UINTN)Image->ImageContext.EntryPoint,\r
416 (VOID **)&Image->EntryPoint\r
417 );\r
418 if (EFI_ERROR(Status)) {\r
419 goto Done;\r
420 }\r
421 }\r
422\r
423 //\r
424 // Fill in the image information for the Loaded Image Protocol\r
425 //\r
426 Image->Type = Image->ImageContext.ImageType;\r
427 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
428 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
429 Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;\r
430 Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;\r
431\r
432 //\r
433 // Fill in the entry point of the image if it is available\r
434 //\r
435 if (EntryPoint != NULL) {\r
436 *EntryPoint = Image->ImageContext.EntryPoint;\r
437 }\r
438\r
439 //\r
440 // Print the load address and the PDB file name if it is available\r
441 //\r
442\r
443 DEBUG_CODE (\r
444 {\r
445 UINTN Index;\r
446 UINTN StartIndex;\r
447 CHAR8 EfiFileName[256];\r
448\r
449 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint));\r
450 if (Image->ImageContext.PdbPointer != NULL) {\r
451 StartIndex = 0;\r
452 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
453 if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
454 StartIndex = Index + 1;\r
455 }\r
456 }\r
457 //\r
458 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
459 //\r
460 for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
461 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
462 if (EfiFileName[Index] == 0) {\r
463 EfiFileName[Index] = '.';\r
464 }\r
465 if (EfiFileName[Index] == '.') {\r
466 EfiFileName[Index + 1] = 'e';\r
467 EfiFileName[Index + 2] = 'f';\r
468 EfiFileName[Index + 3] = 'i';\r
469 EfiFileName[Index + 4] = 0;\r
470 break;\r
471 }\r
472 }\r
473 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
474 }\r
475 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
476 }\r
477 );\r
478\r
479 return EFI_SUCCESS;\r
480\r
481Done:\r
482 //\r
483 // Free memory\r
484 //\r
485 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
486 return Status;\r
487}\r
488\r
489\r
490LOADED_IMAGE_PRIVATE_DATA *\r
491CoreLoadedImageInfo (\r
492 IN EFI_HANDLE ImageHandle\r
493 )\r
494/*++\r
495\r
496Routine Description:\r
497\r
498 Get the image's private data from its handle.\r
499\r
500Arguments:\r
501\r
502 ImageHandle - The image handle\r
503\r
504Returns:\r
505\r
506 Return the image private data associated with ImageHandle.\r
507\r
508--*/\r
509{\r
510 EFI_STATUS Status;\r
511 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
512 LOADED_IMAGE_PRIVATE_DATA *Image;\r
513\r
514 Status = CoreHandleProtocol (\r
515 ImageHandle,\r
516 &gEfiLoadedImageProtocolGuid,\r
517 (VOID **)&LoadedImage\r
518 );\r
519 if (!EFI_ERROR (Status)) {\r
520 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
521 } else {\r
522 DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));\r
523 Image = NULL;\r
524 }\r
525\r
526 return Image;\r
527}\r
528\r
529\r
530EFI_STATUS\r
531CoreLoadImageCommon (\r
532 IN BOOLEAN BootPolicy,\r
533 IN EFI_HANDLE ParentImageHandle,\r
534 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
535 IN VOID *SourceBuffer OPTIONAL,\r
536 IN UINTN SourceSize,\r
537 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
538 IN OUT UINTN *NumberOfPages OPTIONAL,\r
539 OUT EFI_HANDLE *ImageHandle,\r
540 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
541 IN UINT32 Attribute\r
542 )\r
543/*++\r
544\r
545Routine Description:\r
546\r
547 Loads an EFI image into memory and returns a handle to the image.\r
548\r
549Arguments:\r
550\r
551 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
552 and that the boot manager is attempting to load FilePath as a boot selection.\r
553 ParentImageHandle - The caller's image handle.\r
554 FilePath - The specific file path from which the image is loaded.\r
555 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
556 the image to be loaded.\r
557 SourceSize - The size in bytes of SourceBuffer.\r
558 DstBuffer - The buffer to store the image\r
559 NumberOfPages - If not NULL, a pointer to the image's page number, if this number\r
560 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain\r
561 the required number.\r
562 ImageHandle - Pointer to the returned image handle that is created when the image\r
563 is successfully loaded.\r
564 EntryPoint - A pointer to the entry point\r
565 Attribute - The bit mask of attributes to set for the load PE image\r
566\r
567Returns:\r
568\r
569 EFI_SUCCESS - The image was loaded into memory.\r
570 EFI_NOT_FOUND - The FilePath was not found.\r
571 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
572 EFI_BUFFER_TOO_SMALL - The buffer is too small\r
573 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
574 parsed to locate the proper protocol for loading the file.\r
575 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
576--*/\r
577{\r
578 LOADED_IMAGE_PRIVATE_DATA *Image;\r
579 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
580 IMAGE_FILE_HANDLE FHand;\r
581 EFI_STATUS Status;\r
582 EFI_STATUS SecurityStatus;\r
583 EFI_HANDLE DeviceHandle;\r
584 UINT32 AuthenticationStatus;\r
585 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
586 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
587 UINTN FilePathSize;\r
588\r
589\r
590 ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);\r
591 ParentImage = NULL;\r
592\r
593 //\r
594 // The caller must pass in a valid ParentImageHandle\r
595 //\r
596 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
597 return EFI_INVALID_PARAMETER;\r
598 }\r
599\r
600 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
601 if (ParentImage == NULL) {\r
602 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
603 return EFI_INVALID_PARAMETER;\r
604 }\r
605\r
606 //\r
607 // Get simple read access to the source file\r
608 //\r
609 OriginalFilePath = FilePath;\r
610 Status = CoreOpenImageFile (\r
611 BootPolicy,\r
612 SourceBuffer,\r
613 SourceSize,\r
614 FilePath,\r
615 &DeviceHandle,\r
616 &FHand,\r
617 &AuthenticationStatus\r
618 );\r
619 if (Status == EFI_ALREADY_STARTED) {\r
620 Image = NULL;\r
621 goto Done;\r
622 } else if (EFI_ERROR (Status)) {\r
623 return Status;\r
624 }\r
625\r
626 //\r
627 // Verify the Authentication Status through the Security Architectural Protocol\r
628 //\r
629 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
630 SecurityStatus = gSecurity->FileAuthenticationState (\r
631 gSecurity,\r
632 AuthenticationStatus,\r
633 OriginalFilePath\r
634 );\r
635 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
636 Status = SecurityStatus;\r
637 Image = NULL;\r
638 goto Done;\r
639 }\r
640 }\r
641\r
642\r
643 //\r
644 // Allocate a new image structure\r
645 //\r
646 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
647 if (Image == NULL) {\r
648 return EFI_OUT_OF_RESOURCES;\r
649 }\r
650\r
651 //\r
652 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
653 //\r
654 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
655 if (!EFI_ERROR (Status)) {\r
656 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
657 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );\r
658 }\r
659\r
660 //\r
661 // Initialize the fields for an internal driver\r
662 //\r
663 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
664 Image->Info.SystemTable = gST;\r
665 Image->Info.DeviceHandle = DeviceHandle;\r
666 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
667 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);\r
668 Image->Info.ParentHandle = ParentImageHandle;\r
669\r
670 if (NumberOfPages != NULL) {\r
671 Image->NumberOfPages = *NumberOfPages ;\r
672 } else {\r
673 Image->NumberOfPages = 0 ;\r
674 }\r
675\r
676 //\r
677 // Install the protocol interfaces for this image\r
678 // don't fire notifications yet\r
679 //\r
680 Status = CoreInstallProtocolInterfaceNotify (\r
681 &Image->Handle,\r
682 &gEfiLoadedImageProtocolGuid,\r
683 EFI_NATIVE_INTERFACE,\r
684 &Image->Info,\r
685 FALSE\r
686 );\r
687 if (EFI_ERROR (Status)) {\r
688 goto Done;\r
689 }\r
690\r
691 //\r
692 // Load the image. If EntryPoint is Null, it will not be set.\r
693 //\r
694 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);\r
695 if (EFI_ERROR (Status)) {\r
696 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
697 if (NumberOfPages != NULL) {\r
698 *NumberOfPages = Image->NumberOfPages;\r
699 }\r
700 }\r
701 goto Done;\r
702 }\r
703\r
704 //\r
705 // Register the image in the Debug Image Info Table if the attribute is set\r
706 //\r
707 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
708 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
709 }\r
710\r
711 //\r
712 //Reinstall loaded image protocol to fire any notifications\r
713 //\r
714 Status = CoreReinstallProtocolInterface (\r
715 Image->Handle,\r
716 &gEfiLoadedImageProtocolGuid,\r
717 &Image->Info,\r
718 &Image->Info\r
719 );\r
720 if (EFI_ERROR (Status)) {\r
721 goto Done;\r
722 }\r
723\r
724\r
725 //\r
726 // Success. Return the image handle\r
727 //\r
728 *ImageHandle = Image->Handle;\r
729\r
730Done:\r
731 //\r
732 // All done accessing the source file\r
733 // If we allocated the Source buffer, free it\r
734 //\r
735 if (FHand.FreeBuffer) {\r
736 CoreFreePool (FHand.Source);\r
737 }\r
738\r
739 //\r
740 // There was an error. If there's an Image structure, free it\r
741 //\r
742 if (EFI_ERROR (Status)) {\r
743 if (Image != NULL) {\r
744 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
745 *ImageHandle = NULL;\r
746 }\r
747 }\r
748\r
749 return Status;\r
750}\r
751\r
752\r
753\r
754EFI_STATUS\r
755EFIAPI\r
756CoreLoadImage (\r
757 IN BOOLEAN BootPolicy,\r
758 IN EFI_HANDLE ParentImageHandle,\r
759 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
760 IN VOID *SourceBuffer OPTIONAL,\r
761 IN UINTN SourceSize,\r
762 OUT EFI_HANDLE *ImageHandle\r
763 )\r
764/*++\r
765\r
766Routine Description:\r
767\r
768 Loads an EFI image into memory and returns a handle to the image.\r
769\r
770Arguments:\r
771\r
772 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
773 and that the boot manager is attempting to load FilePath as a boot selection.\r
774 ParentImageHandle - The caller's image handle.\r
775 FilePath - The specific file path from which the image is loaded.\r
776 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
777 the image to be loaded.\r
778 SourceSize - The size in bytes of SourceBuffer.\r
779 ImageHandle - Pointer to the returned image handle that is created when the image\r
780 is successfully loaded.\r
781\r
782Returns:\r
783\r
784 EFI_SUCCESS - The image was loaded into memory.\r
785 EFI_NOT_FOUND - The FilePath was not found.\r
786 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
787 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
788 parsed to locate the proper protocol for loading the file.\r
789 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
790--*/\r
791{\r
792 EFI_STATUS Status;\r
793\r
794 PERF_START (NULL, "LoadImage", NULL, 0);\r
795\r
796 Status = CoreLoadImageCommon (\r
797 BootPolicy,\r
798 ParentImageHandle,\r
799 FilePath,\r
800 SourceBuffer,\r
801 SourceSize,\r
802 (EFI_PHYSICAL_ADDRESS)NULL,\r
803 NULL,\r
804 ImageHandle,\r
805 NULL,\r
806 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
807 );\r
808\r
809 PERF_END (NULL, "LoadImage", NULL, 0);\r
810\r
811 return Status;\r
812}\r
813\r
814\r
815EFI_STATUS\r
816EFIAPI\r
817CoreLoadImageEx (\r
818 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
819 IN EFI_HANDLE ParentImageHandle,\r
820 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
821 IN VOID *SourceBuffer OPTIONAL,\r
822 IN UINTN SourceSize,\r
823 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
824 OUT UINTN *NumberOfPages OPTIONAL,\r
825 OUT EFI_HANDLE *ImageHandle,\r
826 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
827 IN UINT32 Attribute\r
828 )\r
829/*++\r
830\r
831Routine Description:\r
832\r
833 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
834\r
835Arguments:\r
836\r
837 This - Calling context\r
838 ParentImageHandle - The caller's image handle.\r
839 FilePath - The specific file path from which the image is loaded.\r
840 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
841 the image to be loaded.\r
842 SourceSize - The size in bytes of SourceBuffer.\r
843 DstBuffer - The buffer to store the image.\r
844 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.\r
845 For output, specifies the actual space size needed.\r
846 ImageHandle - Image handle for output.\r
847 EntryPoint - Image entry point for output.\r
848 Attribute - The bit mask of attributes to set for the load PE image.\r
849\r
850Returns:\r
851\r
852 EFI_SUCCESS - The image was loaded into memory.\r
853 EFI_NOT_FOUND - The FilePath was not found.\r
854 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
855 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
856 parsed to locate the proper protocol for loading the file.\r
857 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
858--*/\r
859{\r
860 return CoreLoadImageCommon (\r
861 TRUE,\r
862 ParentImageHandle,\r
863 FilePath,\r
864 SourceBuffer,\r
865 SourceSize,\r
866 DstBuffer,\r
867 NumberOfPages,\r
868 ImageHandle,\r
869 EntryPoint,\r
870 Attribute\r
871 );\r
872}\r
873\r
874\r
875\r
876\r
877EFI_STATUS\r
878EFIAPI\r
879CoreStartImage (\r
880 IN EFI_HANDLE ImageHandle,\r
881 OUT UINTN *ExitDataSize,\r
882 OUT CHAR16 **ExitData OPTIONAL\r
883 )\r
884/*++\r
885\r
886Routine Description:\r
887\r
888 Transfer control to a loaded image's entry point.\r
889\r
890Arguments:\r
891\r
892 ImageHandle - Handle of image to be started.\r
893\r
894 ExitDataSize - Pointer of the size to ExitData\r
895\r
896 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated\r
897 Unicode string, optionally followed by additional binary data. The string\r
898 is a description that the caller may use to further indicate the reason for\r
899