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