TianoCore EDK2 master
Loading...
Searching...
No Matches
DxePrmPeCoffLib.c
Go to the documentation of this file.
1
13#include <Library/BaseLib.h>
14#include <Library/DebugLib.h>
15#include <Library/PeCoffLib.h>
16
17#include <PrmExportDescriptor.h>
19
20#define _DBGMSGID_ "[PRMPECOFFLIB]"
21
40 IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
41 IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
43 )
44{
45 UINTN Index;
46 EFI_PHYSICAL_ADDRESS CurrentImageAddress;
47 UINT16 PrmModuleExportDescriptorOrdinal;
48 CONST CHAR8 *CurrentExportName;
49 UINT16 *OrdinalTable;
50 UINT32 *ExportNamePointerTable;
51 UINT32 *ExportAddressTable;
52 PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *TempExportDescriptor;
53
54 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
55
56 if ((ImageExportDirectory == NULL) ||
57 (PeCoffLoaderImageContext == NULL) ||
58 (PeCoffLoaderImageContext->ImageAddress == 0) ||
59 (ExportDescriptor == NULL))
60 {
61 return EFI_INVALID_PARAMETER;
62 }
63
64 *ExportDescriptor = NULL;
65
66 DEBUG ((
67 DEBUG_INFO,
68 " %a %a: %d exported names found in this image.\n",
69 _DBGMSGID_,
70 __func__,
71 ImageExportDirectory->NumberOfNames
72 ));
73
74 //
75 // The export name pointer table and export ordinal table form two parallel arrays associated by index.
76 //
77 CurrentImageAddress = PeCoffLoaderImageContext->ImageAddress;
78 ExportAddressTable = (UINT32 *)((UINTN)CurrentImageAddress + ImageExportDirectory->AddressOfFunctions);
79 ExportNamePointerTable = (UINT32 *)((UINTN)CurrentImageAddress + ImageExportDirectory->AddressOfNames);
80 OrdinalTable = (UINT16 *)((UINTN)CurrentImageAddress + ImageExportDirectory->AddressOfNameOrdinals);
81
82 for (Index = 0; Index < ImageExportDirectory->NumberOfNames; Index++) {
83 CurrentExportName = (CONST CHAR8 *)((UINTN)CurrentImageAddress + ExportNamePointerTable[Index]);
84 DEBUG ((
85 DEBUG_INFO,
86 " %a %a: Export Name[0x%x] - %a.\n",
87 _DBGMSGID_,
88 __func__,
89 Index,
90 CurrentExportName
91 ));
92 if (
94 PRM_STRING (PRM_MODULE_EXPORT_DESCRIPTOR_NAME),
95 CurrentExportName,
96 AsciiStrLen (PRM_STRING (PRM_MODULE_EXPORT_DESCRIPTOR_NAME))
97 ) == 0)
98 {
99 PrmModuleExportDescriptorOrdinal = OrdinalTable[Index];
100 DEBUG ((
101 DEBUG_INFO,
102 " %a %a: PRM Module Export Descriptor found. Ordinal = %d.\n",
103 _DBGMSGID_,
104 __func__,
105 PrmModuleExportDescriptorOrdinal
106 ));
107 if (PrmModuleExportDescriptorOrdinal >= ImageExportDirectory->NumberOfFunctions) {
108 DEBUG ((DEBUG_ERROR, "%a %a: The PRM Module Export Descriptor ordinal value is invalid.\n", _DBGMSGID_, __func__));
109 return EFI_NOT_FOUND;
110 }
111
112 TempExportDescriptor = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *)((UINTN)CurrentImageAddress + ExportAddressTable[PrmModuleExportDescriptorOrdinal]);
113 if (TempExportDescriptor->Header.Signature == PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE) {
114 *ExportDescriptor = TempExportDescriptor;
115 DEBUG ((DEBUG_INFO, " %a %a: PRM Module Export Descriptor found at 0x%x.\n", _DBGMSGID_, __func__, (UINTN)ExportDescriptor));
116 } else {
117 DEBUG ((
118 DEBUG_INFO,
119 " %a %a: PRM Module Export Descriptor found at 0x%x but signature check failed.\n",
120 _DBGMSGID_,
121 __func__,
122 (UINTN)TempExportDescriptor
123 ));
124 }
125
126 DEBUG ((DEBUG_INFO, " %a %a: Exiting export iteration since export descriptor found.\n", _DBGMSGID_, __func__));
127 return EFI_SUCCESS;
128 }
129 }
130
131 return EFI_NOT_FOUND;
132}
133
152 IN VOID *Image,
153 IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
154 OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory
155 )
156{
157 UINT16 Magic;
158 UINT32 NumberOfRvaAndSizes;
159 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
160 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
161 EFI_IMAGE_EXPORT_DIRECTORY *ExportDirectory;
162
163 if ((Image == NULL) || (PeCoffLoaderImageContext == NULL) || (ImageExportDirectory == NULL)) {
164 return EFI_INVALID_PARAMETER;
165 }
166
167 DirectoryEntry = NULL;
168 ExportDirectory = NULL;
169
170 //
171 // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
172 // image instead of using the Magic field. Some systems might generate a PE32+
173 // image with PE32 magic.
174 //
175 switch (PeCoffLoaderImageContext->Machine) {
177 //
178 // Assume PE32 image with IA32 Machine field.
179 //
181 break;
184 //
185 // Assume PE32+ image with X64 Machine field
186 //
188 break;
189 default:
190 //
191 // For unknown Machine field, use Magic in optional header
192 //
193 DEBUG ((
194 DEBUG_WARN,
195 "%a %a: The machine type for this image is not valid for a PRM module.\n",
196 _DBGMSGID_,
197 __func__
198 ));
199 return EFI_UNSUPPORTED;
200 }
201
202 OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(
203 (UINTN)Image +
204 PeCoffLoaderImageContext->PeCoffHeaderOffset
205 );
206
207 //
208 // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
209 //
210 if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
211 DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __func__));
212 return EFI_UNSUPPORTED;
213 }
214
216 //
217 // Use the PE32 offset to get the Export Directory Entry
218 //
219 NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32->OptionalHeader.NumberOfRvaAndSizes;
220 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHeaderPtrUnion.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
221 } else if (OptionalHeaderPtrUnion.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
222 //
223 // Use the PE32+ offset get the Export Directory Entry
224 //
225 NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
226 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
227 } else {
228 return EFI_UNSUPPORTED;
229 }
230
231 if ((NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_EXPORT) || (DirectoryEntry->VirtualAddress == 0)) {
232 //
233 // The export directory is not present
234 //
235 return EFI_NOT_FOUND;
236 } else if (((UINT32)(~0) - DirectoryEntry->VirtualAddress) < DirectoryEntry->Size) {
237 //
238 // The directory address overflows
239 //
240 DEBUG ((DEBUG_ERROR, "%a %a: The export directory entry in this image results in overflow.\n", _DBGMSGID_, __func__));
241 return EFI_UNSUPPORTED;
242 } else {
243 DEBUG ((DEBUG_INFO, "%a %a: Export Directory Entry found in the image at 0x%x.\n", _DBGMSGID_, __func__, (UINTN)OptionalHeaderPtrUnion.Pe32));
244 DEBUG ((DEBUG_INFO, " %a %a: Directory Entry Virtual Address = 0x%x.\n", _DBGMSGID_, __func__, DirectoryEntry->VirtualAddress));
245
246 ExportDirectory = (EFI_IMAGE_EXPORT_DIRECTORY *)((UINTN)Image + DirectoryEntry->VirtualAddress);
247 DEBUG ((
248 DEBUG_INFO,
249 " %a %a: Export Directory Table found successfully at 0x%x. Name address = 0x%x. Name = %a.\n",
250 _DBGMSGID_,
251 __func__,
252 (UINTN)ExportDirectory,
253 ((UINTN)Image + ExportDirectory->Name),
254 (CHAR8 *)((UINTN)Image + ExportDirectory->Name)
255 ));
256 }
257
258 *ImageExportDirectory = ExportDirectory;
259
260 return EFI_SUCCESS;
261}
262
281 IN VOID *Image,
282 IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
283 OUT UINT16 *ImageMajorVersion,
284 OUT UINT16 *ImageMinorVersion
285 )
286{
287 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
288 UINT16 Magic;
289
290 DEBUG ((DEBUG_INFO, " %a %a - Entry.\n", _DBGMSGID_, __func__));
291
292 if ((Image == NULL) || (PeCoffLoaderImageContext == NULL) || (ImageMajorVersion == NULL) || (ImageMinorVersion == NULL)) {
293 return EFI_INVALID_PARAMETER;
294 }
295
296 //
297 // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
298 // image instead of using the Magic field. Some systems might generate a PE32+
299 // image with PE32 magic.
300 //
301 switch (PeCoffLoaderImageContext->Machine) {
303 //
304 // Assume PE32 image
305 //
307 break;
310 //
311 // Assume PE32+ image
312 //
314 break;
315 default:
316 //
317 // For unknown Machine field, use Magic in optional header
318 //
319 DEBUG ((
320 DEBUG_WARN,
321 "%a %a: The machine type for this image is not valid for a PRM module.\n",
322 _DBGMSGID_,
323 __func__
324 ));
325 return EFI_UNSUPPORTED;
326 }
327
328 OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(
329 (UINTN)Image +
330 PeCoffLoaderImageContext->PeCoffHeaderOffset
331 );
332 //
333 // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
334 //
335 if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
336 DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __func__));
337 return EFI_UNSUPPORTED;
338 }
339
341 //
342 // Use the PE32 offset to get the Export Directory Entry
343 //
344 *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MajorImageVersion;
345 *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MinorImageVersion;
346 } else {
347 //
348 // Use the PE32+ offset to get the Export Directory Entry
349 //
350 *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MajorImageVersion;
351 *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MinorImageVersion;
352 }
353
354 DEBUG ((DEBUG_INFO, " %a %a - Image Major Version: 0x%02x.\n", _DBGMSGID_, __func__, *ImageMajorVersion));
355 DEBUG ((DEBUG_INFO, " %a %a - Image Minor Version: 0x%02x.\n", _DBGMSGID_, __func__, *ImageMinorVersion));
356
357 return EFI_SUCCESS;
358}
359
376 IN CONST CHAR8 *ExportName,
377 IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
378 IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
379 OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress
380 )
381{
382 UINTN ExportNameIndex;
383 UINT16 CurrentExportOrdinal;
384 UINT32 *ExportAddressTable;
385 UINT32 *ExportNamePointerTable;
386 UINT16 *OrdinalTable;
387 CONST CHAR8 *ExportNameTablePointerName;
388
389 if ((ExportName == NULL) || (ImageBaseAddress == 0) || (ImageExportDirectory == NULL) || (ExportPhysicalAddress == NULL)) {
390 return EFI_INVALID_PARAMETER;
391 }
392
393 *ExportPhysicalAddress = 0;
394
395 ExportAddressTable = (UINT32 *)((UINTN)ImageBaseAddress + ImageExportDirectory->AddressOfFunctions);
396 ExportNamePointerTable = (UINT32 *)((UINTN)ImageBaseAddress + ImageExportDirectory->AddressOfNames);
397 OrdinalTable = (UINT16 *)((UINTN)ImageBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
398
399 for (ExportNameIndex = 0; ExportNameIndex < ImageExportDirectory->NumberOfNames; ExportNameIndex++) {
400 ExportNameTablePointerName = (CONST CHAR8 *)((UINTN)ImageBaseAddress + ExportNamePointerTable[ExportNameIndex]);
401
402 if (AsciiStrnCmp (ExportName, ExportNameTablePointerName, PRM_HANDLER_NAME_MAXIMUM_LENGTH) == 0) {
403 CurrentExportOrdinal = OrdinalTable[ExportNameIndex];
404
405 ASSERT (CurrentExportOrdinal < ImageExportDirectory->NumberOfFunctions);
406 if (CurrentExportOrdinal >= ImageExportDirectory->NumberOfFunctions) {
407 DEBUG ((DEBUG_ERROR, " %a %a: The export ordinal value is invalid.\n", _DBGMSGID_, __func__));
408 break;
409 }
410
411 *ExportPhysicalAddress = (EFI_PHYSICAL_ADDRESS)((UINTN)ImageBaseAddress + ExportAddressTable[CurrentExportOrdinal]);
412 return EFI_SUCCESS;
413 }
414 }
415
416 return EFI_NOT_FOUND;
417}
UINT64 UINTN
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition: String.c:872
EFI_STATUS GetExportDirectoryInPeCoffImage(IN VOID *Image, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory)
EFI_STATUS GetPrmModuleExportDescriptorTable(IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT **ExportDescriptor)
EFI_STATUS GetImageVersionInPeCoffImage(IN VOID *Image, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT UINT16 *ImageMajorVersion, OUT UINT16 *ImageMinorVersion)
EFI_STATUS GetExportEntryAddress(IN CONST CHAR8 *ExportName, IN EFI_PHYSICAL_ADDRESS ImageBaseAddress, IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory, OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:143
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: PeImage.h:194
#define EFI_IMAGE_MACHINE_AARCH64
Definition: UefiBaseType.h:243
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_IMAGE_MACHINE_IA32
Definition: UefiBaseType.h:218
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_IMAGE_MACHINE_X64
Definition: UefiBaseType.h:233
#define EFI_SUCCESS
Definition: UefiBaseType.h:112