]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/Image.c
1. CoreOpenImageFile(): FilePath should be IN OUT.
[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
e98cd821
LG
449 \r
450 if (Image->ImageContext.Machine != IMAGE_FILE_MACHINE_IA64) {\r
451 DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
452 "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
453 (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
454 (VOID *)(UINTN)Image->ImageContext.EntryPoint));\r
455 } else {\r
456 //\r
457 // For IPF Image, the real entry point should be print.\r
458 // \r
459 DEBUG ((EFI_D_INFO | EFI_D_LOAD, \r
460 "Loading driver at 0x%10p EntryPoint=0x%10p ", \r
461 (VOID *)(UINTN)Image->ImageContext.ImageAddress, \r
462 (VOID *)(UINTN)(*(UINT64 *)(UINTN)Image->ImageContext.EntryPoint)));\r
463 }\r
464 \r
465 //\r
466 // Print Module Name by Pdb file path\r
467 //\r
28a00297 468 if (Image->ImageContext.PdbPointer != NULL) {\r
469 StartIndex = 0;\r
470 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
471 if (Image->ImageContext.PdbPointer[Index] == '\\') {\r
472 StartIndex = Index + 1;\r
473 }\r
474 }\r
475 //\r
476 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
477 //\r
478 for (Index = 0; Index < sizeof (EfiFileName); Index++) {\r
479 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
480 if (EfiFileName[Index] == 0) {\r
481 EfiFileName[Index] = '.';\r
482 }\r
483 if (EfiFileName[Index] == '.') {\r
484 EfiFileName[Index + 1] = 'e';\r
485 EfiFileName[Index + 2] = 'f';\r
486 EfiFileName[Index + 3] = 'i';\r
487 EfiFileName[Index + 4] = 0;\r
488 break;\r
489 }\r
490 }\r
491 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
492 }\r
493 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
494\r
495 DEBUG_CODE_END ();\r
496\r
497 return EFI_SUCCESS;\r
498\r
499Done:\r
500\r
501 //\r
502 // Free memory.\r
503 //\r
504\r
505 if (DstBufAlocated) {\r
506 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
507 }\r
508\r
509 if (Image->ImageContext.FixupData != NULL) {\r
510 CoreFreePool (Image->ImageContext.FixupData);\r
511 }\r
512\r
513 return Status;\r
514}\r
515\r
516\r
517LOADED_IMAGE_PRIVATE_DATA *\r
518CoreLoadedImageInfo (\r
519 IN EFI_HANDLE ImageHandle\r
520 )\r
521/*++\r
522\r
523Routine Description:\r
524\r
525 Get the image's private data from its handle.\r
526\r
527Arguments:\r
528\r
529 ImageHandle - The image handle\r
530\r
531Returns:\r
532\r
533 Return the image private data associated with ImageHandle.\r
534\r
535--*/\r
536{\r
537 EFI_STATUS Status;\r
538 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
539 LOADED_IMAGE_PRIVATE_DATA *Image;\r
540\r
541 Status = CoreHandleProtocol (\r
542 ImageHandle,\r
543 &gEfiLoadedImageProtocolGuid,\r
544 (VOID **)&LoadedImage\r
545 );\r
546 if (!EFI_ERROR (Status)) {\r
547 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
548 } else {\r
549 DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle));\r
550 Image = NULL;\r
551 }\r
552\r
553 return Image;\r
554}\r
555\r
556STATIC\r
557EFI_STATUS\r
558CoreLoadImageCommon (\r
559 IN BOOLEAN BootPolicy,\r
560 IN EFI_HANDLE ParentImageHandle,\r
561 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
562 IN VOID *SourceBuffer OPTIONAL,\r
563 IN UINTN SourceSize,\r
564 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
565 IN OUT UINTN *NumberOfPages OPTIONAL,\r
566 OUT EFI_HANDLE *ImageHandle,\r
567 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
568 IN UINT32 Attribute\r
569 )\r
570/*++\r
571\r
572Routine Description:\r
573\r
574 Loads an EFI image into memory and returns a handle to the image.\r
575\r
576Arguments:\r
577\r
578 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
579 and that the boot manager is attempting to load FilePath as a boot selection.\r
580 ParentImageHandle - The caller's image handle.\r
581 FilePath - The specific file path from which the image is loaded.\r
582 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
583 the image to be loaded.\r
584 SourceSize - The size in bytes of SourceBuffer.\r
585 DstBuffer - The buffer to store the image\r
586 NumberOfPages - If not NULL, a pointer to the image's page number, if this number\r
587 is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain\r
588 the required number.\r
589 ImageHandle - Pointer to the returned image handle that is created when the image\r
590 is successfully loaded.\r
591 EntryPoint - A pointer to the entry point\r
592 Attribute - The bit mask of attributes to set for the load PE image\r
593\r
594Returns:\r
595\r
596 EFI_SUCCESS - The image was loaded into memory.\r
597 EFI_NOT_FOUND - The FilePath was not found.\r
598 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
599 EFI_BUFFER_TOO_SMALL - The buffer is too small\r
600 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
601 parsed to locate the proper protocol for loading the file.\r
602 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
603--*/\r
604{\r
605 LOADED_IMAGE_PRIVATE_DATA *Image;\r
606 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
607 IMAGE_FILE_HANDLE FHand;\r
608 EFI_STATUS Status;\r
609 EFI_STATUS SecurityStatus;\r
610 EFI_HANDLE DeviceHandle;\r
611 UINT32 AuthenticationStatus;\r
612 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
613 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
614 UINTN FilePathSize;\r
615\r
616 SecurityStatus = EFI_SUCCESS;\r
617\r
618 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
619 ParentImage = NULL;\r
620\r
621 //\r
622 // The caller must pass in a valid ParentImageHandle\r
623 //\r
624 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
625 return EFI_INVALID_PARAMETER;\r
626 }\r
627\r
628 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
629 if (ParentImage == NULL) {\r
630 DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
631 return EFI_INVALID_PARAMETER;\r
632 }\r
633\r
634 //\r
635 // Get simple read access to the source file\r
636 //\r
637 OriginalFilePath = FilePath;\r
638 Status = CoreOpenImageFile (\r
639 BootPolicy,\r
640 SourceBuffer,\r
641 SourceSize,\r
cfe9de52 642 &FilePath,\r
28a00297 643 &DeviceHandle,\r
644 &FHand,\r
645 &AuthenticationStatus\r
646 );\r
647 if (Status == EFI_ALREADY_STARTED) {\r
648 Image = NULL;\r
649 goto Done;\r
650 } else if (EFI_ERROR (Status)) {\r
651 return Status;\r
652 }\r
653\r
654 //\r
655 // Verify the Authentication Status through the Security Architectural Protocol\r
656 //\r
657 if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
658 SecurityStatus = gSecurity->FileAuthenticationState (\r
659 gSecurity,\r
660 AuthenticationStatus,\r
661 OriginalFilePath\r
662 );\r
663 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
664 Status = SecurityStatus;\r
665 Image = NULL;\r
666 goto Done;\r
667 }\r
668 }\r
669\r
670\r
671 //\r
672 // Allocate a new image structure\r
673 //\r
674 Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
675 if (Image == NULL) {\r
676 return EFI_OUT_OF_RESOURCES;\r
677 }\r
678\r
679 //\r
680 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
681 //\r
cfe9de52 682 FilePath = OriginalFilePath;\r
28a00297 683 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
684 if (!EFI_ERROR (Status)) {\r
685 FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
686 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize );\r
85658066 687 Image->DeviceHandleDevicePath = CoreDuplicateDevicePath (HandleFilePath);\r
28a00297 688 }\r
689\r
690 //\r
691 // Initialize the fields for an internal driver\r
692 //\r
693 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
694 Image->Info.SystemTable = gDxeCoreST;\r
695 Image->Info.DeviceHandle = DeviceHandle;\r
696 Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION;\r
697 Image->Info.FilePath = CoreDuplicateDevicePath (FilePath);\r
698 Image->Info.ParentHandle = ParentImageHandle;\r
699\r
85658066 700\r
28a00297 701 if (NumberOfPages != NULL) {\r
702 Image->NumberOfPages = *NumberOfPages ;\r
703 } else {\r
704 Image->NumberOfPages = 0 ;\r
705 }\r
706\r
707 //\r
708 // Install the protocol interfaces for this image\r
709 // don't fire notifications yet\r
710 //\r
711 Status = CoreInstallProtocolInterfaceNotify (\r
712 &Image->Handle,\r
713 &gEfiLoadedImageProtocolGuid,\r
714 EFI_NATIVE_INTERFACE,\r
715 &Image->Info,\r
716 FALSE\r
717 );\r
718 if (EFI_ERROR (Status)) {\r
719 goto Done;\r
720 }\r
721\r
722 //\r
723 // Load the image. If EntryPoint is Null, it will not be set.\r
724 //\r
725 Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute);\r
726 if (EFI_ERROR (Status)) {\r
727 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
728 if (NumberOfPages != NULL) {\r
729 *NumberOfPages = Image->NumberOfPages;\r
730 }\r
731 }\r
732 goto Done;\r
733 }\r
734\r
735 //\r
736 // Register the image in the Debug Image Info Table if the attribute is set\r
737 //\r
738 if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) {\r
739 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
740 }\r
741\r
742 //\r
743 //Reinstall loaded image protocol to fire any notifications\r
744 //\r
745 Status = CoreReinstallProtocolInterface (\r
746 Image->Handle,\r
747 &gEfiLoadedImageProtocolGuid,\r
748 &Image->Info,\r
749 &Image->Info\r
750 );\r
751 if (EFI_ERROR (Status)) {\r
752 goto Done;\r
753 }\r
754\r
755\r
756 //\r
757 // Success. Return the image handle\r
758 //\r
759 *ImageHandle = Image->Handle;\r
760\r
761Done:\r
762 //\r
763 // All done accessing the source file\r
764 // If we allocated the Source buffer, free it\r
765 //\r
766 if (FHand.FreeBuffer) {\r
767 CoreFreePool (FHand.Source);\r
768 }\r
769\r
770 //\r
771 // There was an error. If there's an Image structure, free it\r
772 //\r
773 if (EFI_ERROR (Status)) {\r
774 if (Image != NULL) {\r
775 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
776 *ImageHandle = NULL;\r
777 }\r
778 } else if (EFI_ERROR (SecurityStatus)) {\r
779 Status = SecurityStatus;\r
780 }\r
781\r
782 return Status;\r
783}\r
784\r
785\r
786\r
787EFI_STATUS\r
788EFIAPI\r
789CoreLoadImage (\r
790 IN BOOLEAN BootPolicy,\r
791 IN EFI_HANDLE ParentImageHandle,\r
792 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
793 IN VOID *SourceBuffer OPTIONAL,\r
794 IN UINTN SourceSize,\r
795 OUT EFI_HANDLE *ImageHandle\r
796 )\r
797/*++\r
798\r
799Routine Description:\r
800\r
801 Loads an EFI image into memory and returns a handle to the image.\r
802\r
803Arguments:\r
804\r
805 BootPolicy - If TRUE, indicates that the request originates from the boot manager,\r
806 and that the boot manager is attempting to load FilePath as a boot selection.\r
807 ParentImageHandle - The caller's image handle.\r
808 FilePath - The specific file path from which the image is loaded.\r
809 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
810 the image to be loaded.\r
811 SourceSize - The size in bytes of SourceBuffer.\r
812 ImageHandle - Pointer to the returned image handle that is created when the image\r
813 is successfully loaded.\r
814\r
815Returns:\r
816\r
817 EFI_SUCCESS - The image was loaded into memory.\r
818 EFI_NOT_FOUND - The FilePath was not found.\r
819 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
820 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
821 parsed to locate the proper protocol for loading the file.\r
822 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
823--*/\r
824{\r
825 EFI_STATUS Status;\r
826\r
827 PERF_START (NULL, "LoadImage", NULL, 0);\r
828\r
829 Status = CoreLoadImageCommon (\r
830 BootPolicy,\r
831 ParentImageHandle,\r
832 FilePath,\r
833 SourceBuffer,\r
834 SourceSize,\r
835 (EFI_PHYSICAL_ADDRESS)NULL,\r
836 NULL,\r
837 ImageHandle,\r
838 NULL,\r
839 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
840 );\r
841\r
842 PERF_END (NULL, "LoadImage", NULL, 0);\r
843\r
844 return Status;\r
845}\r
846\r
847\r
848EFI_STATUS\r
849EFIAPI\r
850CoreLoadImageEx (\r
851 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
852 IN EFI_HANDLE ParentImageHandle,\r
853 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
854 IN VOID *SourceBuffer OPTIONAL,\r
855 IN UINTN SourceSize,\r
856 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
857 OUT UINTN *NumberOfPages OPTIONAL,\r
858 OUT EFI_HANDLE *ImageHandle,\r
859 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
860 IN UINT32 Attribute\r
861 )\r
862/*++\r
863\r
864Routine Description:\r
865\r
866 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
867\r
868Arguments:\r
869\r
870 This - Calling context\r
871 ParentImageHandle - The caller's image handle.\r
872 FilePath - The specific file path from which the image is loaded.\r
873 SourceBuffer - If not NULL, a pointer to the memory location containing a copy of\r
874 the image to be loaded.\r
875 SourceSize - The size in bytes of SourceBuffer.\r
876 DstBuffer - The buffer to store the image.\r
877 NumberOfPages - For input, specifies the space size of the image by caller if not NULL.\r
878 For output, specifies the actual space size needed.\r
879 ImageHandle - Image handle for output.\r
880 EntryPoint - Image entry point for output.\r
881 Attribute - The bit mask of attributes to set for the load PE image.\r
882\r
883Returns:\r
884\r
885 EFI_SUCCESS - The image was loaded into memory.\r
886 EFI_NOT_FOUND - The FilePath was not found.\r
887 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
888 EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be\r
889 parsed to locate the proper protocol for loading the file.\r
890 EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources.\r
891--*/\r
892{\r
893 return CoreLoadImageCommon (\r
894 TRUE,\r
895 ParentImageHandle,\r
896 FilePath,\r
897 SourceBuffer,\r
898 SourceSize,\r
899 DstBuffer,\r
900 NumberOfPages,\r
901 ImageHandle,\r
902 EntryPoint,\r
903 Attribute\r
904 );\r
905}\r
906\r
907\r
908\r
909\r
910EFI_STATUS\r
911EFIAPI\r
912CoreStartImage (\r
913 IN EFI_HANDLE ImageHandle,\r
914 OUT UINTN *ExitDataSize,\r
915 OUT CHAR16 **ExitData OPTIONAL\r
916 )\r
917/*++\r
918\r
919Routine Description:\r
920\r
921 Transfer control to a loaded image's entry point.\r
922\r
923Arguments:\r
924\r
925 ImageHandle - Handle of image to be started.\r
926\r
927 ExitDataSize - Pointer of the size to ExitData\r
928\r
929 ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated\r
930 Unicode string, optionally followed by additional binary data. The string\r
931 is a description that the caller may use to further indicate the reason for\r
932 the image's exit.\r
933\r
934Returns:\r
935\r
936 EFI_INVALID_PARAMETER - Invalid parameter\r
937\r
938 EFI_OUT_OF_RESOURCES - No enough buffer to allocate\r
939\r
940 EFI_SUCCESS - Successfully transfer control to the image's entry point.\r
941\r
942--*/\r
943{\r
944 EFI_STATUS Status;\r
945 LOADED_IMAGE_PRIVATE_DATA *Image;\r
946 LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
947 UINT64 HandleDatabaseKey;\r
948 UINTN SetJumpFlag;\r
949\r
950 Image = CoreLoadedImageInfo (ImageHandle);\r
951 if (Image == NULL_HANDLE || Image->Started) {\r
952 return EFI_INVALID_PARAMETER;\r
953 }\r
954\r
955 //\r
956 // Don't profile Objects or invalid start requests\r
957 //\r
958 PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
959\r
960\r
961 //\r
962 // Push the current start image context, and\r
963 // link the current image to the head. This is the\r
964 // only image that can call Exit()\r
965 //\r
966 HandleDatabaseKey = CoreGetHandleDatabaseKey ();\r
967 LastImage = mCurrentImage;\r
968 mCurrentImage = Image;\r
969 Image->Tpl = gEfiCurrentTpl;\r
970\r
971 //\r
972 // Set long jump for Exit() support\r
973 // JumpContext must be aligned on a CPU specific boundary.\r
974 // Overallocate the buffer and force the required alignment\r
975 //\r
976 Image->JumpBuffer = CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
977 if (Image->JumpBuffer == NULL) {\r
978 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
979 return EFI_OUT_OF_RESOURCES;\r
980 }\r
981 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
982\r
983 SetJumpFlag = SetJump (Image->JumpContext);\r
984 //\r
985 // The initial call to SetJump() must always return 0.\r
986 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
987 //\r
988 if (!SetJumpFlag) {\r
989 //\r
990 // Call the image's entry point\r
991 //\r
992 Image->Started = TRUE;\r
993 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);\r
994\r
995 //\r
996 // Add some debug information if the image returned with error.\r
997 // This make the user aware and check if the driver image have already released\r
998 // all the resource in this situation.\r
999 //\r
1000 DEBUG_CODE_BEGIN ();\r
1001 if (EFI_ERROR (Image->Status)) {\r
1002 DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
1003 }\r
1004 DEBUG_CODE_END ();\r
1005\r
1006 //\r
1007 // If the image returns, exit it through Exit()\r
1008 //\r
1009 CoreExit (ImageHandle, Image->Status, 0, NULL);\r
1010 }\r
1011\r
1012 //\r
1013 // Image has completed. Verify the tpl is the same\r
1014 //\r
1015 ASSERT (Image->Tpl == gEfiCurrentTpl);\r
1016 CoreRestoreTpl (Image->Tpl);\r
1017\r
1018 CoreFreePool (Image->JumpBuffer);\r
1019\r
1020 //\r
1021 // Pop the current start image context\r
1022 //\r
1023 mCurrentImage = LastImage;\r
1024\r
1025 //\r
1026 // Go connect any handles that were created or modified while the image executed.\r
1027 //\r
1028 CoreConnectHandlesByKey (HandleDatabaseKey);\r
1029\r
1030 //\r
1031 // Handle the image's returned ExitData\r
1032 //\r
1033 DEBUG_CODE_BEGIN ();\r
1034 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
1035\r
1036 DEBUG (\r
1037 (EFI_D_LOAD,\r
1038 "StartImage: ExitDataSize %d, ExitData %x",\r
1039 Image->ExitDataSize,\r
1040 Image->ExitData)\r
1041 );\r
1042 if (Image->ExitData != NULL) {\r
1043 DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData));\r
1044 }\r
1045 DEBUG ((EFI_D_LOAD, "\n"));\r
1046 }\r
1047 DEBUG_CODE_END ();\r
1048\r
1049 //\r
1050 // Return the exit data to the caller\r
1051 //\r
1052 if (ExitData != NULL && ExitDataSize != NULL) {\r
1053 *ExitDataSize = Image->ExitDataSize;\r
1054 *ExitData = Image->ExitData;\r
1055 } else {\r
1056 //\r
1057 // Caller doesn't want the exit data, free it\r
1058 //\r
1059 CoreFreePool (Image->ExitData);\r
1060 Image->ExitData = NULL;\r
1061 }\r
1062\r
1063 //\r
1064 // Save the Status because Image will get destroyed if it is unloaded.\r
1065 //\r
1066 Status = Image->Status;\r
1067\r
1068 //\r
1069 // If the image returned an error, or if the image is an application\r
1070 // unload it\r
1071 //\r
1072 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1073 CoreUnloadAndCloseImage (Image, TRUE);\r
1074 }\r
1075\r
1076 //\r
1077 // Done\r
1078 //\r
1079 PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
1080 return Status;\r
1081}\r
1082\r
1083\r
1084VOID\r
1085CoreUnloadAndCloseImage (\r
1086 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
1087 IN BOOLEAN FreePage\r
1088 )\r
1089/*++\r
1090\r
1091Routine Description:\r
1092\r
1093 Unloads EFI image from memory.\r
1094\r
1095Arguments:\r
1096\r
1097 Image - EFI image\r
1098 FreePage - Free allocated pages\r
1099\r
1100Returns:\r
1101\r
1102 None\r
1103\r
1104--*/\r
1105{\r
1106 EFI_STATUS Status;\r
1107 UINTN HandleCount;\r
1108 EFI_HANDLE *HandleBuffer;\r
1109 UINTN HandleIndex;\r
1110 EFI_GUID **ProtocolGuidArray;\r
1111 UINTN ArrayCount;\r
1112 UINTN ProtocolIndex;\r
1113 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
1114 UINTN OpenInfoCount;\r
1115 UINTN OpenInfoIndex;\r
1116\r
1117 if (Image->Ebc != NULL) {\r
1118 //\r
1119 // If EBC protocol exists we must perform cleanups for this image.\r
1120 //\r
1121 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
1122 }\r
1123\r
1124 //\r
1125 // Unload image, free Image->ImageContext->ModHandle\r
1126 //\r
3d7b0992 1127 PeCoffLoaderUnloadImage (&Image->ImageContext);\r
28a00297 1128\r
1129 //\r
1130 // Free our references to the image handle\r
1131 //\r
1132 if (Image->Handle != NULL_HANDLE) {\r
1133\r
1134 Status = CoreLocateHandleBuffer (\r
1135 AllHandles,\r
1136 NULL,\r
1137 NULL,\r
1138 &HandleCount,\r
1139 &HandleBuffer\r
1140 );\r
1141 if (!EFI_ERROR (Status)) {\r
1142 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
1143 Status = CoreProtocolsPerHandle (\r
1144 HandleBuffer[HandleIndex],\r
1145 &ProtocolGuidArray,\r
1146 &ArrayCount\r
1147 );\r
1148 if (!EFI_ERROR (Status)) {\r
1149 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
1150 Status = CoreOpenProtocolInformation (\r
1151 HandleBuffer[HandleIndex],\r
1152 ProtocolGuidArray[ProtocolIndex],\r
1153 &OpenInfo,\r
1154 &OpenInfoCount\r
1155 );\r
1156 if (!EFI_ERROR (Status)) {\r
1157 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
1158 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
1159 Status = CoreCloseProtocol (\r
1160 HandleBuffer[HandleIndex],\r
1161 ProtocolGuidArray[ProtocolIndex],\r
1162 Image->Handle,\r
1163 OpenInfo[OpenInfoIndex].ControllerHandle\r
1164 );\r
1165 }\r
1166 }\r
1167 if (OpenInfo != NULL) {\r
1168 CoreFreePool(OpenInfo);\r
1169 }\r
1170 }\r
1171 }\r
1172 if (ProtocolGuidArray != NULL) {\r
1173 CoreFreePool(ProtocolGuidArray);\r
1174 }\r
1175 }\r
1176 }\r
1177 if (HandleBuffer != NULL) {\r
1178 CoreFreePool (HandleBuffer);\r
1179 }\r
1180 }\r
1181\r
1182 CoreRemoveDebugImageInfoEntry (Image->Handle);\r
1183\r
1184 Status = CoreUninstallProtocolInterface (\r
1185 Image->Handle,\r
1186 &gEfiLoadedImageProtocolGuid,\r
1187 &Image->Info\r
1188 );\r
1189 }\r
1190\r
1191 if (Image->RuntimeData != NULL) {\r
1192 if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
1193 //\r
1194 // Remove the Image from the Runtime Image list as we are about to Free it!\r
1195 //\r
1196 RemoveEntryList (&Image->RuntimeData->Link);\r
1197 }\r
1198 CoreFreePool (Image->RuntimeData);\r
1199 }\r
1200\r
1201 //\r
1202 // Free the Image from memory\r
1203 //\r
1204 if ((Image->ImageBasePage != 0) && FreePage) {\r
1205 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
1206 }\r
1207\r
1208 //\r
1209 // Done with the Image structure\r
1210 //\r
1211 if (Image->Info.FilePath != NULL) {\r
1212 CoreFreePool (Image->Info.FilePath);\r
1213 }\r
1214\r
85658066 1215 if (Image->DeviceHandleDevicePath != NULL) {\r
1216 CoreFreePool (Image->DeviceHandleDevicePath);\r
1217 }\r
1218\r
28a00297 1219 if (Image->FixupData != NULL) {\r
1220 CoreFreePool (Image->FixupData);\r
1221 }\r
1222\r
1223 CoreFreePool (Image);\r
1224}\r
1225\r
1226\r
1227\r
1228EFI_STATUS\r
1229EFIAPI\r
1230CoreExit (\r
1231 IN EFI_HANDLE ImageHandle,\r
1232 IN EFI_STATUS Status,\r
1233 IN UINTN ExitDataSize,\r
1234 IN CHAR16 *ExitData OPTIONAL\r
1235 )\r
1236/*++\r
1237\r
1238Routine Description:\r
1239\r
1240 Terminates the currently loaded EFI image and returns control to boot services.\r
1241\r
1242Arguments:\r
1243\r
1244 ImageHandle - Handle that identifies the image. This parameter is passed to the image\r
1245 on entry.\r
1246 Status - The image's exit code.\r
1247 ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is\r
1248 EFI_SUCCESS.\r
1249 ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string,\r
1250 optionally followed by additional binary data. The string is a\r
1251 description that the caller may use to further indicate the reason for\r
1252 the image's exit.\r
1253\r
1254Returns:\r
1255\r
1256 EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image.\r
1257\r
1258 EFI_SUCCESS - Successfully terminates the currently loaded EFI image.\r
1259\r
1260 EFI_ACCESS_DENIED - Should never reach there.\r
1261\r
1262 EFI_OUT_OF_RESOURCES - Could not allocate pool\r
1263\r
1264--*/\r
1265{\r
1266 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1267 EFI_TPL OldTpl;\r
1268\r
1269 //\r
1270 // Prevent possible reentrance to this function\r
1271 // for the same ImageHandle\r
1272 // \r
1273 OldTpl = CoreRaiseTpl (TPL_NOTIFY); \r
1274 \r
1275 Image = CoreLoadedImageInfo (ImageHandle);\r
1276 if (Image == NULL_HANDLE) {\r
1277 Status = EFI_INVALID_PARAMETER;\r
1278 goto Done;\r
1279 }\r
1280\r
1281 if (!Image->Started) {\r
1282 //\r
1283 // The image has not been started so just free its resources\r
1284 //\r
1285 CoreUnloadAndCloseImage (Image, TRUE);\r
1286 Status = EFI_SUCCESS;\r
1287 goto Done;\r
1288 }\r
1289\r
1290 //\r
1291 // Image has been started, verify this image can exit\r
1292 //\r
1293 if (Image != mCurrentImage) {\r
1294 DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));\r
1295 Status = EFI_INVALID_PARAMETER;\r
1296 goto Done;\r
1297 }\r
1298\r
1299 //\r
1300 // Set status\r
1301 //\r
1302 Image->Status = Status;\r
1303\r
1304 //\r
1305 // If there's ExitData info, move it\r
1306 //\r
1307 if (ExitData != NULL) {\r
1308 Image->ExitDataSize = ExitDataSize;\r
1309 Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);\r
1310 if (Image->ExitData == NULL) {\r
1311 Status = EFI_OUT_OF_RESOURCES;\r
1312 goto Done;\r
1313 }\r
1314 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
1315 }\r
1316\r
1317 CoreRestoreTpl (OldTpl);\r
1318 //\r
1319 // return to StartImage\r
1320 //\r
1321 LongJump (Image->JumpContext, (UINTN)-1);\r
1322\r
1323 //\r
1324 // If we return from LongJump, then it is an error\r
1325 //\r
1326 ASSERT (FALSE);\r
1327 Status = EFI_ACCESS_DENIED;\r
1328Done:\r
1329 CoreRestoreTpl (OldTpl);\r
1330 return Status;\r
1331}\r
1332\r
1333\r
1334\r
1335EFI_STATUS\r
1336EFIAPI\r
1337CoreUnloadImage (\r
1338 IN EFI_HANDLE ImageHandle\r
1339 )\r
1340/*++\r
1341\r
1342Routine Description:\r
1343\r
1344 Unloads an image.\r
1345\r
1346Arguments:\r
1347\r
1348 ImageHandle - Handle that identifies the image to be unloaded.\r
1349\r
1350Returns:\r
1351\r
1352 EFI_SUCCESS - The image has been unloaded.\r
1353 EFI_UNSUPPORTED - The image has been sarted, and does not support unload.\r
1354 EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle.\r
1355\r
1356--*/\r
1357{\r
1358 EFI_STATUS Status;\r
1359 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1360 EFI_TPL OldTpl;\r
1361\r
1362 //\r
1363 // Prevent possible reentrance to this function\r
1364 // for the same ImageHandle\r
1365 // \r
1366 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1367 \r
1368 Image = CoreLoadedImageInfo (ImageHandle);\r
1369 if (Image == NULL ) {\r
1370 //\r
1371 // The image handle is not valid\r
1372 //\r
1373 Status = EFI_INVALID_PARAMETER;\r
1374 goto Done;\r
1375 }\r
1376\r
1377 if (Image->Started) {\r
1378 //\r
1379 // The image has been started, request it to unload.\r
1380 //\r
1381 Status = EFI_UNSUPPORTED;\r
1382 if (Image->Info.Unload != NULL) {\r
1383 Status = Image->Info.Unload (ImageHandle);\r
1384 }\r
1385\r
1386 } else {\r
1387 //\r
1388 // This Image hasn't been started, thus it can be unloaded\r
1389 //\r
1390 Status = EFI_SUCCESS;\r
1391 }\r
1392\r
1393\r
1394 if (!EFI_ERROR (Status)) {\r
1395 //\r
1396 // if the Image was not started or Unloaded O.K. then clean up\r
1397 //\r
1398 CoreUnloadAndCloseImage (Image, TRUE);\r
1399 }\r
1400\r
1401Done:\r
1402 CoreRestoreTpl (OldTpl);\r
1403 return Status;\r
1404}\r
1405\r
1406\r
1407EFI_STATUS\r
1408EFIAPI\r
1409CoreUnloadImageEx (\r
1410 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1411 IN EFI_HANDLE ImageHandle\r
1412 )\r
1413/*++\r
1414\r
1415Routine Description:\r
1416\r
1417 Unload the specified image.\r
1418\r
1419Arguments:\r
1420\r
1421 This - Indicates the calling context.\r
1422\r
1423 ImageHandle - The specified image handle.\r
1424\r
1425Returns:\r
1426\r
1427 EFI_INVALID_PARAMETER - Image handle is NULL.\r
1428\r
1429 EFI_UNSUPPORTED - Attempt to unload an unsupported image.\r
1430\r
1431 EFI_SUCCESS - Image successfully unloaded.\r
1432\r
1433--*/\r
1434{\r
1435 return CoreUnloadImage (ImageHandle);\r
1436}\r