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
34 #define PE_HEADER_MACHINE_ARM 0x01c2
35 #define PE_HEADER_MACHINE_RISCV64 0x5064
38 UINT16 NumberOfSections
;
40 UINT32 PointerToSymbolTable
;
41 UINT32 NumberOfSymbols
;
42 UINT16 SizeOfOptionalHeader
;
43 UINT16 Characteristics
;
44 } __attribute__((packed
));
48 struct PeFileHeader FileHeader
;
49 } __attribute__((packed
));
51 struct PeSectionHeader
{
54 UINT32 VirtualAddress
;
56 UINT32 PointerToRawData
;
57 UINT32 PointerToRelocations
;
58 UINT32 PointerToLinenumbers
;
59 UINT16 NumberOfRelocations
;
60 UINT16 NumberOfLinenumbers
;
61 UINT32 Characteristics
;
62 } __attribute__((packed
));
64 EFI_STATUS
pe_memory_locate_sections(CHAR8
*base
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
65 struct DosFileHeader
*dos
;
69 dos
= (struct DosFileHeader
*)base
;
71 if (CompareMem(dos
->Magic
, "MZ", 2) != 0)
72 return EFI_LOAD_ERROR
;
74 pe
= (struct PeHeader
*)&base
[dos
->ExeHeader
];
75 if (CompareMem(pe
->Magic
, "PE\0\0", 4) != 0)
76 return EFI_LOAD_ERROR
;
78 /* PE32+ Subsystem type */
79 if (pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_X64
&&
80 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_ARM64
&&
81 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_I386
&&
82 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_ARM
&&
83 pe
->FileHeader
.Machine
!= PE_HEADER_MACHINE_RISCV64
)
84 return EFI_LOAD_ERROR
;
86 if (pe
->FileHeader
.NumberOfSections
> 96)
87 return EFI_LOAD_ERROR
;
89 offset
= dos
->ExeHeader
+ sizeof(*pe
) + pe
->FileHeader
.SizeOfOptionalHeader
;
91 for (UINTN i
= 0; i
< pe
->FileHeader
.NumberOfSections
; i
++) {
92 struct PeSectionHeader
*sect
;
94 sect
= (struct PeSectionHeader
*)&base
[offset
];
95 for (UINTN j
= 0; sections
[j
]; j
++) {
96 if (CompareMem(sect
->Name
, sections
[j
], strlena(sections
[j
])) != 0)
100 addrs
[j
] = (UINTN
)sect
->VirtualAddress
;
102 offsets
[j
] = (UINTN
)sect
->PointerToRawData
;
104 sizes
[j
] = (UINTN
)sect
->VirtualSize
;
106 offset
+= sizeof(*sect
);
112 EFI_STATUS
pe_file_locate_sections(EFI_FILE
*dir
, CHAR16
*path
, CHAR8
**sections
, UINTN
*addrs
, UINTN
*offsets
, UINTN
*sizes
) {
113 EFI_FILE_HANDLE handle
;
114 struct DosFileHeader dos
;
119 _cleanup_freepool_ CHAR8
*header
= NULL
;
121 err
= uefi_call_wrapper(dir
->Open
, 5, dir
, &handle
, path
, EFI_FILE_MODE_READ
, 0ULL);
127 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &dos
);
130 if (len
!= sizeof(dos
)) {
131 err
= EFI_LOAD_ERROR
;
135 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, dos
.ExeHeader
);
140 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, &pe
);
143 if (len
!= sizeof(pe
)) {
144 err
= EFI_LOAD_ERROR
;
148 headerlen
= sizeof(dos
) + sizeof(pe
) + pe
.FileHeader
.SizeOfOptionalHeader
+ pe
.FileHeader
.NumberOfSections
* sizeof(struct PeSectionHeader
);
149 header
= AllocatePool(headerlen
);
151 err
= EFI_OUT_OF_RESOURCES
;
155 err
= uefi_call_wrapper(handle
->SetPosition
, 2, handle
, 0);
159 err
= uefi_call_wrapper(handle
->Read
, 3, handle
, &len
, header
);
163 if (len
!= headerlen
) {
164 err
= EFI_LOAD_ERROR
;
168 err
= pe_memory_locate_sections(header
, sections
, addrs
, offsets
, sizes
);
170 uefi_call_wrapper(handle
->Close
, 1, handle
);