TianoCore EDK2 master
Loading...
Searching...
No Matches
ElfLib.c
Go to the documentation of this file.
1
9#include "ElfLibInternal.h"
10
19BOOLEAN
21 IN CONST UINT8 *ImageBase
22 )
23{
24 Elf32_Ehdr *Elf32Hdr;
25 Elf64_Ehdr *Elf64Hdr;
26
27 ASSERT (ImageBase != NULL);
28
29 Elf32Hdr = (Elf32_Ehdr *)ImageBase;
30
31 //
32 // Start with correct signature "\7fELF"
33 //
34 if ((Elf32Hdr->e_ident[EI_MAG0] != ELFMAG0) ||
35 (Elf32Hdr->e_ident[EI_MAG1] != ELFMAG1) ||
36 (Elf32Hdr->e_ident[EI_MAG1] != ELFMAG1) ||
37 (Elf32Hdr->e_ident[EI_MAG2] != ELFMAG2)
38 )
39 {
40 return FALSE;
41 }
42
43 //
44 // Support little-endian only
45 //
46 if (Elf32Hdr->e_ident[EI_DATA] != ELFDATA2LSB) {
47 return FALSE;
48 }
49
50 //
51 // Check 32/64-bit architecture
52 //
53 if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS64) {
54 Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr;
55 Elf32Hdr = NULL;
56 } else if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS32) {
57 Elf64Hdr = NULL;
58 } else {
59 return FALSE;
60 }
61
62 if (Elf64Hdr != NULL) {
63 //
64 // Support intel architecture only for now
65 //
66 if (Elf64Hdr->e_machine != EM_X86_64) {
67 return FALSE;
68 }
69
70 //
71 // Support ELF types: EXEC (Executable file), DYN (Shared object file)
72 //
73 if ((Elf64Hdr->e_type != ET_EXEC) && (Elf64Hdr->e_type != ET_DYN)) {
74 return FALSE;
75 }
76
77 //
78 // Support current ELF version only
79 //
80 if (Elf64Hdr->e_version != EV_CURRENT) {
81 return FALSE;
82 }
83 } else {
84 //
85 // Support intel architecture only for now
86 //
87 if (Elf32Hdr->e_machine != EM_386) {
88 return FALSE;
89 }
90
91 //
92 // Support ELF types: EXEC (Executable file), DYN (Shared object file)
93 //
94 if ((Elf32Hdr->e_type != ET_EXEC) && (Elf32Hdr->e_type != ET_DYN)) {
95 return FALSE;
96 }
97
98 //
99 // Support current ELF version only
100 //
101 if (Elf32Hdr->e_version != EV_CURRENT) {
102 return FALSE;
103 }
104 }
105
106 return TRUE;
107}
108
121 IN ELF_IMAGE_CONTEXT *ElfCt,
122 OUT UINTN *FileSize
123 )
124{
125 EFI_STATUS Status;
126 UINTN FileSize1;
127 UINTN FileSize2;
128 Elf32_Ehdr *Elf32Hdr;
129 Elf64_Ehdr *Elf64Hdr;
130 UINTN Offset;
131 UINTN Size;
132
133 if ((ElfCt == NULL) || (FileSize == NULL)) {
134 return EFI_INVALID_PARAMETER;
135 }
136
137 // Use last section as end of file
138 Status = GetElfSectionPos (ElfCt, ElfCt->ShNum - 1, &Offset, &Size);
139 if (EFI_ERROR (Status)) {
140 return EFI_UNSUPPORTED;
141 }
142
143 FileSize1 = Offset + Size;
144
145 // Use end of section header as end of file
146 FileSize2 = 0;
147 if (ElfCt->EiClass == ELFCLASS32) {
148 Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase;
149 FileSize2 = Elf32Hdr->e_shoff + Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum;
150 } else if (ElfCt->EiClass == ELFCLASS64) {
151 Elf64Hdr = (Elf64_Ehdr *)ElfCt->FileBase;
152 FileSize2 = ((UINTN)Elf64Hdr->e_shoff + (UINTN)(Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum));
153 }
154
155 *FileSize = MAX (FileSize1, FileSize2);
156
157 return EFI_SUCCESS;
158}
159
174 IN UINT8 *ImageBase,
175 IN UINT32 EiClass,
176 IN UINT32 Index,
177 OUT SEGMENT_INFO *SegInfo
178 )
179{
180 Elf32_Phdr *Elf32Phdr;
181 Elf64_Phdr *Elf64Phdr;
182
183 if ((ImageBase == NULL) || (SegInfo == NULL)) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 if (EiClass == ELFCLASS32) {
188 Elf32Phdr = GetElf32SegmentByIndex (ImageBase, Index);
189 if (Elf32Phdr != NULL) {
190 SegInfo->PtType = Elf32Phdr->p_type;
191 SegInfo->Offset = Elf32Phdr->p_offset;
192 SegInfo->Length = Elf32Phdr->p_filesz;
193 SegInfo->MemLen = Elf32Phdr->p_memsz;
194 SegInfo->MemAddr = Elf32Phdr->p_paddr;
195 SegInfo->Alignment = Elf32Phdr->p_align;
196 return EFI_SUCCESS;
197 }
198 } else if (EiClass == ELFCLASS64) {
199 Elf64Phdr = GetElf64SegmentByIndex (ImageBase, Index);
200 if (Elf64Phdr != NULL) {
201 SegInfo->PtType = Elf64Phdr->p_type;
202 SegInfo->Offset = (UINTN)Elf64Phdr->p_offset;
203 SegInfo->Length = (UINTN)Elf64Phdr->p_filesz;
204 SegInfo->MemLen = (UINTN)Elf64Phdr->p_memsz;
205 SegInfo->MemAddr = (UINTN)Elf64Phdr->p_paddr;
206 SegInfo->Alignment = (UINTN)Elf64Phdr->p_align;
207 return EFI_SUCCESS;
208 }
209 }
210
211 return EFI_NOT_FOUND;
212}
213
228EFIAPI
230 IN VOID *ImageBase,
232 )
233{
234 Elf32_Ehdr *Elf32Hdr;
235 Elf64_Ehdr *Elf64Hdr;
236 Elf32_Shdr *Elf32Shdr;
237 Elf64_Shdr *Elf64Shdr;
238 EFI_STATUS Status;
239 UINT32 Index;
240 SEGMENT_INFO SegInfo;
241 UINTN End;
242 UINTN Base;
243
244 if (ElfCt == NULL) {
245 return EFI_INVALID_PARAMETER;
246 }
247
248 ZeroMem (ElfCt, sizeof (ELF_IMAGE_CONTEXT));
249
250 if (ImageBase == NULL) {
251 return (ElfCt->ParseStatus = EFI_INVALID_PARAMETER);
252 }
253
254 ElfCt->FileBase = (UINT8 *)ImageBase;
255 if (!IsElfFormat (ElfCt->FileBase)) {
256 return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
257 }
258
259 Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase;
260 ElfCt->EiClass = Elf32Hdr->e_ident[EI_CLASS];
261 if (ElfCt->EiClass == ELFCLASS32) {
262 if ((Elf32Hdr->e_type != ET_EXEC) && (Elf32Hdr->e_type != ET_DYN)) {
263 return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
264 }
265
266 Elf32Shdr = (Elf32_Shdr *)GetElf32SectionByIndex (ElfCt->FileBase, Elf32Hdr->e_shstrndx);
267 if (Elf32Shdr == NULL) {
268 return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
269 }
270
271 ElfCt->EntryPoint = (UINTN)Elf32Hdr->e_entry;
272 ElfCt->ShNum = Elf32Hdr->e_shnum;
273 ElfCt->PhNum = Elf32Hdr->e_phnum;
274 ElfCt->ShStrLen = Elf32Shdr->sh_size;
275 ElfCt->ShStrOff = Elf32Shdr->sh_offset;
276 } else {
277 Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr;
278 if ((Elf64Hdr->e_type != ET_EXEC) && (Elf64Hdr->e_type != ET_DYN)) {
279 return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
280 }
281
282 Elf64Shdr = (Elf64_Shdr *)GetElf64SectionByIndex (ElfCt->FileBase, Elf64Hdr->e_shstrndx);
283 if (Elf64Shdr == NULL) {
284 return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
285 }
286
287 ElfCt->EntryPoint = (UINTN)Elf64Hdr->e_entry;
288 ElfCt->ShNum = Elf64Hdr->e_shnum;
289 ElfCt->PhNum = Elf64Hdr->e_phnum;
290 ElfCt->ShStrLen = (UINT32)Elf64Shdr->sh_size;
291 ElfCt->ShStrOff = (UINT32)Elf64Shdr->sh_offset;
292 }
293
294 //
295 // Get the preferred image base and required memory size when loaded to new location.
296 //
297 End = 0;
298 Base = MAX_UINT32;
299 ElfCt->ReloadRequired = FALSE;
300 for (Index = 0; Index < ElfCt->PhNum; Index++) {
301 Status = GetElfSegmentInfo (ElfCt->FileBase, ElfCt->EiClass, Index, &SegInfo);
302 ASSERT_EFI_ERROR (Status);
303
304 if (SegInfo.PtType != PT_LOAD) {
305 continue;
306 }
307
308 if (SegInfo.MemLen != SegInfo.Length) {
309 //
310 // Not enough space to execute at current location.
311 //
312 ElfCt->ReloadRequired = TRUE;
313 }
314
315 if (Base > (SegInfo.MemAddr & ~(EFI_PAGE_SIZE - 1))) {
316 Base = SegInfo.MemAddr & ~(EFI_PAGE_SIZE - 1);
317 }
318
319 if (End < ALIGN_VALUE (SegInfo.MemAddr + SegInfo.MemLen, EFI_PAGE_SIZE) - 1) {
320 End = ALIGN_VALUE (SegInfo.MemAddr + SegInfo.MemLen, EFI_PAGE_SIZE) - 1;
321 }
322 }
323
324 //
325 // 0 - MAX_UINT32 + 1 equals to 0.
326 //
327 ElfCt->ImageSize = End - Base + 1;
328 ElfCt->PreferredImageAddress = (VOID *)Base;
329
330 CalculateElfFileSize (ElfCt, &ElfCt->FileSize);
331 return (ElfCt->ParseStatus = EFI_SUCCESS);
332}
333
350EFIAPI
352 IN ELF_IMAGE_CONTEXT *ElfCt
353 )
354{
355 EFI_STATUS Status;
356
357 if (ElfCt == NULL) {
358 return EFI_INVALID_PARAMETER;
359 }
360
361 if (EFI_ERROR (ElfCt->ParseStatus)) {
362 return ElfCt->ParseStatus;
363 }
364
365 if (ElfCt->ImageAddress == NULL) {
366 return EFI_INVALID_PARAMETER;
367 }
368
369 Status = EFI_UNSUPPORTED;
370 if (ElfCt->EiClass == ELFCLASS32) {
371 Status = LoadElf32Image (ElfCt);
372 } else if (ElfCt->EiClass == ELFCLASS64) {
373 Status = LoadElf64Image (ElfCt);
374 }
375
376 return Status;
377}
378
391EFIAPI
393 IN ELF_IMAGE_CONTEXT *ElfCt,
394 IN UINT32 SectionIndex,
395 OUT CHAR8 **SectionName
396 )
397{
398 Elf32_Shdr *Elf32Shdr;
399 Elf64_Shdr *Elf64Shdr;
400 CHAR8 *Name;
401
402 if ((ElfCt == NULL) || (SectionName == NULL)) {
403 return EFI_INVALID_PARAMETER;
404 }
405
406 if (EFI_ERROR (ElfCt->ParseStatus)) {
407 return ElfCt->ParseStatus;
408 }
409
410 Name = NULL;
411 if (ElfCt->EiClass == ELFCLASS32) {
412 Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, SectionIndex);
413 if ((Elf32Shdr != NULL) && (Elf32Shdr->sh_name < ElfCt->ShStrLen)) {
414 Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf32Shdr->sh_name);
415 }
416 } else if (ElfCt->EiClass == ELFCLASS64) {
417 Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, SectionIndex);
418 if ((Elf64Shdr != NULL) && (Elf64Shdr->sh_name < ElfCt->ShStrLen)) {
419 Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf64Shdr->sh_name);
420 }
421 }
422
423 if (Name == NULL) {
424 return EFI_NOT_FOUND;
425 }
426
427 *SectionName = Name;
428 return EFI_SUCCESS;
429}
430
445EFIAPI
447 IN ELF_IMAGE_CONTEXT *ElfCt,
448 IN UINT32 Index,
449 OUT UINTN *Offset,
450 OUT UINTN *Size
451 )
452{
453 Elf32_Shdr *Elf32Shdr;
454 Elf64_Shdr *Elf64Shdr;
455
456 if ((ElfCt == NULL) || (Offset == NULL) || (Size == NULL)) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 if (EFI_ERROR (ElfCt->ParseStatus)) {
461 return ElfCt->ParseStatus;
462 }
463
464 if (ElfCt->EiClass == ELFCLASS32) {
465 Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, Index);
466 if (Elf32Shdr != NULL) {
467 *Offset = (UINTN)Elf32Shdr->sh_offset;
468 *Size = (UINTN)Elf32Shdr->sh_size;
469 return EFI_SUCCESS;
470 }
471 } else if (ElfCt->EiClass == ELFCLASS64) {
472 Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, Index);
473 if (Elf64Shdr != NULL) {
474 *Offset = (UINTN)Elf64Shdr->sh_offset;
475 *Size = (UINTN)Elf64Shdr->sh_size;
476 return EFI_SUCCESS;
477 }
478 }
479
480 return EFI_NOT_FOUND;
481}
UINT64 UINTN
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
Elf32_Phdr * GetElf32SegmentByIndex(IN UINT8 *ImageBase, IN UINT32 Index)
Definition: Elf32Lib.c:44
EFI_STATUS LoadElf32Image(IN ELF_IMAGE_CONTEXT *ElfCt)
Definition: Elf32Lib.c:430
Elf32_Shdr * GetElf32SectionByIndex(IN UINT8 *ImageBase, IN UINT32 Index)
Definition: Elf32Lib.c:20
Elf64_Shdr * GetElf64SectionByIndex(IN UINT8 *ImageBase, IN UINT32 Index)
Definition: Elf64Lib.c:20
EFI_STATUS LoadElf64Image(IN ELF_IMAGE_CONTEXT *ElfCt)
Definition: Elf64Lib.c:439
Elf64_Phdr * GetElf64SegmentByIndex(IN UINT8 *ImageBase, IN UINT32 Index)
Definition: Elf64Lib.c:44
EFI_STATUS EFIAPI LoadElfImage(IN ELF_IMAGE_CONTEXT *ElfCt)
Definition: ElfLib.c:351
EFI_STATUS EFIAPI GetElfSectionName(IN ELF_IMAGE_CONTEXT *ElfCt, IN UINT32 SectionIndex, OUT CHAR8 **SectionName)
Definition: ElfLib.c:392
EFI_STATUS GetElfSegmentInfo(IN UINT8 *ImageBase, IN UINT32 EiClass, IN UINT32 Index, OUT SEGMENT_INFO *SegInfo)
Definition: ElfLib.c:173
BOOLEAN IsElfFormat(IN CONST UINT8 *ImageBase)
Definition: ElfLib.c:20
EFI_STATUS CalculateElfFileSize(IN ELF_IMAGE_CONTEXT *ElfCt, OUT UINTN *FileSize)
Definition: ElfLib.c:120
EFI_STATUS EFIAPI GetElfSectionPos(IN ELF_IMAGE_CONTEXT *ElfCt, IN UINT32 Index, OUT UINTN *Offset, OUT UINTN *Size)
Definition: ElfLib.c:446
EFI_STATUS EFIAPI ParseElfImage(IN VOID *ImageBase, OUT ELF_IMAGE_CONTEXT *ElfCt)
Definition: ElfLib.c:229
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112