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