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