1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
23 struct DosFileHeader
{
43 } __attribute__((packed
));
45 #define PE_HEADER_MACHINE_I386 0x014c
46 #define PE_HEADER_MACHINE_X64 0x8664
49 UINT16 NumberOfSections
;
51 UINT32 PointerToSymbolTable
;
52 UINT32 NumberOfSymbols
;
53 UINT16 SizeOfOptionalHeader
;
54 UINT16 Characteristics
;
55 } __attribute__((packed
));
57 struct PeSectionHeader
{
60 UINT32 VirtualAddress
;
62 UINT32 PointerToRawData
;
63 UINT32 PointerToRelocations
;
64 UINT32 PointerToLinenumbers
;
65 UINT16 NumberOfRelocations
;
66 UINT16 NumberOfLinenumbers
;
67 UINT32 Characteristics
;
68 } __attribute__((packed
));
71 EFI_STATUS
pefile_locate_sections(EFI_FILE
*dir
, CHAR16
*path
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
72 EFI_FILE_HANDLE handle
;
73 struct DosFileHeader dos
;
75 struct PeFileHeader pe
;
80 err
= uefi_call_wrapper(dir
->Open
, 5, dir
, &handle
, path
, EFI_FILE_MODE_READ
, 0ULL);
86 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &dos
);
89 if (len
!= sizeof(dos
)) {
94 if (CompareMem(dos
.Magic
, "MZ", 2) != 0) {
99 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, dos
.ExeHeader
);
105 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &magic
);
108 if (len
!= sizeof(magic
)) {
109 err
= EFI_LOAD_ERROR
;
113 if (CompareMem(magic
, "PE\0\0", 2) != 0) {
114 err
= EFI_LOAD_ERROR
;
119 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &pe
);
122 if (len
!= sizeof(pe
)) {
123 err
= EFI_LOAD_ERROR
;
127 /* PE32+ Subsystem type */
128 if (pe
.Machine
!= PE_HEADER_MACHINE_X64
&&
129 pe
.Machine
!= PE_HEADER_MACHINE_I386
) {
130 err
= EFI_LOAD_ERROR
;
134 if (pe
.NumberOfSections
> 96) {
135 err
= EFI_LOAD_ERROR
;
139 /* the sections start directly after the headers */
140 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, dos
.ExeHeader
+ sizeof(magic
) + sizeof(pe
) + pe
.SizeOfOptionalHeader
);
144 for (i
= 0; i
< pe
.NumberOfSections
; i
++) {
145 struct PeSectionHeader sect
;
149 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, §
);
152 if (len
!= sizeof(sect
)) {
153 err
= EFI_LOAD_ERROR
;
156 for (j
= 0; sections
[j
]; j
++) {
157 if (CompareMem(sect
.Name
, sections
[j
], strlena(sections
[j
])) != 0)
161 addrs
[j
] = (UINTN
)sect
.VirtualAddress
;
163 offsets
[j
] = (UINTN
)sect
.PointerToRawData
;
165 sizes
[j
] = (UINTN
)sect
.VirtualSize
;
170 uefi_call_wrapper(handle
->Close
, 1, handle
);