]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/Image.c
Added change log for r4251
[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
a0ae8996
LG
228 \r
229 //\r
230 // Set EFI memory type based on ImageType\r
231 //\r
232 switch (Image->ImageContext.ImageType) {\r
233 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
234 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;\r
235 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;\r
236 break;\r
237 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
238 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;\r
239 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;\r
240 break;\r
241 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
242 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:\r
243 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;\r
244 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;\r
245 break;\r
246 default:\r
247 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
248 return EFI_UNSUPPORTED;\r
249 }\r
28a00297 250\r
251 //\r
252 // Allocate memory of the correct memory type aligned on the required image boundry\r
253 //\r
254 DstBufAlocated = FALSE;\r
255 if (DstBuffer == 0) {\r
256 //\r
257 // Allocate Destination Buffer as caller did not pass it in\r
258 //\r
259\r
260 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
261 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
262 } else {\r
263 Size = (UINTN)Image->ImageContext.ImageSize;\r
264 }\r
265\r
266 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
267\r
268 //\r
269 // If the image relocations have not been stripped, then load at any address.\r
270 // Otherwise load at the address at which it was linked.\r
271 //\r
272 // Memory below 1MB should be treated reserved for CSM and there should be\r
273 // no modules whose preferred load addresses are below 1MB.\r
274 //\r
275 Status = EFI_OUT_OF_RESOURCES;\r
276 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
277 Status = CoreAllocatePages (\r
278 AllocateAddress,\r
279 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
280 Image->NumberOfPages,\r
281 &Image->ImageContext.ImageAddress\r
282 );\r
283 }\r
284 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
285 Status = CoreAllocatePages (\r
286 AllocateAnyPages,\r
287 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
288 Image->NumberOfPages,\r
289 &Image->ImageContext.ImageAddress\r
290 );\r
291 }\r
292 if (EFI_ERROR (Status)) {\r
293 return Status;\r
294 }\r
295 DstBufAlocated = TRUE;\r
296 } else {\r
297 //\r
298 // Caller provided the destination buffer\r
299 //\r
300\r
301 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
302 //\r
303 // If the image relocations were stripped, and the caller provided a\r
304 // destination buffer address that does not match the address that the\r
305 // image is linked at, then the image cannot be loaded.\r
306 //\r
307 return EFI_INVALID_PARAMETER;\r
308 }\r
309\r
310 if (Image->NumberOfPages != 0 &&\r
311 Image->NumberOfPages <\r
312 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
313 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
314 return EFI_BUFFER_TOO_SMALL;\r
315 }\r
316\r
317 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
318 Image->ImageContext.ImageAddress = DstBuffer;\r
319 }\r
320\r
321 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
322 Image->ImageContext.ImageAddress =\r
323 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
324 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
325\r
326 //\r
327 // Load the image from the file into the allocated memory\r
328 //\r
3d7b0992 329 Status = PeCoffLoaderLoadImage (&Image->ImageContext);\r
28a00297 330 if (EFI_ERROR (Status)) {\r
331 goto Done;\r
332 }\r
333\r
334 //\r
335 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
336 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
337 // relocation is done by the Runtime AP.\r
338 //\r
339 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
340 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
341 Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
342 if (Image->ImageContext.FixupData == NULL) {\r
343 Status = EFI_OUT_OF_RESOURCES;\r
344 goto Done;\r
345 }\r
346 }\r
347 }\r
348\r
349 //\r
350 // Relocate the image in memory\r
351 //\r
3d7b0992 352 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);\r
28a00297 353 if (EFI_ERROR (Status)) {\r
354 goto Done;\r
355 }\r
356\r
357 //\r
358 // Flush the Instruction Cache\r
359 //\r
360 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
361\r
362 //\r
363 // Copy the machine type from the context to the image private data. This\r
364 // is needed during image unload to know if we should call an EBC protocol\r
365 // to unload the image.\r
366 //\r
367 Image->Machine = Image->ImageContext.Machine;\r
368\r
369 //\r
370 // Get the image entry point. If it's an EBC image, then call into the\r
371 // interpreter to create a thunk for the entry point and use the returned\r
372 // value for the entry point.\r
373 //\r
374 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
375 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
376 //\r
377 // Locate the EBC interpreter protocol\r
378 //\r
379 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
380 if (EFI_ERROR(Status)) {\r
381 goto Done;\r
382 }\r
383\r
384 //\r
385 // Register a callback for flushing the instruction cache so that created\r
386 // thunks can be flushed.\r
387 //\r
388 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
389 if (EFI_ERROR(Status)) {\r
390 goto Done;\r
391 }\r
392\r
393 //\r
394 // Create a thunk for the image's entry point. This will be the new\r
395 // entry point for the image.\r
396 //\r
397 Status = Image->Ebc->CreateThunk (\r
398 Image->Ebc,\r
399 Image->Handle,\r
400 (VOID *)(UINTN)Image->ImageContext.EntryPoint,\r
401 (VOID **)&Image->EntryPoint\r
402 );\r
403 if (EFI_ERROR(Status)) {\r
404 goto Done;\r
405 }\r
406 }\r
407\r
408 //\r
409 // Fill in the image information for the Loaded Image Protocol\r
410 //\r
411 Image->Type = Image->ImageContext.ImageType;\r
412 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
413 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
414 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
415 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
416 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
417 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
418 //\r
419 // Make a list off all the RT images so we can let the RT AP know about them.\r
420 //\r
421 Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
422 if (Image->RuntimeData == NULL) {\r
423 goto Done;\r
424 }\r
425 Image->RuntimeData->ImageBase = Image->Info.ImageBase;\r
426 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);\r
427 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
428 Image->RuntimeData->Handle = Image->Handle;\r
429 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
430 }\r
431 }\r
432\r
433 //\r
434 // Fill in the entry point of the image if it is available\r
435 //\r
436 if (EntryPoint != NULL) {\r
437 *EntryPoint = Image->ImageContext.EntryPoint;\r
438 }\r
439\r
440 //\r
441 // Print the load address and the PDB file name if it is available\r
442 //\r
443\r
444 DEBUG_CODE_BEGIN ();\r
445\r
446 UINTN Index;\r
447 UINTN StartIndex;\r
448 CHAR8 EfiFileName[256];\r
449\r
450 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
451 if (Image->ImageContext.PdbPointer != NULL) {\r
452 StartIndex = 0;\r
453 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
454 if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
455 StartIndex = Index + 1;\r
456 }\r
457 }\r
458 //\r
459 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
460 //\r
461 for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
462 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
463 if (EfiFileName[Index] == 0) {\r
464 EfiFileName[Index] = '.';\r
465 }\r
466 if (EfiFileName[Index] == '.') {\r
467 EfiFileName[Index + 1] = 'e';\r
468 EfiFileName[Index + 2] = 'f';\r
469 EfiFileName[Index + 3] = 'i';\r
470 EfiFileName[Index + 4] = 0;\r
471 break;\r
472 }\r
473 }\r
474 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
475 }\r
476 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
477\r
478 DEBUG_CODE_END ();\r
479\r
480 return EFI_SUCCESS;\r
481\r
482Done:\r
483\r
484 //\r
485 // Free memory.\r
486 //\r
487\r
488 if (DstBufAlocated) {\r
489 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
490 }\r
491\r
492 if (Image->ImageContext.FixupData != NULL) {\r
493 CoreFreePool (Image->ImageContext.FixupData);\r
494 }\r
495\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
539STATIC\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
599 SecurityStatus = EFI_SUCCESS;\r
600\r
601 ASSERT (gEfiCurrentTpl < 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
85658066 669 Image->DeviceHandleDevicePath = CoreDuplicateDevicePath (HandleFilePath);\r
28a00297 670 }\r
671\r
672 //\r
673 // Initialize the fields for an internal driver\r
674 //\r
675 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
676 Image->Info.SystemTable = gDxeCoreST;\r
677 Image->Info.DeviceHandle = DeviceHandle;\r
678 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
679 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);\r
680 Image->Info.ParentHandle = ParentImageHandle;\r
681\r
85658066 682\r
28a00297 683 if (NumberOfPages != NULL) {\r
684 Image->NumberOfPages = *NumberOfPages ;\r
685 } else {\r
686 Image->NumberOfPages = 0 ;\r
687 }\r
688\r
689 //\r
690 // Install the protocol interfaces for this image\r
691 // don't fire notifications yet\r
692 //\r
693 Status = CoreInstallProtocolInterfaceNotify (\r
694 &Image->Handle,\r
695 &gEfiLoadedImageProtocolGuid,\r
696 EFI_NATIVE_INTERFACE,\r
697 &Image->Info,\r
698 FALSE\r
699 );\r
700 if (EFI_ERROR (Status)) {\r
701 goto Done;\r
702 }\r
703\r
704 //\r
705 // Load the image. If EntryPoint is Null, it will not be set.\r
706 //\r
707 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);\r
708 if (EFI_ERROR (Status)) {\r
709 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
710 if (NumberOfPages != NULL) {\r
711 *NumberOfPages = Image->NumberOfPages;\r
712 }\r
713 }\r
714 goto Done;\r
715 }\r
716\r
717 //\r
718 // Register the image in the Debug Image Info Table if the attribute is set\r
719 //\r
720 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
721 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
722 }\r
723\r
724 //\r
725 //Reinstall loaded image protocol to fire any notifications\r
726 //\r
727 Status = CoreReinstallProtocolInterface (\r
728 Image->Handle,\r
729 &gEfiLoadedImageProtocolGuid,\r
730 &Image->Info,\r
731 &Image->Info\r
732 );\r
733 if (EFI_ERROR (Status)) {\r
734 goto Done;\r
735 }\r
736\r
737\r
738 //\r
739 // Success. Return the image handle\r
740 //\r
741 *ImageHandle = Image->Handle;\r
742\r
743Done:\r
744 //\r
745 // All done accessing the source file\r
746 // If we allocated the Source buffer, free it\r
747 //\r
748 if (FHand.FreeBuffer) {\r
749 CoreFreePool (FHand.Source);\r
750 }\r
751\r
752 //\r
753 // There was an error. If there's an Image structure, free it\r
754 //\r
755 if (EFI_ERROR (Status)) {\r
756 if (Image != NULL) {\r
757 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
758 *ImageHandle = NULL;\r
759 }\r
760 } else if (EFI_ERROR (SecurityStatus)) {\r
761 Status = SecurityStatus;\r
762 }\r
763\r
764 return Status;\r
765}\r
766\r
767\r
768\r
769EFI_STATUS\r
770EFIAPI\r
771CoreLoadImage (\r
772 IN BOOLEAN BootPolicy,\r
773 IN EFI_HANDLE ParentImageHandle,\r
774 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
775 IN VOID *SourceBuffer OPTIONAL,\r
776 IN UINTN SourceSize,\r
777 OUT EFI_HANDLE *ImageHandle\r
778 )\r
779/*++\r
780\r
781Routine Description:\r
782\r
783 Loads an EFI image into memory and returns a handle to the image.\r
784\r
785Arguments:\r
786\r
787 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
788 and that the boot manager is attempting to load FilePath as a boot selection.\r
789 ParentImageHandle - The caller's image handle.\r
790 FilePath - The specific file path from which the image is loaded.\r
791 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
792 the image to be loaded.\r
793 SourceSize - The size in bytes of SourceBuffer.\r
794 ImageHandle - Pointer to the returned image handle that is created when the image\r
795 is successfully loaded.\r
796\r
797Returns:\r
798\r
799 EFI_SUCCESS - The image was loaded into memory.\r
800 EFI_NOT_FOUND - The FilePath was not found.\r
801 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
802 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
803 parsed to locate the proper protocol for loading the file.\r
804 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
805--*/\r
806{\r
807 EFI_STATUS Status;\r
808\r
809 PERF_START (NULL, "LoadImage", NULL, 0);\r
810\r
811 Status = CoreLoadImageCommon (\r
812 BootPolicy,\r
813 ParentImageHandle,\r
814 FilePath,\r
815 SourceBuffer,\r
816 SourceSize,\r
817 (EFI_PHYSICAL_ADDRESS)NULL,\r
818 NULL,\r
819 ImageHandle,\r
820 NULL,\r
821 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
822 );\r
823\r
824 PERF_END (NULL, "LoadImage", NULL, 0);\r
825\r
826 return Status;\r
827}\r
828\r
829\r
830EFI_STATUS\r
831EFIAPI\r
832CoreLoadImageEx (\r
833 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
834 IN EFI_HANDLE ParentImageHandle,\r
835 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
836 IN VOID *SourceBuffer OPTIONAL,\r
837 IN UINTN SourceSize,\r
838 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
839 OUT UINTN *NumberOfPages OPTIONAL,\r
840 OUT EFI_HANDLE *ImageHandle,\r
841 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
842 IN UINT32 Attribute\r
843 )\r
844/*++\r
845\r
846Routine Description:\r
847\r
848 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
849\r
850Arguments:\r
851\r
852 This - Calling context\r
853 ParentImageHandle - The caller's image handle.\r
854 FilePath - The specific file path from which the image is loaded.\r
855 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
856 the image to be loaded.\r
857 SourceSize - The size in bytes of SourceBuffer.\r
858 DstBuffer - The buffer to store the image.\r
859 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.\r
860 For output, specifies the actual space size needed.\r
861 ImageHandle - Image handle for output.\r
862 EntryPoint - Image entry point for output.\r
863 Attribute - The bit mask of attributes to set for the load PE image.\r
864\r
865Returns:\r
866\r
867 EFI_SUCCESS - The image was loaded into memory.\r
868 EFI_NOT_FOUND - The FilePath was not found.\r
869 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
870 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
871 parsed to locate the proper protocol for loading the file.\r
872 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
873--*/\r
874{\r
875 return CoreLoadImageCommon (\r
876 TRUE,\r
877 ParentImageHandle,\r
878 FilePath,\r
879 SourceBuffer,\r
880 SourceSize,\r
881 DstBuffer,\r
882 NumberOfPages,\r
883 ImageHandle,\r
884 EntryPoint,\r
885 Attribute\r
886 );\r
887}\r
888\r
889\r
890\r
891\r
892EFI_STATUS\r
893EFIAPI\r
894CoreStartImage (\r
895 IN EFI_HANDLE ImageHandle,\r
896 OUT UINTN *ExitDataSize,\r
897 OUT CHAR16 **ExitData OPTIONAL\r
898 )\r
899/*++\r
900\r
901Routine Description:\r
902\r
903 Transfer control to a loaded image's entry point.\r
904\r
905Arguments:\r
906\r
907 ImageHandle - Handle of image to be started.\r
908\r
909 ExitDataSize - Pointer of the size to ExitData\r
910\r
911 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated\r
912 Unicode string, optionally followed by additional binary data. The string\r
913 is a description that the caller may use to further indicate the reason for\r
914 the image's exit.\r
915\r
916Returns:\r
917\r
918 EFI_INVALID_PARAMETER - Invalid parameter\r
919\r
920 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
921\r
922 EFI_SUCCESS - Successfully transfer control to the image's entry point.\r
923\r
924--*/\r
925{\r
926 EFI_STATUS Status;\r
927 LOADED_IMAGE_PRIVATE_DATA *Image;\r
928 LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
929 UINT64 HandleDatabaseKey;\r
930 UINTN SetJumpFlag;\r
931\r
932 Image = CoreLoadedImageInfo (ImageHandle);\r
933 if (Image == NULL_HANDLE || Image->Started) {\r
934 return EFI_INVALID_PARAMETER;\r
935 }\r
936\r
937 //\r
938 // Don't profile Objects or invalid start requests\r
939 //\r
940 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
941\r
942\r
943 //\r
944 // Push the current start image context, and\r
945 // link the current image to the head. This is the\r
946 // only image that can call Exit()\r
947 //\r
948 HandleDatabaseKey = CoreGetHandleDatabaseKey ();\r
949 LastImage = mCurrentImage;\r
950 mCurrentImage = Image;\r
951 Image->Tpl = gEfiCurrentTpl;\r
952\r
953 //\r
954 // Set long jump for Exit() support\r
955 // JumpContext must be aligned on a CPU specific boundary.\r
956 // Overallocate the buffer and force the required alignment\r
957 //\r
958 Image->JumpBuffer = CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
959 if (Image->JumpBuffer == NULL) {\r
960 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
961 return EFI_OUT_OF_RESOURCES;\r
962 }\r
963 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
964\r
965 SetJumpFlag = SetJump (Image->JumpContext);\r
966 //\r
967 // The initial call to SetJump() must always return 0.\r
968 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
969 //\r
970 if (!SetJumpFlag) {\r
971 //\r
972 // Call the image's entry point\r
973 //\r
974 Image->Started = TRUE;\r
975 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);\r
976\r
977 //\r
978 // Add some debug information if the image returned with error.\r
979 // This make the user aware and check if the driver image have already released\r
980 // all the resource in this situation.\r
981 //\r
982 DEBUG_CODE_BEGIN ();\r
983 if (EFI_ERROR (Image->Status)) {\r
984 DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
985 }\r
986 DEBUG_CODE_END ();\r
987\r
988 //\r
989 // If the image returns, exit it through Exit()\r
990 //\r
991 CoreExit (ImageHandle, Image->Status, 0, NULL);\r
992 }\r
993\r
994 //\r
995 // Image has completed. Verify the tpl is the same\r
996 //\r
997 ASSERT (Image->Tpl == gEfiCurrentTpl);\r
998 CoreRestoreTpl (Image->Tpl);\r
999\r
1000 CoreFreePool (Image->JumpBuffer);\r
1001\r
1002 //\r
1003 // Pop the current start image context\r
1004 //\r
1005 mCurrentImage = LastImage;\r
1006\r
1007 //\r
1008 // Go connect any handles that were created or modified while the image executed.\r
1009 //\r
1010 CoreConnectHandlesByKey (HandleDatabaseKey);\r
1011\r
1012 //\r
1013 // Handle the image's returned ExitData\r
1014 //\r
1015 DEBUG_CODE_BEGIN ();\r
1016 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
1017\r
1018 DEBUG (\r
1019 (EFI_D_LOAD,\r
1020 "StartImage: ExitDataSize %d, ExitData %x",\r
1021 Image->ExitDataSize,\r
1022 Image->ExitData)\r
1023 );\r
1024 if (Image->ExitData != NULL) {\r
1025 DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));\r
1026 }\r
1027 DEBUG ((EFI_D_LOAD, "\n"));\r
1028 }\r
1029 DEBUG_CODE_END ();\r
1030\r
1031 //\r
1032 // Return the exit data to the caller\r
1033 //\r
1034 if (ExitData != NULL && ExitDataSize != NULL) {\r
1035 *ExitDataSize = Image->ExitDataSize;\r
1036 *ExitData = Image->ExitData;\r
1037 } else {\r
1038 //\r
1039 // Caller doesn't want the exit data, free it\r
1040 //\r
1041 CoreFreePool (Image->ExitData);\r
1042 Image->ExitData = NULL;\r
1043 }\r
1044\r
1045 //\r
1046 // Save the Status because Image will get destroyed if it is unloaded.\r
1047 //\r
1048 Status = Image->Status;\r
1049\r
1050 //\r
1051 // If the image returned an error, or if the image is an application\r
1052 // unload it\r
1053 //\r
1054 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1055 CoreUnloadAndCloseImage (Image, TRUE);\r
1056 }\r
1057\r
1058 //\r
1059 // Done\r
1060 //\r
1061 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
1062 return Status;\r
1063}\r
1064\r
1065\r
1066VOID\r
1067CoreUnloadAndCloseImage (\r
1068 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
1069 IN BOOLEAN FreePage\r
1070 )\r
1071/*++\r
1072\r
1073Routine Description:\r
1074\r
1075 Unloads EFI image from memory.\r
1076\r
1077Arguments:\r
1078\r
1079 Image - EFI image\r
1080 FreePage - Free allocated pages\r
1081\r
1082Returns:\r
1083\r
1084 None\r
1085\r
1086--*/\r
1087{\r
1088 EFI_STATUS Status;\r
1089 UINTN HandleCount;\r
1090 EFI_HANDLE *HandleBuffer;\r
1091 UINTN HandleIndex;\r
1092 EFI_GUID **ProtocolGuidArray;\r
1093 UINTN ArrayCount;\r
1094 UINTN ProtocolIndex;\r
1095 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
1096 UINTN OpenInfoCount;\r
1097 UINTN OpenInfoIndex;\r
1098\r
1099 if (Image->Ebc != NULL) {\r
1100 //\r
1101 // If EBC protocol exists we must perform cleanups for this image.\r
1102 //\r
1103 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
1104 }\r
1105\r
1106 //\r
1107 // Unload image, free Image->ImageContext->ModHandle\r
1108 //\r
3d7b0992 1109 PeCoffLoaderUnloadImage (&Image->ImageContext);\r
28a00297 1110\r
1111 //\r
1112 // Free our references to the image handle\r
1113 //\r
1114 if (Image->Handle != NULL_HANDLE) {\r
1115\r
1116 Status = CoreLocateHandleBuffer (\r
1117 AllHandles,\r
1118 NULL,\r
1119 NULL,\r
1120 &HandleCount,\r
1121 &HandleBuffer\r
1122 );\r
1123 if (!EFI_ERROR (Status)) {\r
1124 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
1125 Status = CoreProtocolsPerHandle (\r
1126 HandleBuffer[HandleIndex],\r
1127 &ProtocolGuidArray,\r
1128 &ArrayCount\r
1129 );\r
1130 if (!EFI_ERROR (Status)) {\r
1131 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
1132 Status = CoreOpenProtocolInformation (\r
1133 HandleBuffer[HandleIndex],\r
1134 ProtocolGuidArray[ProtocolIndex],\r
1135 &OpenInfo,\r
1136 &OpenInfoCount\r
1137 );\r
1138 if (!EFI_ERROR (Status)) {\r
1139 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
1140 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
1141 Status = CoreCloseProtocol (\r
1142 HandleBuffer[HandleIndex],\r
1143 ProtocolGuidArray[ProtocolIndex],\r
1144 Image->Handle,\r
1145 OpenInfo[OpenInfoIndex].ControllerHandle\r
1146 );\r
1147 }\r
1148 }\r
1149 if (OpenInfo != NULL) {\r
1150 CoreFreePool(OpenInfo);\r
1151 }\r
1152 }\r
1153 }\r
1154 if (ProtocolGuidArray != NULL) {\r
1155 CoreFreePool(ProtocolGuidArray);\r
1156 }\r
1157 }\r
1158 }\r
1159 if (HandleBuffer != NULL) {\r
1160 CoreFreePool (HandleBuffer);\r
1161 }\r
1162 }\r
1163\r
1164 CoreRemoveDebugImageInfoEntry (Image->Handle);\r
1165\r
1166 Status = CoreUninstallProtocolInterface (\r
1167 Image->Handle,\r
1168 &gEfiLoadedImageProtocolGuid,\r
1169 &Image->Info\r
1170 );\r
1171 }\r
1172\r
1173 if (Image->RuntimeData != NULL) {\r
1174 if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
1175 //\r
1176 // Remove the Image from the Runtime Image list as we are about to Free it!\r
1177 //\r
1178 RemoveEntryList (&Image->RuntimeData->Link);\r
1179 }\r
1180 CoreFreePool (Image->RuntimeData);\r
1181 }\r
1182\r
1183 //\r
1184 // Free the Image from memory\r
1185 //\r
1186 if ((Image->ImageBasePage != 0) && FreePage) {\r
1187 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
1188 }\r
1189\r
1190 //\r
1191 // Done with the Image structure\r
1192 //\r
1193 if (Image->Info.FilePath != NULL) {\r
1194 CoreFreePool (Image->Info.FilePath);\r
1195 }\r
1196\r
85658066 1197 if (Image->DeviceHandleDevicePath != NULL) {\r
1198 CoreFreePool (Image->DeviceHandleDevicePath);\r
1199 }\r
1200\r
28a00297 1201 if (Image->FixupData != NULL) {\r
1202 CoreFreePool (Image->FixupData);\r
1203 }\r
1204\r
1205 CoreFreePool (Image);\r
1206}\r
1207\r
1208\r
1209\r
1210EFI_STATUS\r
1211EFIAPI\r
1212CoreExit (\r
1213 IN EFI_HANDLE ImageHandle,\r
1214 IN EFI_STATUS Status,\r
1215 IN UINTN ExitDataSize,\r
1216 IN CHAR16 *ExitData OPTIONAL\r
1217 )\r
1218/*++\r
1219\r
1220Routine Description:\r
1221\r
1222 Terminates the currently loaded EFI image and returns control to boot services.\r
1223\r
1224Arguments:\r
1225\r
1226 ImageHandle - Handle that identifies the image. This parameter is passed to the image\r
1227 on entry.\r
1228 Status - The image's exit code.\r
1229 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is\r
1230 EFI_SUCCESS.\r
1231 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,\r
1232 optionally followed by additional binary data. The string is a\r
1233 description that the caller may use to further indicate the reason for\r
1234 the image's exit.\r
1235\r
1236Returns:\r
1237\r
1238 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.\r
1239\r
1240 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.\r
1241\r
1242 EFI_ACCESS_DENIED - Should never reach there.\r
1243\r
1244 EFI_OUT_OF_RESOURCES - Could not allocate pool\r
1245\r
1246--*/\r
1247{\r
1248 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1249 EFI_TPL OldTpl;\r
1250\r
1251 //\r
1252 // Prevent possible reentrance to this function\r
1253 // for the same ImageHandle\r
1254 // \r
1255 OldTpl = CoreRaiseTpl (TPL_NOTIFY); \r
1256 \r
1257 Image = CoreLoadedImageInfo (ImageHandle);\r
1258 if (Image == NULL_HANDLE) {\r
1259 Status = EFI_INVALID_PARAMETER;\r
1260 goto Done;\r
1261 }\r
1262\r
1263 if (!Image->Started) {\r
1264 //\r
1265 // The image has not been started so just free its resources\r
1266 //\r
1267 CoreUnloadAndCloseImage (Image, TRUE);\r
1268 Status = EFI_SUCCESS;\r
1269 goto Done;\r
1270 }\r
1271\r
1272 //\r
1273 // Image has been started, verify this image can exit\r
1274 //\r
1275 if (Image != mCurrentImage) {\r
1276 DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));\r
1277 Status = EFI_INVALID_PARAMETER;\r
1278 goto Done;\r
1279 }\r
1280\r
1281 //\r
1282 // Set status\r
1283 //\r
1284 Image->Status = Status;\r
1285\r
1286 //\r
1287 // If there's ExitData info, move it\r
1288 //\r
1289 if (ExitData != NULL) {\r
1290 Image->ExitDataSize = ExitDataSize;\r
1291 Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);\r
1292 if (Image->ExitData == NULL) {\r
1293 Status = EFI_OUT_OF_RESOURCES;\r
1294 goto Done;\r
1295 }\r
1296 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
1297 }\r
1298\r
1299 CoreRestoreTpl (OldTpl);\r
1300 //\r
1301 // return to StartImage\r
1302 //\r
1303 LongJump (Image->JumpContext, (UINTN)-1);\r
1304\r
1305 //\r
1306 // If we return from LongJump, then it is an error\r
1307 //\r
1308 ASSERT (FALSE);\r
1309 Status = EFI_ACCESS_DENIED;\r
1310Done:\r
1311 CoreRestoreTpl (OldTpl);\r
1312 return Status;\r
1313}\r
1314\r
1315\r
1316\r
1317EFI_STATUS\r
1318EFIAPI\r
1319CoreUnloadImage (\r
1320 IN EFI_HANDLE ImageHandle\r
1321 )\r
1322/*++\r
1323\r
1324Routine Description:\r
1325\r
1326 Unloads an image.\r
1327\r
1328Arguments:\r
1329\r
1330 ImageHandle - Handle that identifies the image to be unloaded.\r
1331\r
1332Returns:\r
1333\r
1334 EFI_SUCCESS - The image has been unloaded.\r
1335 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.\r
1336 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.\r
1337\r
1338--*/\r
1339{\r
1340 EFI_STATUS Status;\r
1341 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1342 EFI_TPL OldTpl;\r
1343\r
1344 //\r
1345 // Prevent possible reentrance to this function\r
1346 // for the same ImageHandle\r
1347 // \r
1348 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1349 \r
1350 Image = CoreLoadedImageInfo (ImageHandle);\r
1351 if (Image == NULL ) {\r
1352 //\r
1353 // The image handle is not valid\r
1354 //\r
1355 Status = EFI_INVALID_PARAMETER;\r
1356 goto Done;\r
1357 }\r
1358\r
1359 if (Image->Started) {\r
1360 //\r
1361 // The image has been started, request it to unload.\r
1362 //\r
1363 Status = EFI_UNSUPPORTED;\r
1364 if (Image->Info.Unload != NULL) {\r
1365 Status = Image->Info.Unload (ImageHandle);\r
1366 }\r
1367\r
1368 } else {\r
1369 //\r
1370 // This Image hasn't been started, thus it can be unloaded\r
1371 //\r
1372 Status = EFI_SUCCESS;\r
1373 }\r
1374\r
1375\r
1376 if (!EFI_ERROR (Status)) {\r
1377 //\r
1378 // if the Image was not started or Unloaded O.K. then clean up\r
1379 //\r
1380 CoreUnloadAndCloseImage (Image, TRUE);\r
1381 }\r
1382\r
1383Done:\r
1384 CoreRestoreTpl (OldTpl);\r
1385 return Status;\r
1386}\r
1387\r
1388\r
1389EFI_STATUS\r
1390EFIAPI\r
1391CoreUnloadImageEx (\r
1392 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1393 IN EFI_HANDLE ImageHandle\r
1394 )\r
1395/*++\r
1396\r
1397Routine Description:\r
1398\r
1399 Unload the specified image.\r
1400\r
1401Arguments:\r
1402\r
1403 This - Indicates the calling context.\r
1404\r
1405 ImageHandle - The specified image handle.\r
1406\r
1407Returns:\r
1408\r
1409 EFI_INVALID_PARAMETER - Image handle is NULL.\r
1410\r
1411 EFI_UNSUPPORTED - Attempt to unload an unsupported image.\r
1412\r
1413 EFI_SUCCESS - Image successfully unloaded.\r
1414\r
1415--*/\r
1416{\r
1417 return CoreUnloadImage (ImageHandle);\r
1418}\r