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