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