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