1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
29 } __attribute__((packed
));
31 #define PE_HEADER_MACHINE_I386 0x014c
32 #define PE_HEADER_MACHINE_X64 0x8664
33 #define PE_HEADER_MACHINE_ARM64 0xaa64
36 UINT16 NumberOfSections
;
38 UINT32 PointerToSymbolTable
;
39 UINT32 NumberOfSymbols
;
40 UINT16 SizeOfOptionalHeader
;
41 UINT16 Characteristics
;
42 } __attribute__((packed
));
46 struct PeFileHeader FileHeader
;
47 } __attribute__((packed
));
49 struct PeSectionHeader
{
52 UINT32 VirtualAddress
;
54 UINT32 PointerToRawData
;
55 UINT32 PointerToRelocations
;
56 UINT32 PointerToLinenumbers
;
57 UINT16 NumberOfRelocations
;
58 UINT16 NumberOfLinenumbers
;
59 UINT32 Characteristics
;
60 } __attribute__((packed
));
62 EFI_STATUS
pe_memory_locate_sections(CHAR8
*base
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
63 struct DosFileHeader
*dos
;
68 dos
= (struct DosFileHeader
*)base
;
70 if (CompareMem(dos
->Magic
, "MZ", 2) != 0)
71 return EFI_LOAD_ERROR
;
73 pe
= (struct PeHeader
*)&base
[dos
->ExeHeader
];
74 if (CompareMem(pe
->Magic
, "PE\0\0", 4) != 0)
75 return EFI_LOAD_ERROR
;
77 /* PE32+ Subsystem type */
78 if (pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_X64
&&
79 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_ARM64
&&
80 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_I386
)
81 return EFI_LOAD_ERROR
;
83 if (pe
->FileHeader
.NumberOfSections
> 96)
84 return EFI_LOAD_ERROR
;
86 offset
= dos
->ExeHeader
+ sizeof(*pe
) + pe
->FileHeader
.SizeOfOptionalHeader
;
88 for (i
= 0; i
< pe
->FileHeader
.NumberOfSections
; i
++) {
89 struct PeSectionHeader
*sect
;
92 sect
= (struct PeSectionHeader
*)&base
[offset
];
93 for (j
= 0; sections
[j
]; j
++) {
94 if (CompareMem(sect
->Name
, sections
[j
], strlena(sections
[j
])) != 0)
98 addrs
[j
] = (UINTN
)sect
->VirtualAddress
;
100 offsets
[j
] = (UINTN
)sect
->PointerToRawData
;
102 sizes
[j
] = (UINTN
)sect
->VirtualSize
;
104 offset
+= sizeof(*sect
);
110 EFI_STATUS
pe_file_locate_sections(EFI_FILE
*dir
, CHAR16
*path
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
111 EFI_FILE_HANDLE handle
;
112 struct DosFileHeader dos
;
117 _cleanup_freepool_ CHAR8
*header
= NULL
;
119 err
= uefi_call_wrapper(dir
->Open
, 5, dir
, &handle
, path
, EFI_FILE_MODE_READ
, 0ULL);
125 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &dos
);
128 if (len
!= sizeof(dos
)) {
129 err
= EFI_LOAD_ERROR
;
133 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, dos
.ExeHeader
);
138 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &pe
);
141 if (len
!= sizeof(pe
)) {
142 err
= EFI_LOAD_ERROR
;
146 headerlen
= sizeof(dos
) + sizeof(pe
) + pe
.FileHeader
.SizeOfOptionalHeader
+ pe
.FileHeader
.NumberOfSections
* sizeof(struct PeSectionHeader
);
147 header
= AllocatePool(headerlen
);
149 err
= EFI_OUT_OF_RESOURCES
;
153 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, 0);
157 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, header
);
161 if (len
!= headerlen
) {
162 err
= EFI_LOAD_ERROR
;
166 err
= pe_memory_locate_sections(header
, sections
, addrs
, offsets
, sizes
);
168 uefi_call_wrapper(handle
->Close
, 1, handle
);