Skip to content
This repository was archived by the owner on May 5, 2025. It is now read-only.

Commit 9c574c5

Browse files
libefiwrapper/pe: support 32-bits images relocation
Change-Id: I21832c9da1ff080a1ed0f4a47e2ea87636e10dfa Signed-off-by: Jeremy Compostella <[email protected]>
1 parent f9dc6dc commit 9c574c5

File tree

1 file changed

+59
-3
lines changed

1 file changed

+59
-3
lines changed

libefiwrapper/pe.c

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ typedef struct {
133133
struct {
134134
std_coff_t std;
135135
win_t win;
136-
struct {
136+
struct data_directory {
137137
UINT32 address;
138138
UINT32 size;
139139
} data_directory[16];
@@ -153,6 +153,30 @@ typedef struct {
153153
UINT32 characteristics;
154154
} section_header_t;
155155

156+
typedef struct {
157+
UINT32 virtual_address;
158+
UINT32 size_of_block;
159+
} relocation_t;
160+
161+
typedef enum {
162+
ABSOLUTE,
163+
HIGH,
164+
LOW,
165+
HIGHLOW,
166+
HIGHADJ,
167+
MACHINE_SPECIFIC_5,
168+
RESERVED,
169+
MACHINE_SPECIFIC_7,
170+
MACHINE_SPECIFIC_8,
171+
MACHINE_SPECIFIC_9,
172+
DIR64
173+
} fixup_type_t;
174+
175+
typedef struct {
176+
UINT16 offset: 12;
177+
UINT8 type: 4;
178+
} fixup_t;
179+
156180
#pragma pack()
157181

158182
typedef struct {
@@ -181,7 +205,7 @@ static void get_section_boundaries(section_header_t *section, UINT16 nb,
181205

182206
static EFI_STATUS load_sections(section_header_t *section, UINT16 nb,
183207
void *base, image_t *image,
184-
size_t alignment)
208+
size_t alignment, loaded_section_t **data_p)
185209
{
186210
loaded_section_t *data;
187211
UINT16 i;
@@ -229,15 +253,41 @@ static EFI_STATUS load_sections(section_header_t *section, UINT16 nb,
229253
ewdbg(".text section loaded at %p", dst);
230254
}
231255

256+
*data_p = data;
232257
return EFI_SUCCESS;
233258
}
234259

260+
static void relocate(loaded_section_t *data, UINT32 base, relocation_t *table,
261+
UINT32 size)
262+
{
263+
relocation_t *table_end = (relocation_t *)((UINT8 *)table + size);
264+
unsigned long diff = (unsigned long)data->addr - base - data->start;
265+
266+
while (table < table_end) {
267+
fixup_t *fixup = (fixup_t *)&table[1];
268+
fixup_t *fixup_end = (fixup_t *)((char *)table + table->size_of_block);
269+
unsigned char *mem = (unsigned char *)data->addr +
270+
table->virtual_address - data->start;
271+
272+
for (; fixup < fixup_end; fixup++) {
273+
if (*(UINT16 *)fixup == 0)
274+
break;
275+
if (fixup->type != HIGHLOW)
276+
continue;
277+
*(UINT32 *)&mem[fixup->offset] += diff;
278+
}
279+
table = (relocation_t *)fixup_end;
280+
}
281+
}
282+
235283
EFI_STATUS pe_load(void *data, UINTN size, image_t *image)
236284
{
237285
EFI_STATUS ret;
238286
dos_header_t *dos_hdr;
239287
pe_coff_t *pe;
240288
char *entry;
289+
loaded_section_t *section;
290+
struct data_directory *reloc_dir;
241291

242292
if (!data || !size || !image)
243293
return EFI_INVALID_PARAMETER;
@@ -261,10 +311,16 @@ EFI_STATUS pe_load(void *data, UINTN size, image_t *image)
261311

262312
ret = load_sections((section_header_t *)(pe + 1),
263313
pe->hdr.number_of_sections,
264-
data, image, pe->opt.win.section_alignment);
314+
data, image, pe->opt.win.section_alignment,
315+
&section);
265316
if (EFI_ERROR(ret))
266317
return ret;
267318

319+
reloc_dir = &pe->opt.data_directory[BASERELOC_DIRECTORY_ENTRY];
320+
relocate((loaded_section_t *)image->data, pe->opt.win.image_base,
321+
section->addr + reloc_dir->address - section->start,
322+
reloc_dir->size);
323+
268324
entry = (char *)((loaded_section_t *)image->data)->addr;
269325
entry += pe->opt.std.address_of_entry_point;
270326
entry -= ((loaded_section_t *)image->data)->start;

0 commit comments

Comments
 (0)