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