]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
CommitLineData
23c98c94 1/** @file\r
504214c4
LG
2 Core image handling services to load and unload PeImage.\r
3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
28a00297 6\r
504214c4 7**/\r
28a00297 8\r
9c4ac31c 9#include "DxeMain.h"\r
ec90508b 10#include "Image.h"\r
11\r
28a00297 12//\r
13// Module Globals\r
14//\r
28a00297 15LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL;\r
16\r
023c0fec 17LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = {\r
18 LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE,\r
19 NULL,\r
20 {\r
21 CoreLoadImageEx,\r
22 CoreUnloadImageEx\r
23 }\r
24};\r
25\r
28a00297 26\r
27//\r
28// This code is needed to build the Image handle for the DXE Core\r
29//\r
30LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {\r
31 LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature\r
32 NULL, // Image handle\r
33 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type\r
34 TRUE, // If entrypoint has been called\r
35 NULL, // EntryPoint\r
36 {\r
37 EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision\r
38 NULL, // Parent handle\r
39 NULL, // System handle\r
40\r
41 NULL, // Device handle\r
42 NULL, // File path\r
43 NULL, // Reserved\r
44\r
45 0, // LoadOptionsSize\r
46 NULL, // LoadOptions\r
47\r
48 NULL, // ImageBase\r
49 0, // ImageSize\r
50 EfiBootServicesCode, // ImageCodeType\r
51 EfiBootServicesData // ImageDataType\r
52 },\r
53 (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage\r
54 0, // NumberOfPages\r
55 NULL, // FixupData\r
56 0, // Tpl\r
57 EFI_SUCCESS, // Status\r
58 0, // ExitDataSize\r
59 NULL, // ExitData\r
60 NULL, // JumpBuffer\r
61 NULL, // JumpContext\r
62 0, // Machine\r
63 NULL, // Ebc\r
64 NULL, // RuntimeData\r
ba39e316 65 NULL // LoadedImageDevicePath\r
28a00297 66};\r
54ea99a7 67//\r
68// The field is define for Loading modules at fixed address feature to tracker the PEI code\r
69// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page\r
d1102dba 70// available or not.\r
54ea99a7 71//\r
72GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL;\r
28a00297 73\r
60c0073f
LG
74typedef struct {\r
75 UINT16 MachineType;\r
76 CHAR16 *MachineTypeName;\r
77} MACHINE_TYPE_INFO;\r
78\r
79//\r
80// EBC machine is not listed in this table, because EBC is in the default supported scopes of other machine type.\r
81//\r
82GLOBAL_REMOVE_IF_UNREFERENCED MACHINE_TYPE_INFO mMachineTypeInfo[] = {\r
83 {EFI_IMAGE_MACHINE_IA32, L"IA32"},\r
84 {EFI_IMAGE_MACHINE_IA64, L"IA64"},\r
85 {EFI_IMAGE_MACHINE_X64, L"X64"},\r
9bca00be
AB
86 {EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, L"ARM"},\r
87 {EFI_IMAGE_MACHINE_AARCH64, L"AARCH64"}\r
60c0073f
LG
88};\r
89\r
90UINT16 mDxeCoreImageMachineType = 0;\r
91\r
92/**\r
93 Return machine type name.\r
94\r
95 @param MachineType The machine type\r
96\r
97 @return machine type name\r
98**/\r
99CHAR16 *\r
100GetMachineTypeName (\r
101 UINT16 MachineType\r
102 )\r
103{\r
104 UINTN Index;\r
d1102dba 105\r
60c0073f
LG
106 for (Index = 0; Index < sizeof(mMachineTypeInfo)/sizeof(mMachineTypeInfo[0]); Index++) {\r
107 if (mMachineTypeInfo[Index].MachineType == MachineType) {\r
108 return mMachineTypeInfo[Index].MachineTypeName;\r
109 }\r
110 }\r
111\r
112 return L"<Unknown>";\r
113}\r
114\r
162ed594 115/**\r
28a00297 116 Add the Image Services to EFI Boot Services Table and install the protocol\r
117 interfaces for this image.\r
118\r
57d6f36d 119 @param HobStart The HOB to initialize\r
28a00297 120\r
162ed594 121 @return Status code.\r
28a00297 122\r
162ed594 123**/\r
124EFI_STATUS\r
125CoreInitializeImageServices (\r
126 IN VOID *HobStart\r
127 )\r
28a00297 128{\r
129 EFI_STATUS Status;\r
130 LOADED_IMAGE_PRIVATE_DATA *Image;\r
131 EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress;\r
132 UINT64 DxeCoreImageLength;\r
133 VOID *DxeCoreEntryPoint;\r
134 EFI_PEI_HOB_POINTERS DxeCoreHob;\r
d1102dba 135\r
28a00297 136 //\r
137 // Searching for image hob\r
138 //\r
139 DxeCoreHob.Raw = HobStart;\r
140 while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) {\r
141 if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {\r
142 //\r
143 // Find Dxe Core HOB\r
144 //\r
145 break;\r
146 }\r
147 DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob);\r
148 }\r
149 ASSERT (DxeCoreHob.Raw != NULL);\r
150\r
151 DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;\r
152 DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;\r
153 DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint;\r
154 gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName;\r
d1102dba 155\r
28a00297 156 //\r
157 // Initialize the fields for an internal driver\r
158 //\r
159 Image = &mCorePrivateImage;\r
160\r
161 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint;\r
162 Image->ImageBasePage = DxeCoreImageBaseAddress;\r
163 Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength)));\r
164 Image->Tpl = gEfiCurrentTpl;\r
165 Image->Info.SystemTable = gDxeCoreST;\r
166 Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress;\r
167 Image->Info.ImageSize = DxeCoreImageLength;\r
168\r
169 //\r
170 // Install the protocol interfaces for this image\r
171 //\r
172 Status = CoreInstallProtocolInterface (\r
173 &Image->Handle,\r
174 &gEfiLoadedImageProtocolGuid,\r
175 EFI_NATIVE_INTERFACE,\r
176 &Image->Info\r
177 );\r
178 ASSERT_EFI_ERROR (Status);\r
179\r
180 mCurrentImage = Image;\r
181\r
182 //\r
183 // Fill in DXE globals\r
184 //\r
60c0073f 185 mDxeCoreImageMachineType = PeCoffLoaderGetMachineType (Image->Info.ImageBase);\r
28a00297 186 gDxeCoreImageHandle = Image->Handle;\r
187 gDxeCoreLoadedImage = &Image->Info;\r
188\r
6320fa42
LG
189 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
190 //\r
191 // Export DXE Core PE Loader functionality for backward compatibility.\r
192 //\r
193 Status = CoreInstallProtocolInterface (\r
d0d41b52 194 &mLoadPe32PrivateData.Handle,\r
195 &gEfiLoadPeImageProtocolGuid,\r
196 EFI_NATIVE_INTERFACE,\r
197 &mLoadPe32PrivateData.Pe32Image\r
198 );\r
6320fa42
LG
199 }\r
200\r
d0e92aad
JY
201 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
202\r
6320fa42 203 return Status;\r
28a00297 204}\r
205\r
7748df3d
LG
206/**\r
207 Read image file (specified by UserHandle) into user specified buffer with specified offset\r
208 and length.\r
209\r
210 @param UserHandle Image file handle\r
211 @param Offset Offset to the source file\r
212 @param ReadSize For input, pointer of size to read; For output,\r
213 pointer of size actually read.\r
214 @param Buffer Buffer to write into\r
215\r
216 @retval EFI_SUCCESS Successfully read the specified part of file\r
217 into buffer.\r
218\r
219**/\r
220EFI_STATUS\r
221EFIAPI\r
222CoreReadImageFile (\r
223 IN VOID *UserHandle,\r
224 IN UINTN Offset,\r
225 IN OUT UINTN *ReadSize,\r
226 OUT VOID *Buffer\r
227 )\r
228{\r
229 UINTN EndPosition;\r
230 IMAGE_FILE_HANDLE *FHand;\r
231\r
28186d45
ED
232 if (UserHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
233 return EFI_INVALID_PARAMETER;\r
234 }\r
235\r
236 if (MAX_ADDRESS - Offset < *ReadSize) {\r
237 return EFI_INVALID_PARAMETER;\r
238 }\r
239\r
7748df3d
LG
240 FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
241 ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
242\r
243 //\r
244 // Move data from our local copy of the file\r
245 //\r
246 EndPosition = Offset + *ReadSize;\r
247 if (EndPosition > FHand->SourceSize) {\r
248 *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
249 }\r
250 if (Offset >= FHand->SourceSize) {\r
251 *ReadSize = 0;\r
252 }\r
253\r
254 CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\r
255 return EFI_SUCCESS;\r
256}\r
54ea99a7 257/**\r
2048c585
GM
258 To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If\r
259 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
d1102dba
LG
260 The function is only invoked when load modules at fixed address feature is enabled.\r
261\r
2048c585 262 @param ImageBase The base address the image will be loaded at.\r
54ea99a7 263 @param ImageSize The size of the image\r
d1102dba 264\r
54ea99a7 265 @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
266 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
267**/\r
268EFI_STATUS\r
269CheckAndMarkFixLoadingMemoryUsageBitMap (\r
270 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
271 IN UINTN ImageSize\r
272 )\r
273{\r
274 UINT32 DxeCodePageNumber;\r
d1102dba 275 UINT64 DxeCodeSize;\r
54ea99a7 276 EFI_PHYSICAL_ADDRESS DxeCodeBase;\r
277 UINTN BaseOffsetPageNumber;\r
278 UINTN TopOffsetPageNumber;\r
279 UINTN Index;\r
280 //\r
281 // The DXE code range includes RuntimeCodePage range and Boot time code range.\r
d1102dba 282 //\r
54ea99a7 283 DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);\r
284 DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);\r
285 DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);\r
286 DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;\r
d1102dba 287\r
54ea99a7 288 //\r
d1102dba 289 // If the memory usage bit map is not initialized, do it. Every bit in the array\r
54ea99a7 290 // indicate the status of the corresponding memory page, available or not\r
d1102dba 291 //\r
54ea99a7 292 if (mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
293 mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));\r
294 }\r
295 //\r
296 // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
297 //\r
298 if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {\r
299 return EFI_NOT_FOUND;\r
300 }\r
301 //\r
302 // Test the memory range for loading the image in the DXE code range.\r
303 //\r
304 if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||\r
305 DxeCodeBase > ImageBase) {\r
d1102dba
LG
306 return EFI_NOT_FOUND;\r
307 }\r
54ea99a7 308 //\r
309 // Test if the memory is avalaible or not.\r
d1102dba 310 //\r
16f69227
HW
311 BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));\r
312 TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));\r
54ea99a7 313 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
314 if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
315 //\r
316 // This page is already used.\r
317 //\r
d1102dba 318 return EFI_NOT_FOUND;\r
54ea99a7 319 }\r
320 }\r
d1102dba 321\r
54ea99a7 322 //\r
323 // Being here means the memory range is available. So mark the bits for the memory range\r
d1102dba 324 //\r
54ea99a7 325 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
326 mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
327 }\r
d1102dba 328 return EFI_SUCCESS;\r
54ea99a7 329}\r
330/**\r
331\r
2048c585 332 Get the fixed loading address from image header assigned by build tool. This function only be called\r
54ea99a7 333 when Loading module at Fixed address feature enabled.\r
162ed594 334\r
54ea99a7 335 @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
336 image that needs to be examined by this function.\r
337 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
2048c585 338 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.\r
54ea99a7 339\r
340**/\r
341EFI_STATUS\r
342GetPeCoffImageFixLoadingAssignedAddress(\r
343 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
344 )\r
345{\r
346 UINTN SectionHeaderOffset;\r
347 EFI_STATUS Status;\r
348 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
349 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
350 UINT16 Index;\r
351 UINTN Size;\r
352 UINT16 NumberOfSections;\r
353 IMAGE_FILE_HANDLE *Handle;\r
354 UINT64 ValueInSectionHeader;\r
d1102dba 355\r
54ea99a7 356\r
357 Status = EFI_NOT_FOUND;\r
d1102dba 358\r
54ea99a7 359 //\r
360 // Get PeHeader pointer\r
361 //\r
362 Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;\r
363 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);\r
16f69227
HW
364 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
365 sizeof (UINT32) +\r
366 sizeof (EFI_IMAGE_FILE_HEADER) +\r
367 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
54ea99a7 368 NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
369\r
370 //\r
371 // Get base address from the first section header that doesn't point to code section.\r
372 //\r
373 for (Index = 0; Index < NumberOfSections; Index++) {\r
374 //\r
375 // Read section header from file\r
376 //\r
377 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
378 Status = ImageContext->ImageRead (\r
379 ImageContext->Handle,\r
380 SectionHeaderOffset,\r
381 &Size,\r
382 &SectionHeader\r
383 );\r
384 if (EFI_ERROR (Status)) {\r
385 return Status;\r
386 }\r
16bacc07
SZ
387 if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {\r
388 return EFI_NOT_FOUND;\r
389 }\r
390\r
54ea99a7 391 Status = EFI_NOT_FOUND;\r
d1102dba 392\r
54ea99a7 393 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
394 //\r
395 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
d1102dba
LG
396 // that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an\r
397 // assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations\r
2048c585 398 // & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fields should be set to Zero\r
54ea99a7 399 //\r
400 ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
401 if (ValueInSectionHeader != 0) {\r
402 //\r
d1102dba 403 // When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext\r
54ea99a7 404 // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset\r
405 // relative to top address\r
406 //\r
852081fc 407 if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {\r
d1102dba 408 ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)(INTN)ImageContext->ImageAddress;\r
54ea99a7 409 }\r
410 //\r
2048c585 411 // Check if the memory range is available.\r
54ea99a7 412 //\r
413 Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
414 }\r
d1102dba 415 break;\r
54ea99a7 416 }\r
417 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
418 }\r
852081fc 419 DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status = %r \n", (VOID *)(UINTN)(ImageContext->ImageAddress), Status));\r
54ea99a7 420 return Status;\r
421}\r
162ed594 422/**\r
423 Loads, relocates, and invokes a PE/COFF image\r
424\r
57d6f36d 425 @param BootPolicy If TRUE, indicates that the request originates\r
426 from the boot manager, and that the boot\r
427 manager is attempting to load FilePath as a\r
428 boot selection.\r
429 @param Pe32Handle The handle of PE32 image\r
430 @param Image PE image to be loaded\r
431 @param DstBuffer The buffer to store the image\r
432 @param EntryPoint A pointer to the entry point\r
433 @param Attribute The bit mask of attributes to set for the load\r
434 PE image\r
435\r
436 @retval EFI_SUCCESS The file was loaded, relocated, and invoked\r
437 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and\r
438 relocate the PE/COFF file\r
439 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 440 @retval EFI_BUFFER_TOO_SMALL Buffer for image is too small\r
441\r
442**/\r
28a00297 443EFI_STATUS\r
444CoreLoadPeImage (\r
57d6f36d 445 IN BOOLEAN BootPolicy,\r
28a00297 446 IN VOID *Pe32Handle,\r
447 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
448 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
449 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
450 IN UINT32 Attribute\r
451 )\r
28a00297 452{\r
822360ee
LG
453 EFI_STATUS Status;\r
454 BOOLEAN DstBufAlocated;\r
455 UINTN Size;\r
28a00297 456\r
457 ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
458\r
459 Image->ImageContext.Handle = Pe32Handle;\r
460 Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile;\r
461\r
462 //\r
463 // Get information about the image being loaded\r
464 //\r
3d7b0992 465 Status = PeCoffLoaderGetImageInfo (&Image->ImageContext);\r
28a00297 466 if (EFI_ERROR (Status)) {\r
467 return Status;\r
468 }\r
469\r
470 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
5fed8e34 471 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
472 //\r
473 // The PE/COFF loader can support loading image types that can be executed.\r
474 // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
475 //\r
f00237c1
LG
476 DEBUG ((EFI_D_ERROR, "Image type %s can't be loaded ", GetMachineTypeName(Image->ImageContext.Machine)));\r
477 DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));\r
5fed8e34 478 return EFI_UNSUPPORTED;\r
479 }\r
28a00297 480 }\r
57d6f36d 481\r
a0ae8996
LG
482 //\r
483 // Set EFI memory type based on ImageType\r
484 //\r
485 switch (Image->ImageContext.ImageType) {\r
486 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
487 Image->ImageContext.ImageCodeMemoryType = EfiLoaderCode;\r
488 Image->ImageContext.ImageDataMemoryType = EfiLoaderData;\r
489 break;\r
490 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
491 Image->ImageContext.ImageCodeMemoryType = EfiBootServicesCode;\r
492 Image->ImageContext.ImageDataMemoryType = EfiBootServicesData;\r
493 break;\r
494 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
495 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:\r
496 Image->ImageContext.ImageCodeMemoryType = EfiRuntimeServicesCode;\r
497 Image->ImageContext.ImageDataMemoryType = EfiRuntimeServicesData;\r
498 break;\r
499 default:\r
500 Image->ImageContext.ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;\r
501 return EFI_UNSUPPORTED;\r
502 }\r
28a00297 503\r
504 //\r
6393d9c8 505 // Allocate memory of the correct memory type aligned on the required image boundary\r
28a00297 506 //\r
507 DstBufAlocated = FALSE;\r
508 if (DstBuffer == 0) {\r
509 //\r
510 // Allocate Destination Buffer as caller did not pass it in\r
511 //\r
512\r
513 if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
514 Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment;\r
515 } else {\r
516 Size = (UINTN)Image->ImageContext.ImageSize;\r
517 }\r
518\r
519 Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size);\r
520\r
521 //\r
522 // If the image relocations have not been stripped, then load at any address.\r
523 // Otherwise load at the address at which it was linked.\r
524 //\r
525 // Memory below 1MB should be treated reserved for CSM and there should be\r
526 // no modules whose preferred load addresses are below 1MB.\r
527 //\r
528 Status = EFI_OUT_OF_RESOURCES;\r
54ea99a7 529 //\r
530 // If Loading Module At Fixed Address feature is enabled, the module should be loaded to\r
531 // a specified address.\r
532 //\r
852081fc 533 if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {\r
54ea99a7 534 Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));\r
535\r
536 if (EFI_ERROR (Status)) {\r
537 //\r
d1102dba
LG
538 // If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.\r
539 //\r
54ea99a7 540 DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));\r
d1102dba 541\r
54ea99a7 542 Status = CoreAllocatePages (\r
543 AllocateAnyPages,\r
544 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
545 Image->NumberOfPages,\r
546 &Image->ImageContext.ImageAddress\r
d1102dba
LG
547 );\r
548 }\r
54ea99a7 549 } else {\r
550 if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
551 Status = CoreAllocatePages (\r
552 AllocateAddress,\r
553 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
554 Image->NumberOfPages,\r
555 &Image->ImageContext.ImageAddress\r
556 );\r
557 }\r
558 if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
559 Status = CoreAllocatePages (\r
560 AllocateAnyPages,\r
561 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
562 Image->NumberOfPages,\r
563 &Image->ImageContext.ImageAddress\r
564 );\r
565 }\r
28a00297 566 }\r
567 if (EFI_ERROR (Status)) {\r
568 return Status;\r
569 }\r
570 DstBufAlocated = TRUE;\r
571 } else {\r
572 //\r
573 // Caller provided the destination buffer\r
574 //\r
575\r
576 if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) {\r
577 //\r
578 // If the image relocations were stripped, and the caller provided a\r
579 // destination buffer address that does not match the address that the\r
580 // image is linked at, then the image cannot be loaded.\r
581 //\r
582 return EFI_INVALID_PARAMETER;\r
583 }\r
584\r
585 if (Image->NumberOfPages != 0 &&\r
586 Image->NumberOfPages <\r
587 (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) {\r
588 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
589 return EFI_BUFFER_TOO_SMALL;\r
590 }\r
591\r
592 Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
593 Image->ImageContext.ImageAddress = DstBuffer;\r
594 }\r
595\r
596 Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
1046284d 597 if (!Image->ImageContext.IsTeImage) {\r
54ea99a7 598 Image->ImageContext.ImageAddress =\r
599 (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
600 ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
1046284d 601 }\r
28a00297 602\r
603 //\r
604 // Load the image from the file into the allocated memory\r
605 //\r
3d7b0992 606 Status = PeCoffLoaderLoadImage (&Image->ImageContext);\r
28a00297 607 if (EFI_ERROR (Status)) {\r
608 goto Done;\r
609 }\r
610\r
611 //\r
612 // If this is a Runtime Driver, then allocate memory for the FixupData that\r
613 // is used to relocate the image when SetVirtualAddressMap() is called. The\r
614 // relocation is done by the Runtime AP.\r
615 //\r
71f68914 616 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 617 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
9c4ac31c 618 Image->ImageContext.FixupData = AllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize));\r
28a00297 619 if (Image->ImageContext.FixupData == NULL) {\r
620 Status = EFI_OUT_OF_RESOURCES;\r
621 goto Done;\r
622 }\r
623 }\r
624 }\r
625\r
626 //\r
627 // Relocate the image in memory\r
628 //\r
3d7b0992 629 Status = PeCoffLoaderRelocateImage (&Image->ImageContext);\r
28a00297 630 if (EFI_ERROR (Status)) {\r
631 goto Done;\r
632 }\r
633\r
634 //\r
635 // Flush the Instruction Cache\r
636 //\r
637 InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize);\r
638\r
639 //\r
640 // Copy the machine type from the context to the image private data. This\r
641 // is needed during image unload to know if we should call an EBC protocol\r
642 // to unload the image.\r
643 //\r
644 Image->Machine = Image->ImageContext.Machine;\r
645\r
646 //\r
647 // Get the image entry point. If it's an EBC image, then call into the\r
648 // interpreter to create a thunk for the entry point and use the returned\r
649 // value for the entry point.\r
650 //\r
651 Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint;\r
652 if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) {\r
653 //\r
654 // Locate the EBC interpreter protocol\r
655 //\r
656 Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc);\r
d2fbaaab 657 if (EFI_ERROR(Status) || Image->Ebc == NULL) {\r
57d6f36d 658 DEBUG ((DEBUG_LOAD | DEBUG_ERROR, "CoreLoadPeImage: There is no EBC interpreter for an EBC image.\n"));\r
28a00297 659 goto Done;\r
660 }\r
661\r
662 //\r
663 // Register a callback for flushing the instruction cache so that created\r
664 // thunks can be flushed.\r
665 //\r
666 Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
667 if (EFI_ERROR(Status)) {\r
668 goto Done;\r
669 }\r
670\r
671 //\r
672 // Create a thunk for the image's entry point. This will be the new\r
673 // entry point for the image.\r
674 //\r
675 Status = Image->Ebc->CreateThunk (\r
676 Image->Ebc,\r
677 Image->Handle,\r
e94a9ff7 678 (VOID *)(UINTN) Image->ImageContext.EntryPoint,\r
679 (VOID **) &Image->EntryPoint\r
28a00297 680 );\r
681 if (EFI_ERROR(Status)) {\r
682 goto Done;\r
683 }\r
684 }\r
685\r
686 //\r
687 // Fill in the image information for the Loaded Image Protocol\r
688 //\r
689 Image->Type = Image->ImageContext.ImageType;\r
690 Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
691 Image->Info.ImageSize = Image->ImageContext.ImageSize;\r
692 Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
693 Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
71f68914 694 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) != 0) {\r
28a00297 695 if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
696 //\r
697 // Make a list off all the RT images so we can let the RT AP know about them.\r
698 //\r
9c4ac31c 699 Image->RuntimeData = AllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
28a00297 700 if (Image->RuntimeData == NULL) {\r
701 goto Done;\r
702 }\r
703 Image->RuntimeData->ImageBase = Image->Info.ImageBase;\r
704 Image->RuntimeData->ImageSize = (UINT64) (Image->Info.ImageSize);\r
705 Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
706 Image->RuntimeData->Handle = Image->Handle;\r
707 InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
03d486b2 708 InsertImageRecord (Image->RuntimeData);\r
28a00297 709 }\r
710 }\r
711\r
712 //\r
713 // Fill in the entry point of the image if it is available\r
714 //\r
715 if (EntryPoint != NULL) {\r
716 *EntryPoint = Image->ImageContext.EntryPoint;\r
717 }\r
718\r
719 //\r
720 // Print the load address and the PDB file name if it is available\r
721 //\r
722\r
723 DEBUG_CODE_BEGIN ();\r
724\r
725 UINTN Index;\r
726 UINTN StartIndex;\r
727 CHAR8 EfiFileName[256];\r
57d6f36d 728\r
022c6d45 729\r
e94a9ff7 730 DEBUG ((DEBUG_INFO | DEBUG_LOAD,\r
91136124 731 "Loading driver at 0x%11p EntryPoint=0x%11p ",\r
e94a9ff7 732 (VOID *)(UINTN) Image->ImageContext.ImageAddress,\r
4e2dd553 733 FUNCTION_ENTRY_POINT (Image->ImageContext.EntryPoint)));\r
022c6d45 734\r
57d6f36d 735\r
e98cd821 736 //\r
57dfc48f 737 // Print Module Name by Pdb file path.\r
738 // Windows and Unix style file path are all trimmed correctly.\r
e98cd821 739 //\r
28a00297 740 if (Image->ImageContext.PdbPointer != NULL) {\r
741 StartIndex = 0;\r
742 for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
57dfc48f 743 if ((Image->ImageContext.PdbPointer[Index] == '\\') || (Image->ImageContext.PdbPointer[Index] == '/')) {\r
28a00297 744 StartIndex = Index + 1;\r
745 }\r
746 }\r
747 //\r
748 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
57dfc48f 749 // The PDB file name is limited in the range of 0~255.\r
750 // If the length is bigger than 255, trim the redudant characters to avoid overflow in array boundary.\r
28a00297 751 //\r
57dfc48f 752 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
28a00297 753 EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex];\r
754 if (EfiFileName[Index] == 0) {\r
755 EfiFileName[Index] = '.';\r
756 }\r
757 if (EfiFileName[Index] == '.') {\r
758 EfiFileName[Index + 1] = 'e';\r
759 EfiFileName[Index + 2] = 'f';\r
760 EfiFileName[Index + 3] = 'i';\r
761 EfiFileName[Index + 4] = 0;\r
762 break;\r
763 }\r
764 }\r
57dfc48f 765\r
766 if (Index == sizeof (EfiFileName) - 4) {\r
767 EfiFileName[Index] = 0;\r
768 }\r
162ed594 769 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
28a00297 770 }\r
162ed594 771 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
28a00297 772\r
773 DEBUG_CODE_END ();\r
774\r
775 return EFI_SUCCESS;\r
776\r
777Done:\r
778\r
779 //\r
780 // Free memory.\r
781 //\r
782\r
783 if (DstBufAlocated) {\r
784 CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
d9af5af8
SZ
785 Image->ImageContext.ImageAddress = 0;\r
786 Image->ImageBasePage = 0;\r
28a00297 787 }\r
788\r
789 if (Image->ImageContext.FixupData != NULL) {\r
790 CoreFreePool (Image->ImageContext.FixupData);\r
791 }\r
792\r
793 return Status;\r
794}\r
795\r
796\r
28a00297 797\r
162ed594 798/**\r
28a00297 799 Get the image's private data from its handle.\r
800\r
57d6f36d 801 @param ImageHandle The image handle\r
28a00297 802\r
162ed594 803 @return Return the image private data associated with ImageHandle.\r
28a00297 804\r
162ed594 805**/\r
806LOADED_IMAGE_PRIVATE_DATA *\r
807CoreLoadedImageInfo (\r
808 IN EFI_HANDLE ImageHandle\r
809 )\r
28a00297 810{\r
811 EFI_STATUS Status;\r
812 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
813 LOADED_IMAGE_PRIVATE_DATA *Image;\r
814\r
815 Status = CoreHandleProtocol (\r
816 ImageHandle,\r
817 &gEfiLoadedImageProtocolGuid,\r
818 (VOID **)&LoadedImage\r
819 );\r
820 if (!EFI_ERROR (Status)) {\r
821 Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage);\r
822 } else {\r
e94a9ff7 823 DEBUG ((DEBUG_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %p\n", ImageHandle));\r
28a00297 824 Image = NULL;\r
825 }\r
826\r
827 return Image;\r
828}\r
829\r
162ed594 830\r
c0a23f8c 831/**\r
832 Unloads EFI image from memory.\r
833\r
834 @param Image EFI image\r
835 @param FreePage Free allocated pages\r
836\r
837**/\r
838VOID\r
839CoreUnloadAndCloseImage (\r
840 IN LOADED_IMAGE_PRIVATE_DATA *Image,\r
841 IN BOOLEAN FreePage\r
842 )\r
843{\r
844 EFI_STATUS Status;\r
845 UINTN HandleCount;\r
846 EFI_HANDLE *HandleBuffer;\r
847 UINTN HandleIndex;\r
848 EFI_GUID **ProtocolGuidArray;\r
849 UINTN ArrayCount;\r
850 UINTN ProtocolIndex;\r
851 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;\r
852 UINTN OpenInfoCount;\r
853 UINTN OpenInfoIndex;\r
854\r
4e1005ec
ED
855 HandleBuffer = NULL;\r
856 ProtocolGuidArray = NULL;\r
857\r
57400f34
SZ
858 if (Image->Started) {\r
859 UnregisterMemoryProfileImage (Image);\r
860 }\r
861\r
d0e92aad
JY
862 UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
863\r
c0a23f8c 864 if (Image->Ebc != NULL) {\r
865 //\r
866 // If EBC protocol exists we must perform cleanups for this image.\r
867 //\r
868 Image->Ebc->UnloadImage (Image->Ebc, Image->Handle);\r
869 }\r
870\r
871 //\r
872 // Unload image, free Image->ImageContext->ModHandle\r
873 //\r
874 PeCoffLoaderUnloadImage (&Image->ImageContext);\r
875\r
876 //\r
877 // Free our references to the image handle\r
878 //\r
879 if (Image->Handle != NULL) {\r
880\r
881 Status = CoreLocateHandleBuffer (\r
882 AllHandles,\r
883 NULL,\r
884 NULL,\r
885 &HandleCount,\r
886 &HandleBuffer\r
887 );\r
888 if (!EFI_ERROR (Status)) {\r
889 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
890 Status = CoreProtocolsPerHandle (\r
891 HandleBuffer[HandleIndex],\r
892 &ProtocolGuidArray,\r
893 &ArrayCount\r
894 );\r
895 if (!EFI_ERROR (Status)) {\r
896 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {\r
897 Status = CoreOpenProtocolInformation (\r
898 HandleBuffer[HandleIndex],\r
899 ProtocolGuidArray[ProtocolIndex],\r
900 &OpenInfo,\r
901 &OpenInfoCount\r
902 );\r
903 if (!EFI_ERROR (Status)) {\r
904 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {\r
905 if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) {\r
906 Status = CoreCloseProtocol (\r
907 HandleBuffer[HandleIndex],\r
908 ProtocolGuidArray[ProtocolIndex],\r
909 Image->Handle,\r
910 OpenInfo[OpenInfoIndex].ControllerHandle\r
911 );\r
912 }\r
913 }\r
914 if (OpenInfo != NULL) {\r
915 CoreFreePool(OpenInfo);\r
916 }\r
917 }\r
918 }\r
919 if (ProtocolGuidArray != NULL) {\r
920 CoreFreePool(ProtocolGuidArray);\r
921 }\r
922 }\r
923 }\r
924 if (HandleBuffer != NULL) {\r
925 CoreFreePool (HandleBuffer);\r
926 }\r
927 }\r
928\r
929 CoreRemoveDebugImageInfoEntry (Image->Handle);\r
930\r
931 Status = CoreUninstallProtocolInterface (\r
932 Image->Handle,\r
933 &gEfiLoadedImageDevicePathProtocolGuid,\r
934 Image->LoadedImageDevicePath\r
935 );\r
936\r
937 Status = CoreUninstallProtocolInterface (\r
938 Image->Handle,\r
939 &gEfiLoadedImageProtocolGuid,\r
940 &Image->Info\r
941 );\r
942\r
7547649f 943 if (Image->ImageContext.HiiResourceData != 0) {\r
944 Status = CoreUninstallProtocolInterface (\r
945 Image->Handle,\r
946 &gEfiHiiPackageListProtocolGuid,\r
947 (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
948 );\r
949 }\r
950\r
c0a23f8c 951 }\r
952\r
953 if (Image->RuntimeData != NULL) {\r
954 if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
955 //\r
956 // Remove the Image from the Runtime Image list as we are about to Free it!\r
957 //\r
958 RemoveEntryList (&Image->RuntimeData->Link);\r
03d486b2 959 RemoveImageRecord (Image->RuntimeData);\r
c0a23f8c 960 }\r
961 CoreFreePool (Image->RuntimeData);\r
962 }\r
963\r
964 //\r
965 // Free the Image from memory\r
966 //\r
967 if ((Image->ImageBasePage != 0) && FreePage) {\r
968 CoreFreePages (Image->ImageBasePage, Image->NumberOfPages);\r
969 }\r
970\r
971 //\r
972 // Done with the Image structure\r
973 //\r
974 if (Image->Info.FilePath != NULL) {\r
975 CoreFreePool (Image->Info.FilePath);\r
976 }\r
977\r
978 if (Image->LoadedImageDevicePath != NULL) {\r
979 CoreFreePool (Image->LoadedImageDevicePath);\r
980 }\r
981\r
982 if (Image->FixupData != NULL) {\r
983 CoreFreePool (Image->FixupData);\r
984 }\r
985\r
986 CoreFreePool (Image);\r
987}\r
988\r
989\r
162ed594 990/**\r
991 Loads an EFI image into memory and returns a handle to the image.\r
992\r
57d6f36d 993 @param BootPolicy If TRUE, indicates that the request originates\r
994 from the boot manager, and that the boot\r
995 manager is attempting to load FilePath as a\r
996 boot selection.\r
997 @param ParentImageHandle The caller's image handle.\r
998 @param FilePath The specific file path from which the image is\r
999 loaded.\r
1000 @param SourceBuffer If not NULL, a pointer to the memory location\r
1001 containing a copy of the image to be loaded.\r
1002 @param SourceSize The size in bytes of SourceBuffer.\r
1003 @param DstBuffer The buffer to store the image\r
1004 @param NumberOfPages If not NULL, it inputs a pointer to the page\r
1005 number of DstBuffer and outputs a pointer to\r
1006 the page number of the image. If this number is\r
1007 not enough, return EFI_BUFFER_TOO_SMALL and\r
1008 this parameter contains the required number.\r
1009 @param ImageHandle Pointer to the returned image handle that is\r
1010 created when the image is successfully loaded.\r
1011 @param EntryPoint A pointer to the entry point\r
1012 @param Attribute The bit mask of attributes to set for the load\r
1013 PE image\r
1014\r
1015 @retval EFI_SUCCESS The image was loaded into memory.\r
1016 @retval EFI_NOT_FOUND The FilePath was not found.\r
1017 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1018 @retval EFI_BUFFER_TOO_SMALL The buffer is too small\r
1019 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1020 path cannot be parsed to locate the proper\r
1021 protocol for loading the file.\r
1022 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 1023 resources.\r
b695e7ff
LG
1024 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
1025 understood.\r
1026 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
d1102dba 1027 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
b695e7ff 1028 image from being loaded. NULL is returned in *ImageHandle.\r
d1102dba
LG
1029 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
1030 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
b695e7ff 1031 platform policy specifies that the image should not be started.\r
162ed594 1032\r
1033**/\r
28a00297 1034EFI_STATUS\r
1035CoreLoadImageCommon (\r
1036 IN BOOLEAN BootPolicy,\r
1037 IN EFI_HANDLE ParentImageHandle,\r
1038 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1039 IN VOID *SourceBuffer OPTIONAL,\r
1040 IN UINTN SourceSize,\r
1041 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
1042 IN OUT UINTN *NumberOfPages OPTIONAL,\r
1043 OUT EFI_HANDLE *ImageHandle,\r
1044 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
1045 IN UINT32 Attribute\r
1046 )\r
28a00297 1047{\r
1048 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1049 LOADED_IMAGE_PRIVATE_DATA *ParentImage;\r
1050 IMAGE_FILE_HANDLE FHand;\r
1051 EFI_STATUS Status;\r
1052 EFI_STATUS SecurityStatus;\r
1053 EFI_HANDLE DeviceHandle;\r
1054 UINT32 AuthenticationStatus;\r
1055 EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath;\r
1056 EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;\r
fa447063
LG
1057 EFI_DEVICE_PATH_PROTOCOL *InputFilePath;\r
1058 EFI_DEVICE_PATH_PROTOCOL *Node;\r
28a00297 1059 UINTN FilePathSize;\r
bc2dfdbc 1060 BOOLEAN ImageIsFromFv;\r
fa447063 1061 BOOLEAN ImageIsFromLoadFile;\r
28a00297 1062\r
1063 SecurityStatus = EFI_SUCCESS;\r
1064\r
1065 ASSERT (gEfiCurrentTpl < TPL_NOTIFY);\r
1066 ParentImage = NULL;\r
1067\r
1068 //\r
1069 // The caller must pass in a valid ParentImageHandle\r
1070 //\r
1071 if (ImageHandle == NULL || ParentImageHandle == NULL) {\r
1072 return EFI_INVALID_PARAMETER;\r
1073 }\r
1074\r
1075 ParentImage = CoreLoadedImageInfo (ParentImageHandle);\r
1076 if (ParentImage == NULL) {\r
162ed594 1077 DEBUG((DEBUG_LOAD|DEBUG_ERROR, "LoadImageEx: Parent handle not an image handle\n"));\r
28a00297 1078 return EFI_INVALID_PARAMETER;\r
1079 }\r
1080\r
7748df3d
LG
1081 ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));\r
1082 FHand.Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
28a00297 1083 OriginalFilePath = FilePath;\r
fa447063 1084 InputFilePath = FilePath;\r
7748df3d
LG
1085 HandleFilePath = FilePath;\r
1086 DeviceHandle = NULL;\r
1087 Status = EFI_SUCCESS;\r
1088 AuthenticationStatus = 0;\r
fa447063
LG
1089 ImageIsFromFv = FALSE;\r
1090 ImageIsFromLoadFile = FALSE;\r
bc2dfdbc 1091\r
7748df3d
LG
1092 //\r
1093 // If the caller passed a copy of the file, then just use it\r
1094 //\r
1095 if (SourceBuffer != NULL) {\r
1096 FHand.Source = SourceBuffer;\r
1097 FHand.SourceSize = SourceSize;\r
0407056e
SZ
1098 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1099 if (EFI_ERROR (Status)) {\r
1100 DeviceHandle = NULL;\r
1101 }\r
7748df3d
LG
1102 if (SourceSize > 0) {\r
1103 Status = EFI_SUCCESS;\r
1104 } else {\r
1105 Status = EFI_LOAD_ERROR;\r
1106 }\r
1107 } else {\r
1108 if (FilePath == NULL) {\r
1109 return EFI_INVALID_PARAMETER;\r
1110 }\r
fa447063
LG
1111\r
1112 //\r
1113 // Try to get the image device handle by checking the match protocol.\r
1114 //\r
1115 Node = NULL;\r
1116 Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1117 if (!EFI_ERROR (Status)) {\r
1118 ImageIsFromFv = TRUE;\r
1119 } else {\r
1120 HandleFilePath = FilePath;\r
1121 Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1122 if (EFI_ERROR (Status)) {\r
1123 if (!BootPolicy) {\r
1124 HandleFilePath = FilePath;\r
1125 Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1126 }\r
1127 if (EFI_ERROR (Status)) {\r
1128 HandleFilePath = FilePath;\r
1129 Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
1130 if (!EFI_ERROR (Status)) {\r
1131 ImageIsFromLoadFile = TRUE;\r
1132 Node = HandleFilePath;\r
1133 }\r
1134 }\r
1135 }\r
1136 }\r
1137\r
7748df3d
LG
1138 //\r
1139 // Get the source file buffer by its device path.\r
1140 //\r
1141 FHand.Source = GetFileBufferByFilePath (\r
d1102dba 1142 BootPolicy,\r
7748df3d
LG
1143 FilePath,\r
1144 &FHand.SourceSize,\r
1145 &AuthenticationStatus\r
1146 );\r
1147 if (FHand.Source == NULL) {\r
a13df02e 1148 Status = EFI_NOT_FOUND;\r
7748df3d 1149 } else {\r
7748df3d 1150 FHand.FreeBuffer = TRUE;\r
fa447063
LG
1151 if (ImageIsFromLoadFile) {\r
1152 //\r
1153 // LoadFile () may cause the device path of the Handle be updated.\r
1154 //\r
1155 OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);\r
7748df3d
LG
1156 }\r
1157 }\r
1158 }\r
1159\r
16bacc07 1160 if (EFI_ERROR (Status)) {\r
28a00297 1161 Image = NULL;\r
1162 goto Done;\r
28a00297 1163 }\r
1164\r
bc2dfdbc
LG
1165 if (gSecurity2 != NULL) {\r
1166 //\r
1167 // Verify File Authentication through the Security2 Architectural Protocol\r
1168 //\r
1169 SecurityStatus = gSecurity2->FileAuthentication (\r
1170 gSecurity2,\r
1171 OriginalFilePath,\r
1172 FHand.Source,\r
1173 FHand.SourceSize,\r
1174 BootPolicy\r
1175 );\r
1176 if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {\r
1177 //\r
1178 // When Security2 is installed, Security Architectural Protocol must be published.\r
1179 //\r
1180 ASSERT (gSecurity != NULL);\r
1181\r
1182 //\r
1183 // Verify the Authentication Status through the Security Architectural Protocol\r
1184 // Only on images that have been read using Firmware Volume protocol.\r
1185 //\r
1186 SecurityStatus = gSecurity->FileAuthenticationState (\r
1187 gSecurity,\r
1188 AuthenticationStatus,\r
1189 OriginalFilePath\r
1190 );\r
1191 }\r
1192 } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
1193 //\r
1194 // Verify the Authentication Status through the Security Architectural Protocol\r
1195 //\r
28a00297 1196 SecurityStatus = gSecurity->FileAuthenticationState (\r
1197 gSecurity,\r
1198 AuthenticationStatus,\r
1199 OriginalFilePath\r
1200 );\r
28a00297 1201 }\r
1202\r
bc2dfdbc
LG
1203 //\r
1204 // Check Security Status.\r
1205 //\r
1206 if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
1207 if (SecurityStatus == EFI_ACCESS_DENIED) {\r
1208 //\r
1209 // Image was not loaded because the platform policy prohibits the image from being loaded.\r
1210 // It's the only place we could meet EFI_ACCESS_DENIED.\r
1211 //\r
1212 *ImageHandle = NULL;\r
1213 }\r
1214 Status = SecurityStatus;\r
1215 Image = NULL;\r
1216 goto Done;\r
1217 }\r
28a00297 1218\r
1219 //\r
1220 // Allocate a new image structure\r
1221 //\r
9c4ac31c 1222 Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
28a00297 1223 if (Image == NULL) {\r
16bacc07
SZ
1224 Status = EFI_OUT_OF_RESOURCES;\r
1225 goto Done;\r
28a00297 1226 }\r
1227\r
1228 //\r
1229 // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
1230 //\r
cfe9de52 1231 FilePath = OriginalFilePath;\r
d2fbaaab 1232 if (DeviceHandle != NULL) {\r
1233 Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);\r
1234 if (!EFI_ERROR (Status)) {\r
1235 FilePathSize = GetDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
1236 FilePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *)FilePath) + FilePathSize );\r
1237 }\r
28a00297 1238 }\r
28a00297 1239 //\r
1240 // Initialize the fields for an internal driver\r
1241 //\r
1242 Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE;\r
1243 Image->Info.SystemTable = gDxeCoreST;\r
1244 Image->Info.DeviceHandle = DeviceHandle;\r
162ed594 1245 Image->Info.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
9c4ac31c 1246 Image->Info.FilePath = DuplicateDevicePath (FilePath);\r
28a00297 1247 Image->Info.ParentHandle = ParentImageHandle;\r
1248\r
85658066 1249\r
28a00297 1250 if (NumberOfPages != NULL) {\r
1251 Image->NumberOfPages = *NumberOfPages ;\r
1252 } else {\r
1253 Image->NumberOfPages = 0 ;\r
1254 }\r
1255\r
1256 //\r
1257 // Install the protocol interfaces for this image\r
1258 // don't fire notifications yet\r
1259 //\r
1260 Status = CoreInstallProtocolInterfaceNotify (\r
1261 &Image->Handle,\r
1262 &gEfiLoadedImageProtocolGuid,\r
1263 EFI_NATIVE_INTERFACE,\r
1264 &Image->Info,\r
1265 FALSE\r
1266 );\r
1267 if (EFI_ERROR (Status)) {\r
1268 goto Done;\r
1269 }\r
1270\r
1271 //\r
1272 // Load the image. If EntryPoint is Null, it will not be set.\r
1273 //\r
822360ee 1274 Status = CoreLoadPeImage (BootPolicy, &FHand, Image, DstBuffer, EntryPoint, Attribute);\r
28a00297 1275 if (EFI_ERROR (Status)) {\r
1276 if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) {\r
1277 if (NumberOfPages != NULL) {\r
1278 *NumberOfPages = Image->NumberOfPages;\r
1279 }\r
1280 }\r
1281 goto Done;\r
1282 }\r
1283\r
152af594 1284 if (NumberOfPages != NULL) {\r
1285 *NumberOfPages = Image->NumberOfPages;\r
57d6f36d 1286 }\r
152af594 1287\r
28a00297 1288 //\r
1289 // Register the image in the Debug Image Info Table if the attribute is set\r
1290 //\r
71f68914 1291 if ((Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) != 0) {\r
28a00297 1292 CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle);\r
1293 }\r
1294\r
1295 //\r
1296 //Reinstall loaded image protocol to fire any notifications\r
1297 //\r
1298 Status = CoreReinstallProtocolInterface (\r
1299 Image->Handle,\r
1300 &gEfiLoadedImageProtocolGuid,\r
1301 &Image->Info,\r
1302 &Image->Info\r
1303 );\r
1304 if (EFI_ERROR (Status)) {\r
1305 goto Done;\r
1306 }\r
1307\r
ba39e316 1308 //\r
1309 // If DevicePath parameter to the LoadImage() is not NULL, then make a copy of DevicePath,\r
1310 // otherwise Loaded Image Device Path Protocol is installed with a NULL interface pointer.\r
1311 //\r
1312 if (OriginalFilePath != NULL) {\r
9c4ac31c 1313 Image->LoadedImageDevicePath = DuplicateDevicePath (OriginalFilePath);\r
ba39e316 1314 }\r
1315\r
1316 //\r
1317 // Install Loaded Image Device Path Protocol onto the image handle of a PE/COFE image\r
1318 //\r
1319 Status = CoreInstallProtocolInterface (\r
1320 &Image->Handle,\r
1321 &gEfiLoadedImageDevicePathProtocolGuid,\r
1322 EFI_NATIVE_INTERFACE,\r
1323 Image->LoadedImageDevicePath\r
1324 );\r
1325 if (EFI_ERROR (Status)) {\r
1326 goto Done;\r
1327 }\r
28a00297 1328\r
7547649f 1329 //\r
1330 // Install HII Package List Protocol onto the image handle\r
1331 //\r
1332 if (Image->ImageContext.HiiResourceData != 0) {\r
1333 Status = CoreInstallProtocolInterface (\r
1334 &Image->Handle,\r
1335 &gEfiHiiPackageListProtocolGuid,\r
1336 EFI_NATIVE_INTERFACE,\r
1337 (VOID *) (UINTN) Image->ImageContext.HiiResourceData\r
1338 );\r
1339 if (EFI_ERROR (Status)) {\r
1340 goto Done;\r
1341 }\r
1342 }\r
d0e92aad 1343 ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath);\r
7547649f 1344\r
28a00297 1345 //\r
1346 // Success. Return the image handle\r
1347 //\r
1348 *ImageHandle = Image->Handle;\r
1349\r
1350Done:\r
1351 //\r
1352 // All done accessing the source file\r
1353 // If we allocated the Source buffer, free it\r
1354 //\r
1355 if (FHand.FreeBuffer) {\r
1356 CoreFreePool (FHand.Source);\r
1357 }\r
fa447063
LG
1358 if (OriginalFilePath != InputFilePath) {\r
1359 CoreFreePool (OriginalFilePath);\r
1360 }\r
28a00297 1361\r
1362 //\r
1363 // There was an error. If there's an Image structure, free it\r
1364 //\r
1365 if (EFI_ERROR (Status)) {\r
1366 if (Image != NULL) {\r
1367 CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
bc2dfdbc 1368 Image = NULL;\r
28a00297 1369 }\r
1370 } else if (EFI_ERROR (SecurityStatus)) {\r
1371 Status = SecurityStatus;\r
1372 }\r
1373\r
bc2dfdbc
LG
1374 //\r
1375 // Track the return status from LoadImage.\r
1376 //\r
1377 if (Image != NULL) {\r
1378 Image->LoadImageStatus = Status;\r
1379 }\r
1380\r
28a00297 1381 return Status;\r
1382}\r
1383\r
1384\r
1385\r
162ed594 1386\r
1387/**\r
1388 Loads an EFI image into memory and returns a handle to the image.\r
1389\r
57d6f36d 1390 @param BootPolicy If TRUE, indicates that the request originates\r
1391 from the boot manager, and that the boot\r
1392 manager is attempting to load FilePath as a\r
1393 boot selection.\r
1394 @param ParentImageHandle The caller's image handle.\r
1395 @param FilePath The specific file path from which the image is\r
1396 loaded.\r
1397 @param SourceBuffer If not NULL, a pointer to the memory location\r
1398 containing a copy of the image to be loaded.\r
1399 @param SourceSize The size in bytes of SourceBuffer.\r
1400 @param ImageHandle Pointer to the returned image handle that is\r
1401 created when the image is successfully loaded.\r
1402\r
1403 @retval EFI_SUCCESS The image was loaded into memory.\r
1404 @retval EFI_NOT_FOUND The FilePath was not found.\r
1405 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1406 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1407 path cannot be parsed to locate the proper\r
1408 protocol for loading the file.\r
1409 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
162ed594 1410 resources.\r
b695e7ff
LG
1411 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
1412 understood.\r
1413 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
d1102dba 1414 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
b695e7ff 1415 image from being loaded. NULL is returned in *ImageHandle.\r
d1102dba
LG
1416 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
1417 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
b695e7ff 1418 platform policy specifies that the image should not be started.\r
162ed594 1419\r
1420**/\r
28a00297 1421EFI_STATUS\r
1422EFIAPI\r
1423CoreLoadImage (\r
1424 IN BOOLEAN BootPolicy,\r
1425 IN EFI_HANDLE ParentImageHandle,\r
1426 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1427 IN VOID *SourceBuffer OPTIONAL,\r
1428 IN UINTN SourceSize,\r
1429 OUT EFI_HANDLE *ImageHandle\r
1430 )\r
28a00297 1431{\r
1432 EFI_STATUS Status;\r
d2c243e1 1433 EFI_HANDLE Handle;\r
28a00297 1434\r
67e9ab84 1435 PERF_LOAD_IMAGE_BEGIN (NULL);\r
28a00297 1436\r
1437 Status = CoreLoadImageCommon (\r
1438 BootPolicy,\r
1439 ParentImageHandle,\r
1440 FilePath,\r
1441 SourceBuffer,\r
1442 SourceSize,\r
1be0dda6 1443 (EFI_PHYSICAL_ADDRESS) (UINTN) NULL,\r
28a00297 1444 NULL,\r
1445 ImageHandle,\r
1446 NULL,\r
1447 EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION\r
1448 );\r
1449\r
d1102dba 1450 Handle = NULL;\r
d2c243e1
LG
1451 if (!EFI_ERROR (Status)) {\r
1452 //\r
d1102dba 1453 // ImageHandle will be valid only Status is success.\r
d2c243e1
LG
1454 //\r
1455 Handle = *ImageHandle;\r
1456 }\r
1457\r
67e9ab84 1458 PERF_LOAD_IMAGE_END (Handle);\r
28a00297 1459\r
1460 return Status;\r
1461}\r
1462\r
1463\r
023c0fec 1464\r
1465/**\r
1466 Loads an EFI image into memory and returns a handle to the image with extended parameters.\r
1467\r
1468 @param This Calling context\r
1469 @param ParentImageHandle The caller's image handle.\r
1470 @param FilePath The specific file path from which the image is\r
1471 loaded.\r
1472 @param SourceBuffer If not NULL, a pointer to the memory location\r
1473 containing a copy of the image to be loaded.\r
1474 @param SourceSize The size in bytes of SourceBuffer.\r
1475 @param DstBuffer The buffer to store the image.\r
1476 @param NumberOfPages For input, specifies the space size of the\r
1477 image by caller if not NULL. For output,\r
1478 specifies the actual space size needed.\r
1479 @param ImageHandle Image handle for output.\r
1480 @param EntryPoint Image entry point for output.\r
1481 @param Attribute The bit mask of attributes to set for the load\r
1482 PE image.\r
1483\r
1484 @retval EFI_SUCCESS The image was loaded into memory.\r
1485 @retval EFI_NOT_FOUND The FilePath was not found.\r
1486 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
1487 @retval EFI_UNSUPPORTED The image type is not supported, or the device\r
1488 path cannot be parsed to locate the proper\r
1489 protocol for loading the file.\r
1490 @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient\r
1491 resources.\r
b695e7ff
LG
1492 @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not\r
1493 understood.\r
1494 @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error.\r
d1102dba 1495 @retval EFI_ACCESS_DENIED Image was not loaded because the platform policy prohibits the\r
b695e7ff 1496 image from being loaded. NULL is returned in *ImageHandle.\r
d1102dba
LG
1497 @retval EFI_SECURITY_VIOLATION Image was loaded and an ImageHandle was created with a\r
1498 valid EFI_LOADED_IMAGE_PROTOCOL. However, the current\r
b695e7ff 1499 platform policy specifies that the image should not be started.\r
023c0fec 1500\r
1501**/\r
1502EFI_STATUS\r
1503EFIAPI\r
1504CoreLoadImageEx (\r
1505 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1506 IN EFI_HANDLE ParentImageHandle,\r
1507 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1508 IN VOID *SourceBuffer OPTIONAL,\r
1509 IN UINTN SourceSize,\r
1510 IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL,\r
1511 OUT UINTN *NumberOfPages OPTIONAL,\r
1512 OUT EFI_HANDLE *ImageHandle,\r
1513 OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL,\r
1514 IN UINT32 Attribute\r
1515 )\r
1516{\r
f3235b77 1517 EFI_STATUS Status;\r
f3235b77
SZ
1518 EFI_HANDLE Handle;\r
1519\r
67e9ab84 1520 PERF_LOAD_IMAGE_BEGIN (NULL);\r
f3235b77
SZ
1521\r
1522 Status = CoreLoadImageCommon (\r
023c0fec 1523 TRUE,\r
1524 ParentImageHandle,\r
1525 FilePath,\r
1526 SourceBuffer,\r
1527 SourceSize,\r
1528 DstBuffer,\r
1529 NumberOfPages,\r
1530 ImageHandle,\r
1531 EntryPoint,\r
1532 Attribute\r
1533 );\r
f3235b77 1534\r
d1102dba 1535 Handle = NULL;\r
f3235b77
SZ
1536 if (!EFI_ERROR (Status)) {\r
1537 //\r
d1102dba 1538 // ImageHandle will be valid only Status is success.\r
f3235b77
SZ
1539 //\r
1540 Handle = *ImageHandle;\r
1541 }\r
1542\r
67e9ab84 1543 PERF_LOAD_IMAGE_END (Handle);\r
f3235b77
SZ
1544\r
1545 return Status;\r
023c0fec 1546}\r
1547\r
1548\r
162ed594 1549/**\r
1550 Transfer control to a loaded image's entry point.\r
1551\r
57d6f36d 1552 @param ImageHandle Handle of image to be started.\r
1553 @param ExitDataSize Pointer of the size to ExitData\r
1554 @param ExitData Pointer to a pointer to a data buffer that\r
b695e7ff 1555 includes a Null-terminated string,\r
57d6f36d 1556 optionally followed by additional binary data.\r
1557 The string is a description that the caller may\r
1558 use to further indicate the reason for the\r
1559 image's exit.\r
1560\r
1561 @retval EFI_INVALID_PARAMETER Invalid parameter\r
1562 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
bc2dfdbc 1563 @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started.\r
57d6f36d 1564 @retval EFI_SUCCESS Successfully transfer control to the image's\r
162ed594 1565 entry point.\r
1566\r
1567**/\r
28a00297 1568EFI_STATUS\r
1569EFIAPI\r
1570CoreStartImage (\r
1571 IN EFI_HANDLE ImageHandle,\r
1572 OUT UINTN *ExitDataSize,\r
1573 OUT CHAR16 **ExitData OPTIONAL\r
1574 )\r
28a00297 1575{\r
1576 EFI_STATUS Status;\r
1577 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1578 LOADED_IMAGE_PRIVATE_DATA *LastImage;\r
1579 UINT64 HandleDatabaseKey;\r
1580 UINTN SetJumpFlag;\r
f3235b77
SZ
1581 EFI_HANDLE Handle;\r
1582\r
f3235b77 1583 Handle = ImageHandle;\r
28a00297 1584\r
1585 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1586 if (Image == NULL || Image->Started) {\r
28a00297 1587 return EFI_INVALID_PARAMETER;\r
1588 }\r
bc2dfdbc
LG
1589 if (EFI_ERROR (Image->LoadImageStatus)) {\r
1590 return Image->LoadImageStatus;\r
1591 }\r
28a00297 1592\r
db0b7ad5
LG
1593 //\r
1594 // The image to be started must have the machine type supported by DxeCore.\r
1595 //\r
919df8e6 1596 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {\r
60c0073f
LG
1597 //\r
1598 // Do not ASSERT here, because image might be loaded via EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED\r
1599 // But it can not be started.\r
1600 //\r
f00237c1
LG
1601 DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", GetMachineTypeName(Image->Machine)));\r
1602 DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", GetMachineTypeName(mDxeCoreImageMachineType)));\r
919df8e6
LG
1603 return EFI_UNSUPPORTED;\r
1604 }\r
1605\r
67e9ab84 1606 PERF_START_IMAGE_BEGIN (Handle);\r
28a00297 1607\r
1608\r
1609 //\r
1610 // Push the current start image context, and\r
1611 // link the current image to the head. This is the\r
1612 // only image that can call Exit()\r
1613 //\r
1614 HandleDatabaseKey = CoreGetHandleDatabaseKey ();\r
1615 LastImage = mCurrentImage;\r
1616 mCurrentImage = Image;\r
1617 Image->Tpl = gEfiCurrentTpl;\r
1618\r
1619 //\r
1620 // Set long jump for Exit() support\r
1621 // JumpContext must be aligned on a CPU specific boundary.\r
1622 // Overallocate the buffer and force the required alignment\r
1623 //\r
9c4ac31c 1624 Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
28a00297 1625 if (Image->JumpBuffer == NULL) {\r
f3235b77
SZ
1626 //\r
1627 // Image may be unloaded after return with failure,\r
1628 // then ImageHandle may be invalid, so use NULL handle to record perf log.\r
1629 //\r
67e9ab84 1630 PERF_START_IMAGE_END (NULL);\r
7a14d54f
HW
1631\r
1632 //\r
1633 // Pop the current start image context\r
1634 //\r
1635 mCurrentImage = LastImage;\r
1636\r
28a00297 1637 return EFI_OUT_OF_RESOURCES;\r
1638 }\r
1639 Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
1640\r
1641 SetJumpFlag = SetJump (Image->JumpContext);\r
1642 //\r
1643 // The initial call to SetJump() must always return 0.\r
1644 // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
1645 //\r
71f68914 1646 if (SetJumpFlag == 0) {\r
84edd20b 1647 RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));\r
28a00297 1648 //\r
1649 // Call the image's entry point\r
1650 //\r
1651 Image->Started = TRUE;\r
1652 Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);\r
1653\r
1654 //\r
1655 // Add some debug information if the image returned with error.\r
1656 // This make the user aware and check if the driver image have already released\r
1657 // all the resource in this situation.\r
1658 //\r
1659 DEBUG_CODE_BEGIN ();\r
1660 if (EFI_ERROR (Image->Status)) {\r
91136124 1661 DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
28a00297 1662 }\r
1663 DEBUG_CODE_END ();\r
1664\r
1665 //\r
1666 // If the image returns, exit it through Exit()\r
1667 //\r
1668 CoreExit (ImageHandle, Image->Status, 0, NULL);\r
1669 }\r
1670\r
1671 //\r
1672 // Image has completed. Verify the tpl is the same\r
1673 //\r
1674 ASSERT (Image->Tpl == gEfiCurrentTpl);\r
1675 CoreRestoreTpl (Image->Tpl);\r
1676\r
1677 CoreFreePool (Image->JumpBuffer);\r
1678\r
1679 //\r
1680 // Pop the current start image context\r
1681 //\r
1682 mCurrentImage = LastImage;\r
1683\r
1684 //\r
47104838
MK
1685 // UEFI Specification - StartImage() - EFI 1.10 Extension\r
1686 // To maintain compatibility with UEFI drivers that are written to the EFI\r
1687 // 1.02 Specification, StartImage() must monitor the handle database before\r
1688 // and after each image is started. If any handles are created or modified\r
1689 // when an image is started, then EFI_BOOT_SERVICES.ConnectController() must\r
1690 // be called with the Recursive parameter set to TRUE for each of the newly\r
1691 // created or modified handles before StartImage() returns.\r
1692 //\r
1693 if (Image->Type != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1694 CoreConnectHandlesByKey (HandleDatabaseKey);\r
1695 }\r
28a00297 1696\r
1697 //\r
1698 // Handle the image's returned ExitData\r
1699 //\r
1700 DEBUG_CODE_BEGIN ();\r
1701 if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {\r
1702\r
7df7393f 1703 DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", (UINT32)Image->ExitDataSize, Image->ExitData));\r
28a00297 1704 if (Image->ExitData != NULL) {\r
162ed594 1705 DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));\r
28a00297 1706 }\r
162ed594 1707 DEBUG ((DEBUG_LOAD, "\n"));\r
28a00297 1708 }\r
1709 DEBUG_CODE_END ();\r
1710\r
1711 //\r
1712 // Return the exit data to the caller\r
1713 //\r
1714 if (ExitData != NULL && ExitDataSize != NULL) {\r
1715 *ExitDataSize = Image->ExitDataSize;\r
1716 *ExitData = Image->ExitData;\r
1717 } else {\r
1718 //\r
1719 // Caller doesn't want the exit data, free it\r
1720 //\r
1721 CoreFreePool (Image->ExitData);\r
1722 Image->ExitData = NULL;\r
1723 }\r
1724\r
1725 //\r
1726 // Save the Status because Image will get destroyed if it is unloaded.\r
1727 //\r
1728 Status = Image->Status;\r
1729\r
1730 //\r
1731 // If the image returned an error, or if the image is an application\r
1732 // unload it\r
1733 //\r
1734 if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
1735 CoreUnloadAndCloseImage (Image, TRUE);\r
f3235b77
SZ
1736 //\r
1737 // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.\r
1738 //\r
1739 Handle = NULL;\r
28a00297 1740 }\r
1741\r
1742 //\r
1743 // Done\r
1744 //\r
67e9ab84 1745 PERF_START_IMAGE_END (Handle);\r
28a00297 1746 return Status;\r
1747}\r
1748\r
162ed594 1749/**\r
1750 Terminates the currently loaded EFI image and returns control to boot services.\r
1751\r
57d6f36d 1752 @param ImageHandle Handle that identifies the image. This\r
1753 parameter is passed to the image on entry.\r
1754 @param Status The image's exit code.\r
1755 @param ExitDataSize The size, in bytes, of ExitData. Ignored if\r
1756 ExitStatus is EFI_SUCCESS.\r
1757 @param ExitData Pointer to a data buffer that includes a\r
1758 Null-terminated Unicode string, optionally\r
1759 followed by additional binary data. The string\r
1760 is a description that the caller may use to\r
1761 further indicate the reason for the image's\r
1762 exit.\r
1763\r
1764 @retval EFI_INVALID_PARAMETER Image handle is NULL or it is not current\r
1765 image.\r
1766 @retval EFI_SUCCESS Successfully terminates the currently loaded\r
1767 EFI image.\r
1768 @retval EFI_ACCESS_DENIED Should never reach there.\r
162ed594 1769 @retval EFI_OUT_OF_RESOURCES Could not allocate pool\r
1770\r
1771**/\r
28a00297 1772EFI_STATUS\r
1773EFIAPI\r
1774CoreExit (\r
1775 IN EFI_HANDLE ImageHandle,\r
1776 IN EFI_STATUS Status,\r
1777 IN UINTN ExitDataSize,\r
1778 IN CHAR16 *ExitData OPTIONAL\r
1779 )\r
28a00297 1780{\r
1781 LOADED_IMAGE_PRIVATE_DATA *Image;\r
1782 EFI_TPL OldTpl;\r
1783\r
1784 //\r
1785 // Prevent possible reentrance to this function\r
1786 // for the same ImageHandle\r
57d6f36d 1787 //\r
1788 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
1789\r
28a00297 1790 Image = CoreLoadedImageInfo (ImageHandle);\r
4008328a 1791 if (Image == NULL) {\r
28a00297 1792 Status = EFI_INVALID_PARAMETER;\r
1793 goto Done;\r
1794 }\r
1795\r
1796 if (!Image->Started) {\r
1797 //\r
1798 // The image has not been started so just free its resources\r
1799 //\r
1800 CoreUnloadAndCloseImage (Image, TRUE);\r
1801 Status = EFI_SUCCESS;\r
1802 goto Done;\r
1803 }\r
1804\r
1805 //\r
1806 // Image has been started, verify this image can exit\r
1807 //\r
1808 if (Image != mCurrentImage) {\r
162ed594 1809 DEBUG ((DEBUG_LOAD|DEBUG_ERROR, "Exit: Image is not exitable image\n"));\r
28a00297 1810 Status = EFI_INVALID_PARAMETER;\r
1811 goto Done;\r
1812 }\r
1813\r
1814 //\r
1815 // Set status\r
1816 //\r
1817 Image->Status = Status;\r
1818\r
1819 //\r
1820 // If there's ExitData info, move it\r
1821 //\r
1822 if (ExitData != NULL) {\r
1823 Image->ExitDataSize = ExitDataSize;\r
9c4ac31c 1824 Image->ExitData = AllocatePool (Image->ExitDataSize);\r
28a00297 1825 if (Image->ExitData == NULL) {\r
1826 Status = EFI_OUT_OF_RESOURCES;\r
1827 goto Done;\r
1828 }\r
1829 CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
1830 }\r
1831\r
1832 CoreRestoreTpl (OldTpl);\r
1833 //\r
1834 // return to StartImage\r
1835 //\r
1836 LongJump (Image->JumpContext, (UINTN)-1);\r
1837\r
1838 //\r
1839 // If we return from LongJump, then it is an error\r
1840 //\r
1841 ASSERT (FALSE);\r
1842 Status = EFI_ACCESS_DENIED;\r
1843Done:\r
1844 CoreRestoreTpl (OldTpl);\r
1845 return Status;\r
1846}\r
1847\r
1848\r
1849\r
28a00297 1850\r
162ed594 1851/**\r
28a00297 1852 Unloads an image.\r
1853\r
57d6f36d 1854 @param ImageHandle Handle that identifies the image to be\r
1855 unloaded.\r
28a00297 1856\r
57d6f36d 1857 @retval EFI_SUCCESS The image has been unloaded.\r
6393d9c8 1858 @retval EFI_UNSUPPORTED The image has been started, and does not support\r
57d6f36d 1859 unload.\r
162ed594 1860 @retval EFI_INVALID_PARAMPETER ImageHandle is not a valid image handle.\r
28a00297 1861\r
162ed594 1862**/\r
1863EFI_STATUS\r
1864EFIAPI\r
1865CoreUnloadImage (\r
1866 IN EFI_HANDLE ImageHandle\r
1867 )\r
28a00297 1868{\r
1869 EFI_STATUS Status;\r
1870 LOADED_IMAGE_PRIVATE_DATA *Image;\r
28a00297 1871\r
28a00297 1872 Image = CoreLoadedImageInfo (ImageHandle);\r
1873 if (Image == NULL ) {\r
1874 //\r
1875 // The image handle is not valid\r
1876 //\r
1877 Status = EFI_INVALID_PARAMETER;\r
1878 goto Done;\r
1879 }\r
1880\r
1881 if (Image->Started) {\r
1882 //\r
1883 // The image has been started, request it to unload.\r
1884 //\r
1885 Status = EFI_UNSUPPORTED;\r
1886 if (Image->Info.Unload != NULL) {\r
1887 Status = Image->Info.Unload (ImageHandle);\r
1888 }\r
1889\r
1890 } else {\r
1891 //\r
1892 // This Image hasn't been started, thus it can be unloaded\r
1893 //\r
1894 Status = EFI_SUCCESS;\r
1895 }\r
1896\r
1897\r
1898 if (!EFI_ERROR (Status)) {\r
1899 //\r
1900 // if the Image was not started or Unloaded O.K. then clean up\r
1901 //\r
1902 CoreUnloadAndCloseImage (Image, TRUE);\r
1903 }\r
1904\r
1905Done:\r
28a00297 1906 return Status;\r
1907}\r
1908\r
023c0fec 1909\r
1910\r
1911/**\r
1912 Unload the specified image.\r
1913\r
1914 @param This Indicates the calling context.\r
1915 @param ImageHandle The specified image handle.\r
1916\r
1917 @retval EFI_INVALID_PARAMETER Image handle is NULL.\r
1918 @retval EFI_UNSUPPORTED Attempt to unload an unsupported image.\r
1919 @retval EFI_SUCCESS Image successfully unloaded.\r
1920\r
1921**/\r
1922EFI_STATUS\r
1923EFIAPI\r
1924CoreUnloadImageEx (\r
1925 IN EFI_PE32_IMAGE_PROTOCOL *This,\r
1926 IN EFI_HANDLE ImageHandle\r
1927 )\r
1928{\r
1929 return CoreUnloadImage (ImageHandle);\r
1930}\r