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