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