]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/Image.c
check the usage of %d,%x,%ld,%lx and so on in debug print statement.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 Core image handling services to load and unload PeImage.\r
3\r
23c98c94 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
28a00297 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "Image.h"\r
17\r
28a00297 18//\r
19// Module Globals\r
20//\r
28a00297 21LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;\r
22\r
23LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {\r
24 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,\r
25 NULL,\r
26 {\r
27 CoreLoadImageEx,\r
28 CoreUnloadImageEx\r
29 }\r
30};\r
31\r
32\r
33//\r
34// This code is needed to build the Image handle for the DXE Core\r
35//\r
36LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {\r
37 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature\r
38 NULL, // Image handle\r
39 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type\r
40 TRUE, // If entrypoint has been called\r
41 NULL, // EntryPoint\r
42 {\r
43 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision\r
44 NULL, // Parent handle\r
45 NULL, // System handle\r
46\r
47 NULL, // Device handle\r
48 NULL, // File path\r
49 NULL, // Reserved\r
50\r
51 0, // LoadOptionsSize\r
52 NULL, // LoadOptions\r
53\r
54 NULL, // ImageBase\r
55 0, // ImageSize\r
56 EfiBootServicesCode, // ImageCodeType\r
57 EfiBootServicesData // ImageDataType\r
58 },\r
59 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage\r
60 0, // NumberOfPages\r
61 NULL, // FixupData\r
62 0, // Tpl\r
63 EFI_SUCCESS, // Status\r
64 0, // ExitDataSize\r
65 NULL, // ExitData\r
66 NULL, // JumpBuffer\r
67 NULL, // JumpContext\r
68 0, // Machine\r
69 NULL, // Ebc\r
70 NULL, // RuntimeData\r
ba39e316 71 NULL // LoadedImageDevicePath\r
28a00297 72};\r
73\r
74\r
28a00297 75\r
162ed594 76/**\r
28a00297 77 Add the Image Services to EFI Boot Services Table and install the protocol\r
78 interfaces for this image.\r
79\r
57d6f36d 80 @param HobStart The HOB to initialize\r
28a00297 81\r
162ed594 82 @return Status code.\r
28a00297 83\r
162ed594 84**/\r
85EFI_STATUS\r
86CoreInitializeImageServices (\r
87 IN VOID *HobStart\r
88 )\r
28a00297 89{\r
90 EFI_STATUS Status;\r
91 LOADED_IMAGE_PRIVATE_DATA *Image;\r
92 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;\r
93 UINT64 DxeCoreImageLength;\r
94 VOID *DxeCoreEntryPoint;\r
95 EFI_PEI_HOB_POINTERS DxeCoreHob;\r
96 //\r
97 // Searching for image hob\r
98 //\r
99 DxeCoreHob.Raw = HobStart;\r
100 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {\r
101 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {\r
102 //\r
103 // Find Dxe Core HOB\r
104 //\r
105 break;\r
106 }\r
107 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);\r
108 }\r
109 ASSERT (DxeCoreHob.Raw != NULL);\r
110\r
111 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;\r
112 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
113 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
114 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
115 //\r
116 // Initialize the fields for an internal driver\r
117 //\r
118 Image = &mCorePrivateImage;\r
119\r
120 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;\r
121 Image->ImageBasePage = DxeCoreImageBaseAddress;\r
122 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));\r
123 Image->Tpl = gEfiCurrentTpl;\r
124 Image->Info.SystemTable = gDxeCoreST;\r
125 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;\r
126 Image->Info.ImageSize = DxeCoreImageLength;\r
127\r
128 //\r
129 // Install the protocol interfaces for this image\r
130 //\r
131 Status = CoreInstallProtocolInterface (\r
132 &Image->Handle,\r
133 &gEfiLoadedImageProtocolGuid,\r
134 EFI_NATIVE_INTERFACE,\r
135 &Image->Info\r
136 );\r
137 ASSERT_EFI_ERROR (Status);\r
138\r
139 mCurrentImage = Image;\r
140\r
141 //\r
142 // Fill in DXE globals\r
143 //\r
144 gDxeCoreImageHandle = Image->Handle;\r
145 gDxeCoreLoadedImage = &Image->Info;\r
146\r
147 //\r
148 // Export DXE Core PE Loader functionality\r
149 //\r
150 return CoreInstallProtocolInterface (\r
151 &mLoadPe32PrivateData.Handle,\r
152 &gEfiLoadPeImageProtocolGuid,\r
153 EFI_NATIVE_INTERFACE,\r
154 &mLoadPe32PrivateData.Pe32Image\r
155 );\r
156}\r
157\r
162ed594 158\r
159/**\r
160 Loads, relocates, and invokes a PE/COFF image\r
161\r
57d6f36d 162 @param BootPolicy If TRUE, indicates that the request originates\r
163 from the boot manager, and that the boot\r
164 manager is attempting to load FilePath as a\r
165 boot selection.\r
166 @param Pe32Handle The handle of PE32 image\r
167 @param Image PE image to be loaded\r
168 @param DstBuffer The buffer to store the image\r
169 @param EntryPoint A pointer to the entry point\r
170 @param Attribute The bit mask of attributes to set for the load\r
171 PE image\r
172\r
173 @retval EFI_SUCCESS The file was loaded, relocated, and invoked\r
174 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and\r
175 relocate the PE/COFF file\r
176 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 177 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small\r
178\r
179**/\r
28a00297 180EFI_STATUS\r
181CoreLoadPeImage (\r
57d6f36d 182 IN BOOLEAN BootPolicy,\r
28a00297 183 IN VOID *Pe32Handle,\r
184 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
185 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
186 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
187 IN UINT32 Attribute\r
188 )\r
28a00297 189{\r
822360ee
LG
190 EFI_STATUS Status;\r
191 BOOLEAN DstBufAlocated;\r
192 UINTN Size;\r
193 UINTN LinkTimeBase;\r
194 EFI_TCG_PLATFORM_PROTOCOL *TcgPlatformProtocol;\r
6cd7b51e 195 IMAGE_FILE_HANDLE *FHandle;\r
28a00297 196\r
6cd7b51e 197 FHandle = NULL;\r
28a00297 198 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
199\r
200 Image->ImageContext.Handle = Pe32Handle;\r
201 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;\r
202\r
203 //\r
204 // Get information about the image being loaded\r
205 //\r
3d7b0992 206 Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);\r
28a00297 207 if (EFI_ERROR (Status)) {\r
208 return Status;\r
209 }\r
210\r
211 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
5fed8e34 212 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
213 //\r
214 // The PE/COFF loader can support loading image types that can be executed.\r
215 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
216 //\r
217 return EFI_UNSUPPORTED;\r
218 }\r
28a00297 219 }\r
57d6f36d 220\r
a0ae8996
LG
221 //\r
222 // Set EFI memory type based on ImageType\r
223 //\r
224 switch (Image->ImageContext.ImageType) {\r
225 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
226 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;\r
227 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;\r
228 break;\r
229 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
230 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;\r
231 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;\r
232 break;\r
233 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
234 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:\r
235 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;\r
236 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;\r
237 break;\r
238 default:\r
239 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
240 return EFI_UNSUPPORTED;\r
241 }\r
822360ee
LG
242 //\r
243 // Get the image base address in the original PeImage.\r
244 //\r
245 LinkTimeBase = (UINTN) Image->ImageContext.ImageAddress;\r
28a00297 246\r
247 //\r
248 // Allocate memory of the correct memory type aligned on the required image boundry\r
249 //\r
250 DstBufAlocated = FALSE;\r
251 if (DstBuffer == 0) {\r
252 //\r
253 // Allocate Destination Buffer as caller did not pass it in\r
254 //\r
255\r
256 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
257 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
258 } else {\r
259 Size = (UINTN)Image->ImageContext.ImageSize;\r
260 }\r
261\r
262 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
263\r
264 //\r
265 // If the image relocations have not been stripped, then load at any address.\r
266 // Otherwise load at the address at which it was linked.\r
267 //\r
268 // Memory below 1MB should be treated reserved for CSM and there should be\r
269 // no modules whose preferred load addresses are below 1MB.\r
270 //\r
271 Status = EFI_OUT_OF_RESOURCES;\r
272 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
273 Status = CoreAllocatePages (\r
274 AllocateAddress,\r
275 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
276 Image->NumberOfPages,\r
277 &Image->ImageContext.ImageAddress\r
278 );\r
279 }\r
280 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
281 Status = CoreAllocatePages (\r
282 AllocateAnyPages,\r
283 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
284 Image->NumberOfPages,\r
285 &Image->ImageContext.ImageAddress\r
286 );\r
287 }\r
288 if (EFI_ERROR (Status)) {\r
289 return Status;\r
290 }\r
291 DstBufAlocated = TRUE;\r
292 } else {\r
293 //\r
294 // Caller provided the destination buffer\r
295 //\r
296\r
297 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
298 //\r
299 // If the image relocations were stripped, and the caller provided a\r
300 // destination buffer address that does not match the address that the\r
301 // image is linked at, then the image cannot be loaded.\r
302 //\r
303 return EFI_INVALID_PARAMETER;\r
304 }\r
305\r
306 if (Image->NumberOfPages != 0 &&\r
307 Image->NumberOfPages <\r
308 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
309 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
310 return EFI_BUFFER_TOO_SMALL;\r
311 }\r
312\r
313 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
314 Image->ImageContext.ImageAddress = DstBuffer;\r
315 }\r
316\r
317 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
1046284d
LG
318 if (!Image->ImageContext.IsTeImage) {\r
319 Image->ImageContext.ImageAddress =\r
320 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
321 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
322 }\r
28a00297 323\r
324 //\r
325 // Load the image from the file into the allocated memory\r
326 //\r
3d7b0992 327 Status = PeCoffLoaderLoadImage (&Image->ImageContext);\r
28a00297 328 if (EFI_ERROR (Status)) {\r
329 goto Done;\r
330 }\r
331\r
332 //\r
333 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
334 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
335 // relocation is done by the Runtime AP.\r
336 //\r
71f68914 337 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 338 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
9c4ac31c 339 Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
28a00297 340 if (Image->ImageContext.FixupData == NULL) {\r
341 Status = EFI_OUT_OF_RESOURCES;\r
342 goto Done;\r
343 }\r
344 }\r
345 }\r
346\r
822360ee
LG
347 //\r
348 // Measure the image before applying fixup\r
349 //\r
350 Status = CoreLocateProtocol (\r
351 &gEfiTcgPlatformProtocolGuid,\r
352 NULL,\r
353 (VOID **) &TcgPlatformProtocol\r
354 );\r
6cd7b51e
LG
355 if (!EFI_ERROR (Status)) {\r
356 FHandle = (IMAGE_FILE_HANDLE *) Image->ImageContext.Handle;\r
822360ee
LG
357 Status = TcgPlatformProtocol->MeasurePeImage (\r
358 BootPolicy,\r
6cd7b51e
LG
359 (EFI_PHYSICAL_ADDRESS) (UINTN) FHandle->Source,\r
360 FHandle->SourceSize,\r
822360ee
LG
361 LinkTimeBase,\r
362 Image->ImageContext.ImageType,\r
363 Image->Info.DeviceHandle,\r
364 Image->Info.FilePath\r
365 );\r
6cd7b51e 366\r
822360ee
LG
367 ASSERT_EFI_ERROR (Status);\r
368 }\r
369\r
28a00297 370 //\r
371 // Relocate the image in memory\r
372 //\r
3d7b0992 373 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);\r
28a00297 374 if (EFI_ERROR (Status)) {\r
375 goto Done;\r
376 }\r
377\r
378 //\r
379 // Flush the Instruction Cache\r
380 //\r
381 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
382\r
383 //\r
384 // Copy the machine type from the context to the image private data. This\r
385 // is needed during image unload to know if we should call an EBC protocol\r
386 // to unload the image.\r
387 //\r
388 Image->Machine = Image->ImageContext.Machine;\r
389\r
390 //\r
391 // Get the image entry point. If it's an EBC image, then call into the\r
392 // interpreter to create a thunk for the entry point and use the returned\r
393 // value for the entry point.\r
394 //\r
395 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
396 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
397 //\r
398 // Locate the EBC interpreter protocol\r
399 //\r
400 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
401 if (EFI_ERROR(Status)) {\r
57d6f36d 402 DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));\r
28a00297 403 goto Done;\r
404 }\r
405\r
406 //\r
407 // Register a callback for flushing the instruction cache so that created\r
408 // thunks can be flushed.\r
409 //\r
410 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
411 if (EFI_ERROR(Status)) {\r
412 goto Done;\r
413 }\r
414\r
415 //\r
416 // Create a thunk for the image's entry point. This will be the new\r
417 // entry point for the image.\r
418 //\r
419 Status = Image->Ebc->CreateThunk (\r
420 Image->Ebc,\r
421 Image->Handle,\r
e94a9ff7 422 (VOID *)(UINTN) Image->ImageContext.EntryPoint,\r
423 (VOID **) &Image->EntryPoint\r
28a00297 424 );\r
425 if (EFI_ERROR(Status)) {\r
426 goto Done;\r
427 }\r
428 }\r
429\r
430 //\r
431 // Fill in the image information for the Loaded Image Protocol\r
432 //\r
433 Image->Type = Image->ImageContext.ImageType;\r
434 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
435 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
436 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
437 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
71f68914 438 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 439 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
440 //\r
441 // Make a list off all the RT images so we can let the RT AP know about them.\r
442 //\r
9c4ac31c 443 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
28a00297 444 if (Image->RuntimeData == NULL) {\r
445 goto Done;\r
446 }\r
447 Image->RuntimeData->ImageBase = Image->Info.ImageBase;\r
448 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);\r
449 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
450 Image->RuntimeData->Handle = Image->Handle;\r
451 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
452 }\r
453 }\r
454\r
455 //\r
456 // Fill in the entry point of the image if it is available\r
457 //\r
458 if (EntryPoint != NULL) {\r
459 *EntryPoint = Image->ImageContext.EntryPoint;\r
460 }\r
461\r
462 //\r
463 // Print the load address and the PDB file name if it is available\r
464 //\r
465\r
466 DEBUG_CODE_BEGIN ();\r
467\r
468 UINTN Index;\r
469 UINTN StartIndex;\r
470 CHAR8 EfiFileName[256];\r
57d6f36d 471\r
022c6d45 472\r
e94a9ff7 473 DEBUG ((DEBUG_INFO | DEBUG_LOAD,\r
91136124 474 "Loading driver at 0x%11p EntryPoint=0x%11p ",\r
e94a9ff7 475 (VOID *)(UINTN) Image->ImageContext.ImageAddress,\r
4e2dd553 476 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));\r
022c6d45 477\r
57d6f36d 478\r
e98cd821
LG
479 //\r
480 // Print Module Name by Pdb file path\r
481 //\r
28a00297 482 if (Image->ImageContext.PdbPointer != NULL) {\r
483 StartIndex = 0;\r
484 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
485 if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
486 StartIndex = Index + 1;\r
487 }\r
488 }\r
489 //\r
490 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
491 //\r
492 for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
493 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
494 if (EfiFileName[Index] == 0) {\r
495 EfiFileName[Index] = '.';\r
496 }\r
497 if (EfiFileName[Index] == '.') {\r
498 EfiFileName[Index + 1] = 'e';\r
499 EfiFileName[Index + 2] = 'f';\r
500 EfiFileName[Index + 3] = 'i';\r
501 EfiFileName[Index + 4] = 0;\r
502 break;\r
503 }\r
504 }\r
162ed594 505 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
28a00297 506 }\r
162ed594 507 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
28a00297 508\r
509 DEBUG_CODE_END ();\r
510\r
511 return EFI_SUCCESS;\r
512\r
513Done:\r
514\r
515 //\r
516 // Free memory.\r
517 //\r
518\r
519 if (DstBufAlocated) {\r
520 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
521 }\r
522\r
523 if (Image->ImageContext.FixupData != NULL) {\r
524 CoreFreePool (Image->ImageContext.FixupData);\r
525 }\r
526\r
527 return Status;\r
528}\r
529\r
530\r
28a00297 531\r
162ed594 532/**\r
28a00297 533 Get the image's private data from its handle.\r
534\r
57d6f36d 535 @param ImageHandle The image handle\r
28a00297 536\r
162ed594 537 @return Return the image private data associated with ImageHandle.\r
28a00297 538\r
162ed594 539**/\r
540LOADED_IMAGE_PRIVATE_DATA *\r
541CoreLoadedImageInfo (\r
542 IN EFI_HANDLE ImageHandle\r
543 )\r
28a00297 544{\r
545 EFI_STATUS Status;\r
546 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
547 LOADED_IMAGE_PRIVATE_DATA *Image;\r
548\r
549 Status = CoreHandleProtocol (\r
550 ImageHandle,\r
551 &gEfiLoadedImageProtocolGuid,\r
552 (VOID **)&LoadedImage\r
553 );\r
554 if (!EFI_ERROR (Status)) {\r
555 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
556 } else {\r
e94a9ff7 557 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));\r
28a00297 558 Image = NULL;\r
559 }\r
560\r
561 return Image;\r
562}\r
563\r
162ed594 564\r
c0a23f8c 565/**\r
566 Unloads EFI image from memory.\r
567\r
568 @param Image EFI image\r
569 @param FreePage Free allocated pages\r
570\r
571**/\r
572VOID\r
573CoreUnloadAndCloseImage (\r
574 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
575 IN BOOLEAN FreePage\r
576 )\r
577{\r
578 EFI_STATUS Status;\r
579 UINTN HandleCount;\r
580 EFI_HANDLE *HandleBuffer;\r
581 UINTN HandleIndex;\r
582 EFI_GUID **ProtocolGuidArray;\r
583 UINTN ArrayCount;\r
584 UINTN ProtocolIndex;\r
585 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
586 UINTN OpenInfoCount;\r
587 UINTN OpenInfoIndex;\r
588\r
589 if (Image->Ebc != NULL) {\r
590 //\r
591 // If EBC protocol exists we must perform cleanups for this image.\r
592 //\r
593 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
594 }\r
595\r
596 //\r
597 // Unload image, free Image->ImageContext->ModHandle\r
598 //\r
599 PeCoffLoaderUnloadImage (&Image->ImageContext);\r
600\r
601 //\r
602 // Free our references to the image handle\r
603 //\r
604 if (Image->Handle != NULL) {\r
605\r
606 Status = CoreLocateHandleBuffer (\r
607 AllHandles,\r
608 NULL,\r
609 NULL,\r
610 &HandleCount,\r
611 &HandleBuffer\r
612 );\r
613 if (!EFI_ERROR (Status)) {\r
614 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
615 Status = CoreProtocolsPerHandle (\r
616 HandleBuffer[HandleIndex],\r
617 &ProtocolGuidArray,\r
618 &ArrayCount\r
619 );\r
620 if (!EFI_ERROR (Status)) {\r
621 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
622 Status = CoreOpenProtocolInformation (\r
623 HandleBuffer[HandleIndex],\r
624 ProtocolGuidArray[ProtocolIndex],\r
625 &OpenInfo,\r
626 &OpenInfoCount\r
627 );\r
628 if (!EFI_ERROR (Status)) {\r
629 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
630 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
631 Status = CoreCloseProtocol (\r
632 HandleBuffer[HandleIndex],\r
633 ProtocolGuidArray[ProtocolIndex],\r
634 Image->Handle,\r
635 OpenInfo[OpenInfoIndex].ControllerHandle\r
636 );\r
637 }\r
638 }\r
639 if (OpenInfo != NULL) {\r
640 CoreFreePool(OpenInfo);\r
641 }\r
642 }\r
643 }\r
644 if (ProtocolGuidArray != NULL) {\r
645 CoreFreePool(ProtocolGuidArray);\r
646 }\r
647 }\r
648 }\r
649 if (HandleBuffer != NULL) {\r
650 CoreFreePool (HandleBuffer);\r
651 }\r
652 }\r
653\r
654 CoreRemoveDebugImageInfoEntry (Image->Handle);\r
655\r
656 Status = CoreUninstallProtocolInterface (\r
657 Image->Handle,\r
658 &gEfiLoadedImageDevicePathProtocolGuid,\r
659 Image->LoadedImageDevicePath\r
660 );\r
661\r
662 Status = CoreUninstallProtocolInterface (\r
663 Image->Handle,\r
664 &gEfiLoadedImageProtocolGuid,\r
665 &Image->Info\r
666 );\r
667\r
668 }\r
669\r
670 if (Image->RuntimeData != NULL) {\r
671 if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
672 //\r
673 // Remove the Image from the Runtime Image list as we are about to Free it!\r
674 //\r
675 RemoveEntryList (&Image->RuntimeData->Link);\r
676 }\r
677 CoreFreePool (Image->RuntimeData);\r
678 }\r
679\r
680 //\r
681 // Free the Image from memory\r
682 //\r
683 if ((Image->ImageBasePage != 0) && FreePage) {\r
684 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
685 }\r
686\r
687 //\r
688 // Done with the Image structure\r
689 //\r
690 if (Image->Info.FilePath != NULL) {\r
691 CoreFreePool (Image->Info.FilePath);\r
692 }\r
693\r
694 if (Image->LoadedImageDevicePath != NULL) {\r
695 CoreFreePool (Image->LoadedImageDevicePath);\r
696 }\r
697\r
698 if (Image->FixupData != NULL) {\r
699 CoreFreePool (Image->FixupData);\r
700 }\r
701\r
702 CoreFreePool (Image);\r
703}\r
704\r
705\r
162ed594 706/**\r
707 Loads an EFI image into memory and returns a handle to the image.\r
708\r
57d6f36d 709 @param BootPolicy If TRUE, indicates that the request originates\r
710 from the boot manager, and that the boot\r
711 manager is attempting to load FilePath as a\r
712 boot selection.\r
713 @param ParentImageHandle The caller's image handle.\r
714 @param FilePath The specific file path from which the image is\r
715 loaded.\r
716 @param SourceBuffer If not NULL, a pointer to the memory location\r
717 containing a copy of the image to be loaded.\r
718 @param SourceSize The size in bytes of SourceBuffer.\r
719 @param DstBuffer The buffer to store the image\r
720 @param NumberOfPages If not NULL, it inputs a pointer to the page\r
721 number of DstBuffer and outputs a pointer to\r
722 the page number of the image. If this number is\r
723 not enough, return EFI_BUFFER_TOO_SMALL and\r
724 this parameter contains the required number.\r
725 @param ImageHandle Pointer to the returned image handle that is\r
726 created when the image is successfully loaded.\r
727 @param EntryPoint A pointer to the entry point\r
728 @param Attribute The bit mask of attributes to set for the load\r
729 PE image\r
730\r
731 @retval EFI_SUCCESS The image was loaded into memory.\r
732 @retval EFI_NOT_FOUND The FilePath was not found.\r
733 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
734 @retval EFI_BUFFER_TOO_SMALL The buffer is too small\r
735 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
736 path cannot be parsed to locate the proper\r
737 protocol for loading the file.\r
738 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 739 resources.\r
740\r
741**/\r
28a00297 742EFI_STATUS\r
743CoreLoadImageCommon (\r
744 IN BOOLEAN BootPolicy,\r
745 IN EFI_HANDLE ParentImageHandle,\r
746 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
747 IN VOID *SourceBuffer OPTIONAL,\r
748 IN UINTN SourceSize,\r
749 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
750 IN OUT UINTN *NumberOfPages OPTIONAL,\r
751 OUT EFI_HANDLE *ImageHandle,\r
752 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
753 IN UINT32 Attribute\r
754 )\r
28a00297 755{\r
756 LOADED_IMAGE_PRIVATE_DATA *Image;\r
757 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
758 IMAGE_FILE_HANDLE FHand;\r
759 EFI_STATUS Status;\r
760 EFI_STATUS SecurityStatus;\r
761 EFI_HANDLE DeviceHandle;\r
762 UINT32 AuthenticationStatus;\r
763 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
764 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
765 UINTN FilePathSize;\r
766\r
767 SecurityStatus = EFI_SUCCESS;\r
768\r
769 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
770 ParentImage = NULL;\r
771\r
772 //\r
773 // The caller must pass in a valid ParentImageHandle\r
774 //\r
775 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
776 return EFI_INVALID_PARAMETER;\r
777 }\r
778\r
779 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
780 if (ParentImage == NULL) {\r
162ed594 781 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
28a00297 782 return EFI_INVALID_PARAMETER;\r
783 }\r
784\r
785 //\r
786 // Get simple read access to the source file\r
787 //\r
788 OriginalFilePath = FilePath;\r
789 Status = CoreOpenImageFile (\r
790 BootPolicy,\r
791 SourceBuffer,\r
792 SourceSize,\r
cfe9de52 793 &FilePath,\r
28a00297 794 &DeviceHandle,\r
795 &FHand,\r
796 &AuthenticationStatus\r
797 );\r
798 if (Status == EFI_ALREADY_STARTED) {\r
799 Image = NULL;\r
800 goto Done;\r
801 } else if (EFI_ERROR (Status)) {\r
802 return Status;\r
803 }\r
804\r
805 //\r
806 // Verify the Authentication Status through the Security Architectural Protocol\r
807 //\r
808 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
809 SecurityStatus = gSecurity->FileAuthenticationState (\r
810 gSecurity,\r
811 AuthenticationStatus,\r
812 OriginalFilePath\r
813 );\r
814 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
815 Status = SecurityStatus;\r
816 Image = NULL;\r
817 goto Done;\r
818 }\r
819 }\r
820\r
821\r
822 //\r
823 // Allocate a new image structure\r
824 //\r
9c4ac31c 825 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
28a00297 826 if (Image == NULL) {\r
827 return EFI_OUT_OF_RESOURCES;\r
828 }\r
829\r
830 //\r
831 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
832 //\r
cfe9de52 833 FilePath = OriginalFilePath;\r
28a00297 834 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
835 if (!EFI_ERROR (Status)) {\r
9c4ac31c 836 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
e94a9ff7 837 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );\r
28a00297 838 }\r
839\r
840 //\r
841 // Initialize the fields for an internal driver\r
842 //\r
843 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
844 Image->Info.SystemTable = gDxeCoreST;\r
845 Image->Info.DeviceHandle = DeviceHandle;\r
162ed594 846 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
9c4ac31c 847 Image->Info.FilePath = DuplicateDevicePath (FilePath);\r
28a00297 848 Image->Info.ParentHandle = ParentImageHandle;\r
849\r
85658066 850\r
28a00297 851 if (NumberOfPages != NULL) {\r
852 Image->NumberOfPages = *NumberOfPages ;\r
853 } else {\r
854 Image->NumberOfPages = 0 ;\r
855 }\r
856\r
857 //\r
858 // Install the protocol interfaces for this image\r
859 // don't fire notifications yet\r
860 //\r
861 Status = CoreInstallProtocolInterfaceNotify (\r
862 &Image->Handle,\r
863 &gEfiLoadedImageProtocolGuid,\r
864 EFI_NATIVE_INTERFACE,\r
865 &Image->Info,\r
866 FALSE\r
867 );\r
868 if (EFI_ERROR (Status)) {\r
869 goto Done;\r
870 }\r
871\r
872 //\r
873 // Load the image. If EntryPoint is Null, it will not be set.\r
874 //\r
822360ee 875 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);\r
28a00297 876 if (EFI_ERROR (Status)) {\r
877 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
878 if (NumberOfPages != NULL) {\r
879 *NumberOfPages = Image->NumberOfPages;\r
880 }\r
881 }\r
882 goto Done;\r
883 }\r
884\r
152af594 885 if (NumberOfPages != NULL) {\r
886 *NumberOfPages = Image->NumberOfPages;\r
57d6f36d 887 }\r
152af594 888\r
28a00297 889 //\r
890 // Register the image in the Debug Image Info Table if the attribute is set\r
891 //\r
71f68914 892 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {\r
28a00297 893 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
894 }\r
895\r
896 //\r
897 //Reinstall loaded image protocol to fire any notifications\r
898 //\r
899 Status = CoreReinstallProtocolInterface (\r
900 Image->Handle,\r
901 &gEfiLoadedImageProtocolGuid,\r
902 &Image->Info,\r
903 &Image->Info\r
904 );\r
905 if (EFI_ERROR (Status)) {\r
906 goto Done;\r
907 }\r
908\r
ba39e316 909 //\r
910 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,\r
911 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.\r
912 //\r
913 if (OriginalFilePath != NULL) {\r
9c4ac31c 914 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);\r
ba39e316 915 }\r
916\r
917 //\r
918 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image\r
919 //\r
920 Status = CoreInstallProtocolInterface (\r
921 &Image->Handle,\r
922 &gEfiLoadedImageDevicePathProtocolGuid,\r
923 EFI_NATIVE_INTERFACE,\r
924 Image->LoadedImageDevicePath\r
925 );\r
926 if (EFI_ERROR (Status)) {\r
927 goto Done;\r
928 }\r
28a00297 929\r
930 //\r
931 // Success. Return the image handle\r
932 //\r
933 *ImageHandle = Image->Handle;\r
934\r
935Done:\r
936 //\r
937 // All done accessing the source file\r
938 // If we allocated the Source buffer, free it\r
939 //\r
940 if (FHand.FreeBuffer) {\r
941 CoreFreePool (FHand.Source);\r
942 }\r
943\r
944 //\r
945 // There was an error. If there's an Image structure, free it\r
946 //\r
947 if (EFI_ERROR (Status)) {\r
948 if (Image != NULL) {\r
949 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
950 *ImageHandle = NULL;\r
951 }\r
952 } else if (EFI_ERROR (SecurityStatus)) {\r
953 Status = SecurityStatus;\r
954 }\r
955\r
956 return Status;\r
957}\r
958\r
959\r
960\r
162ed594 961\r
962/**\r
963 Loads an EFI image into memory and returns a handle to the image.\r
964\r
57d6f36d 965 @param BootPolicy If TRUE, indicates that the request originates\r
966 from the boot manager, and that the boot\r
967 manager is attempting to load FilePath as a\r
968 boot selection.\r
969 @param ParentImageHandle The caller's image handle.\r
970 @param FilePath The specific file path from which the image is\r
971 loaded.\r
972 @param SourceBuffer If not NULL, a pointer to the memory location\r
973 containing a copy of the image to be loaded.\r
974 @param SourceSize The size in bytes of SourceBuffer.\r
975 @param ImageHandle Pointer to the returned image handle that is\r
976 created when the image is successfully loaded.\r
977\r
978 @retval EFI_SUCCESS The image was loaded into memory.\r
979 @retval EFI_NOT_FOUND The FilePath was not found.\r
980 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
981 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
982 path cannot be parsed to locate the proper\r
983 protocol for loading the file.\r
984 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 985 resources.\r
986\r
987**/\r
28a00297 988EFI_STATUS\r
989EFIAPI\r
990CoreLoadImage (\r
991 IN BOOLEAN BootPolicy,\r
992 IN EFI_HANDLE ParentImageHandle,\r
993 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
994 IN VOID *SourceBuffer OPTIONAL,\r
995 IN UINTN SourceSize,\r
996 OUT EFI_HANDLE *ImageHandle\r
997 )\r
28a00297 998{\r
999 EFI_STATUS Status;\r
7cff25d6 1000 UINT64 Tick;\r
28a00297 1001\r
7cff25d6 1002 Tick = 0;\r
1003 PERF_CODE (\r
1004 Tick = GetPerformanceCounter ();\r
1005 );\r
28a00297 1006\r
1007 Status = CoreLoadImageCommon (\r
1008 BootPolicy,\r
1009 ParentImageHandle,\r
1010 FilePath,\r
1011 SourceBuffer,\r
1012 SourceSize,\r
1be0dda6 1013 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,\r
28a00297 1014 NULL,\r
1015 ImageHandle,\r
1016 NULL,\r
1017 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
1018 );\r
1019\r
7cff25d6 1020 PERF_START (*ImageHandle, LOAD_IMAGE_TOK, NULL, Tick);\r
1021 PERF_END (*ImageHandle, LOAD_IMAGE_TOK, NULL, 0);\r
28a00297 1022\r
1023 return Status;\r
1024}\r
1025\r
1026\r
162ed594 1027\r
1028/**\r
1029 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
1030\r
57d6f36d 1031 @param This Calling context\r
1032 @param ParentImageHandle The caller's image handle.\r
1033 @param FilePath The specific file path from which the image is\r
1034 loaded.\r
1035 @param SourceBuffer If not NULL, a pointer to the memory location\r
1036 containing a copy of the image to be loaded.\r
1037 @param SourceSize The size in bytes of SourceBuffer.\r
1038 @param DstBuffer The buffer to store the image.\r
1039 @param NumberOfPages For input, specifies the space size of the\r
1040 image by caller if not NULL. For output,\r
1041 specifies the actual space size needed.\r
1042 @param ImageHandle Image handle for output.\r
1043 @param EntryPoint Image entry point for output.\r
1044 @param Attribute The bit mask of attributes to set for the load\r
1045 PE image.\r
1046\r
1047 @retval EFI_SUCCESS The image was loaded into memory.\r
1048 @retval EFI_NOT_FOUND The FilePath was not found.\r
1049 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1050 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1051 path cannot be parsed to locate the proper\r
1052 protocol for loading the file.\r
1053 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 1054 resources.\r
1055\r
1056**/\r
28a00297 1057EFI_STATUS\r
1058EFIAPI\r
1059CoreLoadImageEx (\r
1060 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1061 IN EFI_HANDLE ParentImageHandle,\r
1062 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1063 IN VOID *SourceBuffer OPTIONAL,\r
1064 IN UINTN SourceSize,\r
1065 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
1066 OUT UINTN *NumberOfPages OPTIONAL,\r
1067 OUT EFI_HANDLE *ImageHandle,\r
1068 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
1069 IN UINT32 Attribute\r
1070 )\r
28a00297 1071{\r
1072 return CoreLoadImageCommon (\r
1073 TRUE,\r
1074 ParentImageHandle,\r
1075 FilePath,\r
1076 SourceBuffer,\r
1077 SourceSize,\r
1078 DstBuffer,\r
1079 NumberOfPages,\r
1080 ImageHandle,\r
1081 EntryPoint,\r
1082 Attribute\r
1083 );\r
1084}\r
1085\r
162ed594 1086\r
1087/**\r
1088 Transfer control to a loaded image's entry point.\r
1089\r
57d6f36d 1090 @param ImageHandle Handle of image to be started.\r
1091 @param ExitDataSize Pointer of the size to ExitData\r
1092 @param ExitData Pointer to a pointer to a data buffer that\r
1093 includes a Null-terminated Unicode string,\r
1094 optionally followed by additional binary data.\r
1095 The string is a description that the caller may\r
1096 use to further indicate the reason for the\r
1097 image's exit.\r
1098\r
1099 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1100 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
1101 @retval EFI_SUCCESS Successfully transfer control to the image's\r
162ed594 1102 entry point.\r
1103\r
1104**/\r
28a00297 1105EFI_STATUS\r
1106EFIAPI\r
1107CoreStartImage (\r
1108 IN EFI_HANDLE ImageHandle,\r
1109 OUT UINTN *ExitDataSize,\r
1110 OUT CHAR16 **ExitData OPTIONAL\r
1111 )\r
28a00297 1112{\r
1113 EFI_STATUS Status;\r
1114 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1115 LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
1116 UINT64 HandleDatabaseKey;\r
1117 UINTN SetJumpFlag;\r
1118\r
1119 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1120 if (Image == NULL || Image->Started) {\r
28a00297 1121 return EFI_INVALID_PARAMETER;\r
1122 }\r
1123\r
1124 //\r
1125 // Don't profile Objects or invalid start requests\r
1126 //\r
1127 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
1128\r
1129\r
1130 //\r
1131 // Push the current start image context, and\r
1132 // link the current image to the head. This is the\r
1133 // only image that can call Exit()\r
1134 //\r
1135 HandleDatabaseKey = CoreGetHandleDatabaseKey ();\r
1136 LastImage = mCurrentImage;\r
1137 mCurrentImage = Image;\r
1138 Image->Tpl = gEfiCurrentTpl;\r
1139\r
1140 //\r
1141 // Set long jump for Exit() support\r
1142 // JumpContext must be aligned on a CPU specific boundary.\r
1143 // Overallocate the buffer and force the required alignment\r
1144 //\r
9c4ac31c 1145 Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
28a00297 1146 if (Image->JumpBuffer == NULL) {\r
1147 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
1148 return EFI_OUT_OF_RESOURCES;\r
1149 }\r
1150 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
1151\r
1152 SetJumpFlag = SetJump (Image->JumpContext);\r
1153 //\r
1154 // The initial call to SetJump() must always return 0.\r
1155 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
1156 //\r
71f68914 1157 if (SetJumpFlag == 0) {\r
28a00297 1158 //\r
1159 // Call the image's entry point\r
1160 //\r
1161 Image->Started = TRUE;\r
1162 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);\r
1163\r
1164 //\r
1165 // Add some debug information if the image returned with error.\r
1166 // This make the user aware and check if the driver image have already released\r
1167 // all the resource in this situation.\r
1168 //\r
1169 DEBUG_CODE_BEGIN ();\r
1170 if (EFI_ERROR (Image->Status)) {\r
91136124 1171 DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
28a00297 1172 }\r
1173 DEBUG_CODE_END ();\r
1174\r
1175 //\r
1176 // If the image returns, exit it through Exit()\r
1177 //\r
1178 CoreExit (ImageHandle, Image->Status, 0, NULL);\r
1179 }\r
1180\r
1181 //\r
1182 // Image has completed. Verify the tpl is the same\r
1183 //\r
1184 ASSERT (Image->Tpl == gEfiCurrentTpl);\r
1185 CoreRestoreTpl (Image->Tpl);\r
1186\r
1187 CoreFreePool (Image->JumpBuffer);\r
1188\r
1189 //\r
1190 // Pop the current start image context\r
1191 //\r
1192 mCurrentImage = LastImage;\r
1193\r
1194 //\r
1195 // Go connect any handles that were created or modified while the image executed.\r
1196 //\r
1197 CoreConnectHandlesByKey (HandleDatabaseKey);\r
1198\r
1199 //\r
1200 // Handle the image's returned ExitData\r
1201 //\r
1202 DEBUG_CODE_BEGIN ();\r
1203 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
1204\r
7df7393f 1205 DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));\r
28a00297 1206 if (Image->ExitData != NULL) {\r
162ed594 1207 DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));\r
28a00297 1208 }\r
162ed594 1209 DEBUG ((DEBUG_LOAD, "\n"));\r
28a00297 1210 }\r
1211 DEBUG_CODE_END ();\r
1212\r
1213 //\r
1214 // Return the exit data to the caller\r
1215 //\r
1216 if (ExitData != NULL && ExitDataSize != NULL) {\r
1217 *ExitDataSize = Image->ExitDataSize;\r
1218 *ExitData = Image->ExitData;\r
1219 } else {\r
1220 //\r
1221 // Caller doesn't want the exit data, free it\r
1222 //\r
1223 CoreFreePool (Image->ExitData);\r
1224 Image->ExitData = NULL;\r
1225 }\r
1226\r
1227 //\r
1228 // Save the Status because Image will get destroyed if it is unloaded.\r
1229 //\r
1230 Status = Image->Status;\r
1231\r
1232 //\r
1233 // If the image returned an error, or if the image is an application\r
1234 // unload it\r
1235 //\r
1236 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1237 CoreUnloadAndCloseImage (Image, TRUE);\r
1238 }\r
1239\r
1240 //\r
1241 // Done\r
1242 //\r
1243 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
1244 return Status;\r
1245}\r
1246\r
162ed594 1247/**\r
1248 Terminates the currently loaded EFI image and returns control to boot services.\r
1249\r
57d6f36d 1250 @param ImageHandle Handle that identifies the image. This\r
1251 parameter is passed to the image on entry.\r
1252 @param Status The image's exit code.\r
1253 @param ExitDataSize The size, in bytes, of ExitData. Ignored if\r
1254 ExitStatus is EFI_SUCCESS.\r
1255 @param ExitData Pointer to a data buffer that includes a\r
1256 Null-terminated Unicode string, optionally\r
1257 followed by additional binary data. The string\r
1258 is a description that the caller may use to\r
1259 further indicate the reason for the image's\r
1260 exit.\r
1261\r
1262 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current\r
1263 image.\r
1264 @retval EFI_SUCCESS Successfully terminates the currently loaded\r
1265 EFI image.\r
1266 @retval EFI_ACCESS_DENIED Should never reach there.\r
162ed594 1267 @retval EFI_OUT_OF_RESOURCES Could not allocate pool\r
1268\r
1269**/\r
28a00297 1270EFI_STATUS\r
1271EFIAPI\r
1272CoreExit (\r
1273 IN EFI_HANDLE ImageHandle,\r
1274 IN EFI_STATUS Status,\r
1275 IN UINTN ExitDataSize,\r
1276 IN CHAR16 *ExitData OPTIONAL\r
1277 )\r
28a00297 1278{\r
1279 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1280 EFI_TPL OldTpl;\r
1281\r
1282 //\r
1283 // Prevent possible reentrance to this function\r
1284 // for the same ImageHandle\r
57d6f36d 1285 //\r
1286 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1287\r
28a00297 1288 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1289 if (Image == NULL) {\r
28a00297 1290 Status = EFI_INVALID_PARAMETER;\r
1291 goto Done;\r
1292 }\r
1293\r
1294 if (!Image->Started) {\r
1295 //\r
1296 // The image has not been started so just free its resources\r
1297 //\r
1298 CoreUnloadAndCloseImage (Image, TRUE);\r
1299 Status = EFI_SUCCESS;\r
1300 goto Done;\r
1301 }\r
1302\r
1303 //\r
1304 // Image has been started, verify this image can exit\r
1305 //\r
1306 if (Image != mCurrentImage) {\r
162ed594 1307 DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));\r
28a00297 1308 Status = EFI_INVALID_PARAMETER;\r
1309 goto Done;\r
1310 }\r
1311\r
1312 //\r
1313 // Set status\r
1314 //\r
1315 Image->Status = Status;\r
1316\r
1317 //\r
1318 // If there's ExitData info, move it\r
1319 //\r
1320 if (ExitData != NULL) {\r
1321 Image->ExitDataSize = ExitDataSize;\r
9c4ac31c 1322 Image->ExitData = AllocatePool (Image->ExitDataSize);\r
28a00297 1323 if (Image->ExitData == NULL) {\r
1324 Status = EFI_OUT_OF_RESOURCES;\r
1325 goto Done;\r
1326 }\r
1327 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
1328 }\r
1329\r
1330 CoreRestoreTpl (OldTpl);\r
1331 //\r
1332 // return to StartImage\r
1333 //\r
1334 LongJump (Image->JumpContext, (UINTN)-1);\r
1335\r
1336 //\r
1337 // If we return from LongJump, then it is an error\r
1338 //\r
1339 ASSERT (FALSE);\r
1340 Status = EFI_ACCESS_DENIED;\r
1341Done:\r
1342 CoreRestoreTpl (OldTpl);\r
1343 return Status;\r
1344}\r
1345\r
1346\r
1347\r
28a00297 1348\r
162ed594 1349/**\r
28a00297 1350 Unloads an image.\r
1351\r
57d6f36d 1352 @param ImageHandle Handle that identifies the image to be\r
1353 unloaded.\r
28a00297 1354\r
57d6f36d 1355 @retval EFI_SUCCESS The image has been unloaded.\r
1356 @retval EFI_UNSUPPORTED The image has been sarted, and does not support\r
1357 unload.\r
162ed594 1358 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.\r
28a00297 1359\r
162ed594 1360**/\r
1361EFI_STATUS\r
1362EFIAPI\r
1363CoreUnloadImage (\r
1364 IN EFI_HANDLE ImageHandle\r
1365 )\r
28a00297 1366{\r
1367 EFI_STATUS Status;\r
1368 LOADED_IMAGE_PRIVATE_DATA *Image;\r
28a00297 1369\r
28a00297 1370 Image = CoreLoadedImageInfo (ImageHandle);\r
1371 if (Image == NULL ) {\r
1372 //\r
1373 // The image handle is not valid\r
1374 //\r
1375 Status = EFI_INVALID_PARAMETER;\r
1376 goto Done;\r
1377 }\r
1378\r
1379 if (Image->Started) {\r
1380 //\r
1381 // The image has been started, request it to unload.\r
1382 //\r
1383 Status = EFI_UNSUPPORTED;\r
1384 if (Image->Info.Unload != NULL) {\r
1385 Status = Image->Info.Unload (ImageHandle);\r
1386 }\r
1387\r
1388 } else {\r
1389 //\r
1390 // This Image hasn't been started, thus it can be unloaded\r
1391 //\r
1392 Status = EFI_SUCCESS;\r
1393 }\r
1394\r
1395\r
1396 if (!EFI_ERROR (Status)) {\r
1397 //\r
1398 // if the Image was not started or Unloaded O.K. then clean up\r
1399 //\r
1400 CoreUnloadAndCloseImage (Image, TRUE);\r
1401 }\r
1402\r
1403Done:\r
28a00297 1404 return Status;\r
1405}\r
1406\r
1407\r
162ed594 1408\r
1409/**\r
1410 Unload the specified image.\r
1411\r
57d6f36d 1412 @param This Indicates the calling context.\r
1413 @param ImageHandle The specified image handle.\r
162ed594 1414\r
57d6f36d 1415 @retval EFI_INVALID_PARAMETER Image handle is NULL.\r
1416 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.\r
162ed594 1417 @retval EFI_SUCCESS Image successfully unloaded.\r
1418\r
1419**/\r
28a00297 1420EFI_STATUS\r
1421EFIAPI\r
1422CoreUnloadImageEx (\r
1423 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1424 IN EFI_HANDLE ImageHandle\r
1425 )\r
28a00297 1426{\r
1427 return CoreUnloadImage (ImageHandle);\r
1428}\r