1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
22 struct DosFileHeader
{
42 } __attribute__((packed
));
44 #define PE_HEADER_MACHINE_I386 0x014c
45 #define PE_HEADER_MACHINE_X64 0x8664
48 UINT16 NumberOfSections
;
50 UINT32 PointerToSymbolTable
;
51 UINT32 NumberOfSymbols
;
52 UINT16 SizeOfOptionalHeader
;
53 UINT16 Characteristics
;
54 } __attribute__((packed
));
58 struct PeFileHeader FileHeader
;
59 } __attribute__((packed
));
61 struct PeSectionHeader
{
64 UINT32 VirtualAddress
;
66 UINT32 PointerToRawData
;
67 UINT32 PointerToRelocations
;
68 UINT32 PointerToLinenumbers
;
69 UINT16 NumberOfRelocations
;
70 UINT16 NumberOfLinenumbers
;
71 UINT32 Characteristics
;
72 } __attribute__((packed
));
74 EFI_STATUS
pe_memory_locate_sections(CHAR8
*base
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
75 struct DosFileHeader
*dos
;
80 dos
= (struct DosFileHeader
*)base
;
82 if (CompareMem(dos
->Magic
, "MZ", 2) != 0)
83 return EFI_LOAD_ERROR
;
85 pe
= (struct PeHeader
*)&base
[dos
->ExeHeader
];
86 if (CompareMem(pe
->Magic
, "PE\0\0", 4) != 0)
87 return EFI_LOAD_ERROR
;
89 /* PE32+ Subsystem type */
90 if (pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_X64
&&
91 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_I386
)
92 return EFI_LOAD_ERROR
;
94 if (pe
->FileHeader
.NumberOfSections
> 96)
95 return EFI_LOAD_ERROR
;
97 offset
= dos
->ExeHeader
+ sizeof(*pe
) + pe
->FileHeader
.SizeOfOptionalHeader
;
99 for (i
= 0; i
< pe
->FileHeader
.NumberOfSections
; i
++) {
100 struct PeSectionHeader
*sect
;
103 sect
= (struct PeSectionHeader
*)&base
[offset
];
104 for (j
= 0; sections
[j
]; j
++) {
105 if (CompareMem(sect
->Name
, sections
[j
], strlena(sections
[j
])) != 0)
109 addrs
[j
] = (UINTN
)sect
->VirtualAddress
;
111 offsets
[j
] = (UINTN
)sect
->PointerToRawData
;
113 sizes
[j
] = (UINTN
)sect
->VirtualSize
;
115 offset
+= sizeof(*sect
);
121 EFI_STATUS
pe_file_locate_sections(EFI_FILE
*dir
, CHAR16
*path
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
122 EFI_FILE_HANDLE handle
;
123 struct DosFileHeader dos
;
128 CHAR8
*header
= NULL
;
130 err
= uefi_call_wrapper(dir
->Open
, 5, dir
, &handle
, path
, EFI_FILE_MODE_READ
, 0ULL);
136 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &dos
);
139 if (len
!= sizeof(dos
)) {
140 err
= EFI_LOAD_ERROR
;
144 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, dos
.ExeHeader
);
149 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &pe
);
152 if (len
!= sizeof(pe
)) {
153 err
= EFI_LOAD_ERROR
;
157 headerlen
= sizeof(dos
) + sizeof(pe
) + pe
.FileHeader
.SizeOfOptionalHeader
+ pe
.FileHeader
.NumberOfSections
* sizeof(struct PeSectionHeader
);
158 header
= AllocatePool(headerlen
);
160 err
= EFI_OUT_OF_RESOURCES
;
164 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, 0);
168 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, header
);
169 if (EFI_ERROR(err
)) {
172 if (len
!= headerlen
) {
173 err
= EFI_LOAD_ERROR
;
177 err
= pe_memory_locate_sections(header
, sections
, addrs
, offsets
, sizes
);
181 uefi_call_wrapper(handle
->Close
, 1, handle
);