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