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