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