TianoCore EDK2 master
Loading...
Searching...
No Matches
LoadBelow4G.c
Go to the documentation of this file.
1
9#include <Uefi.h>
10#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
14#include <Library/PeCoffLib.h>
18#include <Library/UefiLib.h>
19
32 IN EFI_HANDLE ImageHandle,
33 IN EFI_SYSTEM_TABLE *SystemTable
34 )
35{
36 EFI_STATUS Status;
37 UINT8 *Buffer;
38 UINTN BufferSize;
39 EFI_HANDLE NewImageHandle;
40 UINTN Pages;
41 EFI_PHYSICAL_ADDRESS FfsBuffer;
43 VOID *Interface;
44
45 //
46 // If it is already <4G, no need do relocate
47 //
48 if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) {
49 return EFI_SUCCESS;
50 }
51
52 //
53 // If locate gEfiCallerIdGuid success, it means 2nd entry.
54 //
55 Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface);
56 if (!EFI_ERROR (Status)) {
57 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));
58 return EFI_SUCCESS;
59 }
60
61 DEBUG ((DEBUG_INFO, "FspNotifyDxe - 1st entry\n"));
62
63 //
64 // Here we install a dummy handle
65 //
66 NewImageHandle = NULL;
67 Status = gBS->InstallProtocolInterface (
68 &NewImageHandle,
69 &gEfiCallerIdGuid,
71 NULL
72 );
73 ASSERT_EFI_ERROR (Status);
74
75 //
76 // Reload image itself to <4G mem
77 //
78 Status = GetSectionFromAnyFv (
79 &gEfiCallerIdGuid,
81 0,
82 (VOID **)&Buffer,
83 &BufferSize
84 );
85 ASSERT_EFI_ERROR (Status);
86 ImageContext.Handle = Buffer;
88 //
89 // Get information about the image being loaded
90 //
91 Status = PeCoffLoaderGetImageInfo (&ImageContext);
92 ASSERT_EFI_ERROR (Status);
93 if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
94 Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
95 } else {
96 Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
97 }
98
99 FfsBuffer = 0xFFFFFFFF;
100 Status = gBS->AllocatePages (
103 Pages,
104 &FfsBuffer
105 );
106 ASSERT_EFI_ERROR (Status);
107 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
108 //
109 // Align buffer on section boundary
110 //
111 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
112 ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
113 //
114 // Load the image to our new buffer
115 //
116 Status = PeCoffLoaderLoadImage (&ImageContext);
117 ASSERT_EFI_ERROR (Status);
118
119 //
120 // Relocate the image in our new buffer
121 //
122 Status = PeCoffLoaderRelocateImage (&ImageContext);
123 ASSERT_EFI_ERROR (Status);
124
125 //
126 // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
127 //
128 gBS->FreePool (Buffer);
129
130 //
131 // Flush the instruction cache so the image data is written before we execute it
132 //
133 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
134
135 DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));
136 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
137 if (EFI_ERROR (Status)) {
138 DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));
139 gBS->FreePages (FfsBuffer, Pages);
140 }
141
142 //
143 // return error to unload >4G copy, if we already relocate itself to <4G.
144 //
145 return EFI_ALREADY_STARTED;
146}
UINT64 UINTN
VOID *EFIAPI InvalidateInstructionCacheRange(IN VOID *Address, IN UINTN Length)
EFI_STATUS EFIAPI GetSectionFromAnyFv(IN CONST EFI_GUID *NameGuid, IN EFI_SECTION_TYPE SectionType, IN UINTN SectionInstance, OUT VOID **Buffer, OUT UINTN *Size)
EFI_STATUS RelocateImageUnder4GIfNeeded(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: LoadBelow4G.c:31
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFIAPI PeCoffLoaderLoadImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:1244
RETURN_STATUS EFIAPI PeCoffLoaderRelocateImage(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:956
RETURN_STATUS EFIAPI PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:577
RETURN_STATUS EFIAPI PeCoffLoaderImageReadFromMemory(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: BasePeCoff.c:1992
#define EFI_SECTION_PE32
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
@ EfiBootServicesCode
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
EFI_STATUS(EFIAPI * EFI_IMAGE_ENTRY_POINT)(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: UefiSpec.h:2108
@ AllocateMaxAddress
Definition: UefiSpec.h:38
PE_COFF_LOADER_READ_FILE ImageRead
Definition: PeCoffLib.h:100
PHYSICAL_ADDRESS EntryPoint
Definition: PeCoffLib.h:95
PHYSICAL_ADDRESS ImageAddress
Definition: PeCoffLib.h:79