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