1 /* grub-mkimage.c - make a bootable image */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
23 #if defined(MKIMAGE_ELF32)
24 # define SUFFIX(x) x ## 32
25 # define ELFCLASSXX ELFCLASS32
26 # define Elf_Ehdr Elf32_Ehdr
27 # define Elf_Phdr Elf32_Phdr
28 # define Elf_Nhdr Elf32_Nhdr
29 # define Elf_Addr Elf32_Addr
30 # define Elf_Sym Elf32_Sym
31 # define Elf_Off Elf32_Off
32 # define Elf_Shdr Elf32_Shdr
33 # define Elf_Rela Elf32_Rela
34 # define Elf_Rel Elf32_Rel
35 # define Elf_Word Elf32_Word
36 # define Elf_Half Elf32_Half
37 # define Elf_Section Elf32_Section
38 # define ELF_R_SYM(val) ELF32_R_SYM(val)
39 # define ELF_R_TYPE(val) ELF32_R_TYPE(val)
40 # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
41 #define XEN_NOTE_SIZE 132
42 #elif defined(MKIMAGE_ELF64)
43 # define SUFFIX(x) x ## 64
44 # define ELFCLASSXX ELFCLASS64
45 # define Elf_Ehdr Elf64_Ehdr
46 # define Elf_Phdr Elf64_Phdr
47 # define Elf_Nhdr Elf64_Nhdr
48 # define Elf_Addr Elf64_Addr
49 # define Elf_Sym Elf64_Sym
50 # define Elf_Off Elf64_Off
51 # define Elf_Shdr Elf64_Shdr
52 # define Elf_Rela Elf64_Rela
53 # define Elf_Rel Elf64_Rel
54 # define Elf_Word Elf64_Word
55 # define Elf_Half Elf64_Half
56 # define Elf_Section Elf64_Section
57 # define ELF_R_SYM(val) ELF64_R_SYM(val)
58 # define ELF_R_TYPE(val) ELF64_R_TYPE(val)
59 # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
60 #define XEN_NOTE_SIZE 120
65 static Elf_Addr
SUFFIX (entry_point
);
68 SUFFIX (generate_elf
) (const struct grub_install_image_target_desc
*image_target
,
69 int note
, char **core_img
, size_t *core_size
,
70 Elf_Addr target_addr
, grub_size_t align
,
71 size_t kernel_size
, size_t bss_size
)
78 int header_size
, footer_size
= 0;
81 int string_size
= sizeof (".text") + sizeof ("mods") + 1;
83 if (image_target
->id
!= IMAGE_LOONGSON_ELF
)
89 footer_size
+= sizeof (struct grub_ieee1275_note
);
91 if (image_target
->id
== IMAGE_XEN
)
95 string_size
+= sizeof (".xen");
96 footer_size
+= XEN_NOTE_SIZE
;
98 header_size
= ALIGN_UP (sizeof (*ehdr
) + phnum
* sizeof (*phdr
)
99 + shnum
* sizeof (*shdr
) + string_size
, align
);
101 program_size
= ALIGN_ADDR (*core_size
);
103 elf_img
= xmalloc (program_size
+ header_size
+ footer_size
);
104 memset (elf_img
, 0, program_size
+ header_size
);
105 memcpy (elf_img
+ header_size
, *core_img
, *core_size
);
106 ehdr
= (void *) elf_img
;
107 phdr
= (void *) (elf_img
+ sizeof (*ehdr
));
108 shdr
= (void *) (elf_img
+ sizeof (*ehdr
) + phnum
* sizeof (*phdr
));
109 memcpy (ehdr
->e_ident
, ELFMAG
, SELFMAG
);
110 ehdr
->e_ident
[EI_CLASS
] = ELFCLASSXX
;
111 if (!image_target
->bigendian
)
112 ehdr
->e_ident
[EI_DATA
] = ELFDATA2LSB
;
114 ehdr
->e_ident
[EI_DATA
] = ELFDATA2MSB
;
115 ehdr
->e_ident
[EI_VERSION
] = EV_CURRENT
;
116 ehdr
->e_ident
[EI_OSABI
] = ELFOSABI_NONE
;
117 ehdr
->e_type
= grub_host_to_target16 (ET_EXEC
);
118 ehdr
->e_machine
= grub_host_to_target16 (image_target
->elf_target
);
119 ehdr
->e_version
= grub_host_to_target32 (EV_CURRENT
);
121 ehdr
->e_phoff
= grub_host_to_target32 ((char *) phdr
- (char *) ehdr
);
122 ehdr
->e_phentsize
= grub_host_to_target16 (sizeof (*phdr
));
123 ehdr
->e_phnum
= grub_host_to_target16 (phnum
);
125 ehdr
->e_shoff
= grub_host_to_target32 ((grub_uint8_t
*) shdr
126 - (grub_uint8_t
*) ehdr
);
127 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
128 ehdr
->e_shentsize
= grub_host_to_target16 (0);
130 ehdr
->e_shentsize
= grub_host_to_target16 (sizeof (Elf_Shdr
));
131 ehdr
->e_shnum
= grub_host_to_target16 (shnum
);
132 ehdr
->e_shstrndx
= grub_host_to_target16 (1);
134 ehdr
->e_ehsize
= grub_host_to_target16 (sizeof (*ehdr
));
136 phdr
->p_type
= grub_host_to_target32 (PT_LOAD
);
137 phdr
->p_offset
= grub_host_to_target32 (header_size
);
138 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
140 ehdr
->e_entry
= grub_host_to_target32 (target_addr
);
141 phdr
->p_vaddr
= grub_host_to_target32 (target_addr
);
142 phdr
->p_paddr
= grub_host_to_target32 (target_addr
);
143 phdr
->p_align
= grub_host_to_target32 (align
> image_target
->link_align
? align
: image_target
->link_align
);
144 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
145 ehdr
->e_flags
= grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
146 | EF_MIPS_PIC
| EF_MIPS_CPIC
);
149 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
151 phdr
->p_filesz
= grub_host_to_target32 (*core_size
);
152 phdr
->p_memsz
= grub_host_to_target32 (*core_size
);
156 grub_uint32_t target_addr_mods
;
157 phdr
->p_filesz
= grub_host_to_target32 (kernel_size
);
158 phdr
->p_memsz
= grub_host_to_target32 (kernel_size
+ bss_size
);
161 phdr
->p_type
= grub_host_to_target32 (PT_GNU_STACK
);
162 phdr
->p_offset
= grub_host_to_target32 (header_size
+ kernel_size
);
163 phdr
->p_paddr
= phdr
->p_vaddr
= phdr
->p_filesz
= phdr
->p_memsz
= 0;
164 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
165 phdr
->p_align
= grub_host_to_target32 (image_target
->link_align
);
168 phdr
->p_type
= grub_host_to_target32 (PT_LOAD
);
169 phdr
->p_offset
= grub_host_to_target32 (header_size
+ kernel_size
);
170 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
171 phdr
->p_filesz
= phdr
->p_memsz
172 = grub_host_to_target32 (*core_size
- kernel_size
);
174 if (image_target
->id
== IMAGE_COREBOOT
)
175 target_addr_mods
= GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR
;
177 target_addr_mods
= ALIGN_UP (target_addr
+ kernel_size
+ bss_size
178 + image_target
->mod_gap
,
179 image_target
->mod_align
);
180 phdr
->p_vaddr
= grub_host_to_target_addr (target_addr_mods
);
181 phdr
->p_paddr
= grub_host_to_target_addr (target_addr_mods
);
182 phdr
->p_align
= grub_host_to_target32 (image_target
->link_align
);
185 if (image_target
->id
== IMAGE_XEN
)
187 char *note_start
= (elf_img
+ program_size
+ header_size
);
189 char *ptr
= (char *) note_start
;
191 grub_util_info ("adding XEN NOTE segment");
194 note_ptr
= (Elf_Nhdr
*) ptr
;
195 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
196 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof (PACKAGE_NAME
));
197 note_ptr
->n_type
= grub_host_to_target32 (6);
198 ptr
+= sizeof (Elf_Nhdr
);
199 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
200 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
201 memcpy (ptr
, PACKAGE_NAME
, sizeof (PACKAGE_NAME
));
202 ptr
+= ALIGN_UP (sizeof (PACKAGE_NAME
), 4);
205 note_ptr
= (Elf_Nhdr
*) ptr
;
206 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
207 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("generic"));
208 note_ptr
->n_type
= grub_host_to_target32 (8);
209 ptr
+= sizeof (Elf_Nhdr
);
210 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
211 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
212 memcpy (ptr
, "generic", sizeof ("generic"));
213 ptr
+= ALIGN_UP (sizeof ("generic"), 4);
216 note_ptr
= (Elf_Nhdr
*) ptr
;
217 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
218 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("xen-3.0"));
219 note_ptr
->n_type
= grub_host_to_target32 (5);
220 ptr
+= sizeof (Elf_Nhdr
);
221 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
222 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
223 memcpy (ptr
, "xen-3.0", sizeof ("xen-3.0"));
224 ptr
+= ALIGN_UP (sizeof ("xen-3.0"), 4);
227 note_ptr
= (Elf_Nhdr
*) ptr
;
228 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
229 note_ptr
->n_descsz
= grub_host_to_target32 (image_target
->voidp_sizeof
);
230 note_ptr
->n_type
= grub_host_to_target32 (1);
231 ptr
+= sizeof (Elf_Nhdr
);
232 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
233 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
234 memset (ptr
, 0, image_target
->voidp_sizeof
);
235 ptr
+= image_target
->voidp_sizeof
;
238 note_ptr
= (Elf_Nhdr
*) ptr
;
239 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
240 note_ptr
->n_descsz
= grub_host_to_target32 (image_target
->voidp_sizeof
);
241 note_ptr
->n_type
= grub_host_to_target32 (3);
242 ptr
+= sizeof (Elf_Nhdr
);
243 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
244 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
245 memset (ptr
, 0, image_target
->voidp_sizeof
);
246 ptr
+= image_target
->voidp_sizeof
;
249 if (image_target
->elf_target
== EM_386
)
251 note_ptr
= (Elf_Nhdr
*) ptr
;
252 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
253 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("yes,bimodal"));
254 note_ptr
->n_type
= grub_host_to_target32 (9);
255 ptr
+= sizeof (Elf_Nhdr
);
256 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
257 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
258 memcpy (ptr
, "yes", sizeof ("yes"));
259 ptr
+= ALIGN_UP (sizeof ("yes"), 4);
262 assert (XEN_NOTE_SIZE
== (ptr
- note_start
));
265 phdr
->p_type
= grub_host_to_target32 (PT_NOTE
);
266 phdr
->p_flags
= grub_host_to_target32 (PF_R
);
267 phdr
->p_align
= grub_host_to_target32 (image_target
->voidp_sizeof
);
270 phdr
->p_filesz
= grub_host_to_target32 (XEN_NOTE_SIZE
);
272 phdr
->p_offset
= grub_host_to_target32 (header_size
+ program_size
);
277 int note_size
= sizeof (struct grub_ieee1275_note
);
278 struct grub_ieee1275_note
*note_ptr
= (struct grub_ieee1275_note
*)
279 (elf_img
+ program_size
+ header_size
);
281 grub_util_info ("adding CHRP NOTE segment");
283 note_ptr
->header
.n_namesz
= grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME
));
284 note_ptr
->header
.n_descsz
= grub_host_to_target32 (note_size
);
285 note_ptr
->header
.n_type
= grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE
);
286 strcpy (note_ptr
->name
, GRUB_IEEE1275_NOTE_NAME
);
287 note_ptr
->descriptor
.real_mode
= grub_host_to_target32 (0xffffffff);
288 note_ptr
->descriptor
.real_base
= grub_host_to_target32 (0x00c00000);
289 note_ptr
->descriptor
.real_size
= grub_host_to_target32 (0xffffffff);
290 note_ptr
->descriptor
.virt_base
= grub_host_to_target32 (0xffffffff);
291 note_ptr
->descriptor
.virt_size
= grub_host_to_target32 (0xffffffff);
292 note_ptr
->descriptor
.load_base
= grub_host_to_target32 (0x00004000);
295 phdr
->p_type
= grub_host_to_target32 (PT_NOTE
);
296 phdr
->p_flags
= grub_host_to_target32 (PF_R
);
297 phdr
->p_align
= grub_host_to_target32 (image_target
->voidp_sizeof
);
300 phdr
->p_filesz
= grub_host_to_target32 (note_size
);
302 phdr
->p_offset
= grub_host_to_target32 (header_size
+ program_size
);
306 char *str_start
= (elf_img
+ sizeof (*ehdr
) + phnum
* sizeof (*phdr
)
307 + shnum
* sizeof (*shdr
));
308 char *ptr
= str_start
+ 1;
312 shdr
->sh_name
= grub_host_to_target32 (0);
313 shdr
->sh_type
= grub_host_to_target32 (SHT_STRTAB
);
314 shdr
->sh_addr
= grub_host_to_target_addr (0);
315 shdr
->sh_offset
= grub_host_to_target_addr (str_start
- elf_img
);
316 shdr
->sh_size
= grub_host_to_target32 (string_size
);
317 shdr
->sh_link
= grub_host_to_target32 (0);
318 shdr
->sh_info
= grub_host_to_target32 (0);
319 shdr
->sh_addralign
= grub_host_to_target32 (align
);
320 shdr
->sh_entsize
= grub_host_to_target32 (0);
323 memcpy (ptr
, ".text", sizeof (".text"));
325 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
326 ptr
+= sizeof (".text");
327 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
328 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
);
329 shdr
->sh_offset
= grub_host_to_target_addr (header_size
);
330 shdr
->sh_size
= grub_host_to_target32 (kernel_size
);
331 shdr
->sh_link
= grub_host_to_target32 (0);
332 shdr
->sh_info
= grub_host_to_target32 (0);
333 shdr
->sh_addralign
= grub_host_to_target32 (align
);
334 shdr
->sh_entsize
= grub_host_to_target32 (0);
337 memcpy (ptr
, "mods", sizeof ("mods"));
338 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
339 ptr
+= sizeof ("mods");
340 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
341 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
+ kernel_size
);
342 shdr
->sh_offset
= grub_host_to_target_addr (header_size
+ kernel_size
);
343 shdr
->sh_size
= grub_host_to_target32 (*core_size
- kernel_size
);
344 shdr
->sh_link
= grub_host_to_target32 (0);
345 shdr
->sh_info
= grub_host_to_target32 (0);
346 shdr
->sh_addralign
= grub_host_to_target32 (image_target
->voidp_sizeof
);
347 shdr
->sh_entsize
= grub_host_to_target32 (0);
350 if (image_target
->id
== IMAGE_XEN
)
352 memcpy (ptr
, ".xen", sizeof (".xen"));
353 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
354 ptr
+= sizeof (".xen");
355 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
356 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
+ kernel_size
);
357 shdr
->sh_offset
= grub_host_to_target_addr (program_size
+ header_size
);
358 shdr
->sh_size
= grub_host_to_target32 (XEN_NOTE_SIZE
);
359 shdr
->sh_link
= grub_host_to_target32 (0);
360 shdr
->sh_info
= grub_host_to_target32 (0);
361 shdr
->sh_addralign
= grub_host_to_target32 (image_target
->voidp_sizeof
);
362 shdr
->sh_entsize
= grub_host_to_target32 (0);
369 *core_size
= program_size
+ header_size
+ footer_size
;
372 /* Relocate symbols; note that this function overwrites the symbol table.
373 Return the address of a start symbol. */
375 SUFFIX (relocate_symbols
) (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
376 Elf_Shdr
*symtab_section
, Elf_Addr
*section_addresses
,
377 Elf_Half section_entsize
, Elf_Half num_sections
,
378 void *jumpers
, Elf_Addr jumpers_addr
,
379 const struct grub_install_image_target_desc
*image_target
)
381 Elf_Word symtab_size
, sym_size
, num_syms
;
382 Elf_Off symtab_offset
;
383 Elf_Addr start_address
= 0;
386 Elf_Shdr
*strtab_section
;
388 grub_uint64_t
*jptr
= jumpers
;
391 = (Elf_Shdr
*) ((char *) sections
392 + (grub_target_to_host32 (symtab_section
->sh_link
)
394 strtab
= (char *) e
+ grub_target_to_host (strtab_section
->sh_offset
);
396 symtab_size
= grub_target_to_host (symtab_section
->sh_size
);
397 sym_size
= grub_target_to_host (symtab_section
->sh_entsize
);
398 symtab_offset
= grub_target_to_host (symtab_section
->sh_offset
);
399 num_syms
= symtab_size
/ sym_size
;
401 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
403 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
405 Elf_Section cur_index
;
408 name
= strtab
+ grub_target_to_host32 (sym
->st_name
);
410 cur_index
= grub_target_to_host16 (sym
->st_shndx
);
411 if (cur_index
== STN_ABS
)
415 else if (cur_index
== STN_UNDEF
)
418 grub_util_error ("undefined symbol %s", name
);
422 else if (cur_index
>= num_sections
)
423 grub_util_error ("section %d does not exist", cur_index
);
425 sym
->st_value
= (grub_target_to_host (sym
->st_value
)
426 + section_addresses
[cur_index
]);
428 if (image_target
->elf_target
== EM_IA_64
&& ELF_ST_TYPE (sym
->st_info
)
431 *jptr
= grub_host_to_target64 (sym
->st_value
);
432 sym
->st_value
= (char *) jptr
- (char *) jumpers
+ jumpers_addr
;
437 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
438 " (0x%" GRUB_HOST_PRIxLONG_LONG
")", name
,
439 (unsigned long long) sym
->st_value
,
440 (unsigned long long) section_addresses
[cur_index
]);
443 if (strcmp (name
, "_start") == 0 || strcmp (name
, "start") == 0)
444 start_address
= sym
->st_value
;
447 return start_address
;
450 /* Return the address of a symbol at the index I in the section S. */
452 SUFFIX (get_symbol_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Word i
,
453 const struct grub_install_image_target_desc
*image_target
)
457 sym
= (Elf_Sym
*) ((char *) e
458 + grub_target_to_host (s
->sh_offset
)
459 + i
* grub_target_to_host (s
->sh_entsize
));
460 return sym
->st_value
;
463 /* Return the address of a modified value. */
465 SUFFIX (get_target_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Addr offset
,
466 const struct grub_install_image_target_desc
*image_target
)
468 return (Elf_Addr
*) ((char *) e
+ grub_target_to_host (s
->sh_offset
) + offset
);
473 SUFFIX (count_funcs
) (Elf_Ehdr
*e
, Elf_Shdr
*symtab_section
,
474 const struct grub_install_image_target_desc
*image_target
)
476 Elf_Word symtab_size
, sym_size
, num_syms
;
477 Elf_Off symtab_offset
;
482 symtab_size
= grub_target_to_host (symtab_section
->sh_size
);
483 sym_size
= grub_target_to_host (symtab_section
->sh_entsize
);
484 symtab_offset
= grub_target_to_host (symtab_section
->sh_offset
);
485 num_syms
= symtab_size
/ sym_size
;
487 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
489 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
490 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
498 /* Deal with relocation information. This function relocates addresses
499 within the virtual address space starting from 0. So only relative
500 addresses can be fully resolved. Absolute addresses must be relocated
501 again by a PE32 relocator when loaded. */
503 arm_get_trampoline_size (Elf_Ehdr
*e
,
505 Elf_Half section_entsize
,
506 Elf_Half num_sections
,
507 const struct grub_install_image_target_desc
*image_target
)
513 for (i
= 0, s
= sections
;
515 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
516 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
517 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
520 Elf_Word rtab_size
, r_size
, num_rs
;
522 Elf_Shdr
*symtab_section
;
525 symtab_section
= (Elf_Shdr
*) ((char *) sections
526 + (grub_target_to_host32 (s
->sh_link
)
529 rtab_size
= grub_target_to_host (s
->sh_size
);
530 r_size
= grub_target_to_host (s
->sh_entsize
);
531 rtab_offset
= grub_target_to_host (s
->sh_offset
);
532 num_rs
= rtab_size
/ r_size
;
534 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
536 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
541 info
= grub_target_to_host (r
->r_info
);
542 sym_addr
= SUFFIX (get_symbol_address
) (e
, symtab_section
,
543 ELF_R_SYM (info
), image_target
);
545 sym_addr
+= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
546 grub_target_to_host (r
->r_addend
) : 0;
548 switch (ELF_R_TYPE (info
))
554 case R_ARM_THM_JUMP24
:
555 case R_ARM_THM_JUMP19
:
567 grub_util_error (_("relocation 0x%x is not implemented yet"),
568 (unsigned int) ELF_R_TYPE (info
));
577 /* Deal with relocation information. This function relocates addresses
578 within the virtual address space starting from 0. So only relative
579 addresses can be fully resolved. Absolute addresses must be relocated
580 again by a PE32 relocator when loaded. */
582 SUFFIX (relocate_addresses
) (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
583 Elf_Addr
*section_addresses
,
584 Elf_Half section_entsize
, Elf_Half num_sections
,
586 char *pe_target
, Elf_Addr tramp_off
,
588 const struct grub_install_image_target_desc
*image_target
)
593 struct grub_ia64_trampoline
*tr
= (void *) (pe_target
+ tramp_off
);
594 grub_uint64_t
*gpptr
= (void *) (pe_target
+ got_off
);
595 #define MASK19 ((1 << 19) - 1)
597 grub_uint32_t
*tr
= (void *) (pe_target
+ tramp_off
);
600 for (i
= 0, s
= sections
;
602 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
603 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
604 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
607 Elf_Word rtab_size
, r_size
, num_rs
;
609 Elf_Shdr
*symtab_section
;
610 Elf_Word target_section_index
;
611 Elf_Addr target_section_addr
;
612 Elf_Shdr
*target_section
;
615 symtab_section
= (Elf_Shdr
*) ((char *) sections
616 + (grub_target_to_host32 (s
->sh_link
)
618 target_section_index
= grub_target_to_host32 (s
->sh_info
);
619 target_section_addr
= section_addresses
[target_section_index
];
620 target_section
= (Elf_Shdr
*) ((char *) sections
621 + (target_section_index
624 grub_util_info ("dealing with the relocation section %s for %s",
625 strtab
+ grub_target_to_host32 (s
->sh_name
),
626 strtab
+ grub_target_to_host32 (target_section
->sh_name
));
628 rtab_size
= grub_target_to_host (s
->sh_size
);
629 r_size
= grub_target_to_host (s
->sh_entsize
);
630 rtab_offset
= grub_target_to_host (s
->sh_offset
);
631 num_rs
= rtab_size
/ r_size
;
633 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
635 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
643 offset
= grub_target_to_host (r
->r_offset
);
644 target
= SUFFIX (get_target_address
) (e
, target_section
,
645 offset
, image_target
);
646 info
= grub_target_to_host (r
->r_info
);
647 sym_addr
= SUFFIX (get_symbol_address
) (e
, symtab_section
,
648 ELF_R_SYM (info
), image_target
);
650 addend
= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
651 grub_target_to_host (r
->r_addend
) : 0;
653 switch (image_target
->elf_target
)
656 switch (ELF_R_TYPE (info
))
662 /* This is absolute. */
663 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
664 + addend
+ sym_addr
);
665 grub_util_info ("relocating an R_386_32 entry to 0x%"
666 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
667 GRUB_HOST_PRIxLONG_LONG
,
668 (unsigned long long) *target
,
669 (unsigned long long) offset
);
673 /* This is relative. */
674 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
676 - target_section_addr
- offset
677 - image_target
->vaddr_offset
);
678 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
679 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
680 GRUB_HOST_PRIxLONG_LONG
,
681 (unsigned long long) *target
,
682 (unsigned long long) offset
);
685 grub_util_error (_("relocation 0x%x is not implemented yet"),
686 (unsigned int) ELF_R_TYPE (info
));
692 switch (ELF_R_TYPE (info
))
699 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
700 + addend
+ sym_addr
);
701 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
702 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
703 GRUB_HOST_PRIxLONG_LONG
,
704 (unsigned long long) *target
,
705 (unsigned long long) offset
);
710 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
711 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
713 - target_section_addr
- offset
714 - image_target
->vaddr_offset
);
715 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
716 GRUB_HOST_PRIxLONG_LONG
,
717 *t32
, (unsigned long long) offset
);
723 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
725 - target_section_addr
- offset
726 - image_target
->vaddr_offset
);
727 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
728 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
729 GRUB_HOST_PRIxLONG_LONG
,
730 (unsigned long long) *target
,
731 (unsigned long long) offset
);
738 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
739 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
740 + addend
+ sym_addr
);
741 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
742 GRUB_HOST_PRIxLONG_LONG
,
743 *t32
, (unsigned long long) offset
);
748 grub_util_error (_("relocation 0x%x is not implemented yet"),
749 (unsigned int) ELF_R_TYPE (info
));
754 switch (ELF_R_TYPE (info
))
756 case R_IA64_PCREL21B
:
759 grub_ia64_make_trampoline (tr
, addend
+ sym_addr
);
760 noff
= ((char *) tr
- (char *) pe_target
761 - target_section_addr
- (offset
& ~3)) >> 4;
764 grub_util_error ("trampoline offset too big (%"
765 GRUB_HOST_PRIxLONG_LONG
")",
766 (unsigned long long) noff
);
767 grub_ia64_add_value_to_slot_20b ((grub_addr_t
) target
, noff
);
771 case R_IA64_LTOFF22X
:
776 sym
= (Elf_Sym
*) ((char *) e
777 + grub_target_to_host (symtab_section
->sh_offset
)
778 + ELF_R_SYM (info
) * grub_target_to_host (symtab_section
->sh_entsize
));
779 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
780 sym_addr
= grub_target_to_host64 (*(grub_uint64_t
*) (pe_target
782 - image_target
->vaddr_offset
));
784 case R_IA64_LTOFF_FPTR22
:
785 *gpptr
= grub_host_to_target64 (addend
+ sym_addr
);
786 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
787 (char *) gpptr
- (char *) pe_target
788 + image_target
->vaddr_offset
);
793 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
796 case R_IA64_PCREL64LSB
:
797 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
799 - target_section_addr
- offset
800 - image_target
->vaddr_offset
);
803 case R_IA64_SEGREL64LSB
:
804 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
805 + addend
+ sym_addr
- target_section_addr
);
807 case R_IA64_DIR64LSB
:
808 case R_IA64_FPTR64LSB
:
809 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
810 + addend
+ sym_addr
);
811 grub_util_info ("relocating a direct entry to 0x%"
812 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
813 GRUB_HOST_PRIxLONG_LONG
,
815 grub_target_to_host64 (*target
),
816 (unsigned long long) offset
);
819 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
824 grub_util_error (_("relocation 0x%x is not implemented yet"),
825 (unsigned int) ELF_R_TYPE (info
));
832 switch (ELF_R_TYPE (info
))
834 case R_AARCH64_ABS64
:
836 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
) + sym_addr
);
839 case R_AARCH64_JUMP26
:
840 case R_AARCH64_CALL26
:
843 sym_addr
-= SUFFIX (entry_point
);
844 if (!grub_arm_64_check_xxxx26_offset (sym_addr
))
845 grub_util_error ("%s", "CALL26 Relocation out of range");
847 grub_arm64_set_xxxx26_offset((grub_uint32_t
*)target
,
852 grub_util_error (_("relocation 0x%x is not implemented yet"),
853 (unsigned int) ELF_R_TYPE (info
));
859 #if defined(MKIMAGE_ELF32)
863 sym_addr
-= SUFFIX (entry_point
);
864 switch (ELF_R_TYPE (info
))
868 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
869 (int) sym_addr
, (int) sym_addr
);
870 /* Data will be naturally aligned */
872 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
) + sym_addr
);
875 /* Happens when compiled with -march=armv4.
876 Since currently we need at least armv5, keep bx as-is.
881 case R_ARM_THM_JUMP24
:
882 case R_ARM_THM_JUMP19
:
885 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
886 (unsigned long) ((char *) target
891 grub_uint32_t tr_addr
;
892 grub_int32_t new_offset
;
893 tr_addr
= (char *) tr
- (char *) pe_target
894 - target_section_addr
;
895 new_offset
= sym_addr
- tr_addr
- 12;
897 if (!grub_arm_jump24_check_offset (new_offset
))
898 return grub_util_error ("jump24 relocation out of range");
900 tr
[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
901 tr
[1] = grub_host_to_target32 (((new_offset
>> 2) & 0xffffff) | 0xea000000); /* b new_offset */
903 sym_addr
= tr_addr
| 1;
906 /* Thumb instructions can be 16-bit aligned */
907 if (ELF_R_TYPE (info
) == R_ARM_THM_JUMP19
)
908 err
= grub_arm_reloc_thm_jump19 ((grub_uint16_t
*) target
, sym_addr
);
910 err
= grub_arm_reloc_thm_call ((grub_uint16_t
*) target
,
913 grub_util_error ("%s", grub_errmsg
);
921 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target
- (char *) e
), sym_addr
);
924 grub_uint32_t tr_addr
;
925 grub_int32_t new_offset
;
926 tr_addr
= (char *) tr
- (char *) pe_target
927 - target_section_addr
;
928 new_offset
= sym_addr
- tr_addr
- 12;
930 /* There is no immediate version of bx, only register one... */
931 tr
[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
932 tr
[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
933 tr
[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
934 tr
[3] = grub_host_to_target32 (new_offset
| 1);
939 err
= grub_arm_reloc_jump24 (target
,
942 grub_util_error ("%s", grub_errmsg
);
947 grub_util_error (_("relocation 0x%x is not implemented yet"),
948 (unsigned int) ELF_R_TYPE (info
));
953 #endif /* MKIMAGE_ELF32 */
955 grub_util_error ("unknown architecture type %d",
956 image_target
->elf_target
);
962 /* Add a PE32's fixup entry for a relocation. Return the resulting address
963 after having written to the file OUT. */
965 SUFFIX (add_fixup_entry
) (struct fixup_block_list
**cblock
, grub_uint16_t type
,
966 Elf_Addr addr
, int flush
, Elf_Addr current_address
,
967 const struct grub_install_image_target_desc
*image_target
)
969 struct grub_pe32_fixup_block
*b
;
973 /* First, check if it is necessary to write out the current block. */
974 if ((*cblock
)->state
)
976 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
982 /* Add as much padding as necessary to align the address
983 with a section boundary. */
984 Elf_Addr next_address
;
985 unsigned padding_size
;
988 next_address
= current_address
+ b
->block_size
;
989 padding_size
= ((ALIGN_UP (next_address
, image_target
->section_align
)
992 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
993 grub_util_info ("adding %d padding fixup entries", padding_size
);
994 while (padding_size
--)
996 b
->entries
[cur_index
++] = 0;
1000 else while (b
->block_size
& (8 - 1))
1002 /* If not aligned with a 32-bit boundary, add
1006 grub_util_info ("adding a padding fixup entry");
1007 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1008 b
->entries
[cur_index
] = 0;
1013 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1014 b
->block_size
, b
->page_rva
);
1015 size
= b
->block_size
;
1016 current_address
+= size
;
1017 b
->page_rva
= grub_host_to_target32 (b
->page_rva
);
1018 b
->block_size
= grub_host_to_target32 (b
->block_size
);
1019 (*cblock
)->next
= xmalloc (sizeof (**cblock
) + 2 * 0x1000);
1020 memset ((*cblock
)->next
, 0, sizeof (**cblock
) + 2 * 0x1000);
1021 *cblock
= (*cblock
)->next
;
1025 b
= &((*cblock
)->b
);
1029 grub_uint16_t entry
;
1032 /* If not allocated yet, allocate a block with enough entries. */
1033 if (! (*cblock
)->state
)
1035 (*cblock
)->state
= 1;
1037 /* The spec does not mention the requirement of a Page RVA.
1038 Here, align the address with a 4K boundary for safety. */
1039 b
->page_rva
= (addr
& ~(0x1000 - 1));
1040 b
->block_size
= sizeof (*b
);
1044 if (b
->block_size
>= sizeof (*b
) + 2 * 0x1000)
1045 grub_util_error ("too many fixup entries");
1047 /* Add a new entry. */
1048 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1049 entry
= GRUB_PE32_FIXUP_ENTRY (type
, addr
- b
->page_rva
);
1050 b
->entries
[cur_index
] = grub_host_to_target16 (entry
);
1054 return current_address
;
1057 /* Make a .reloc section. */
1059 SUFFIX (make_reloc_section
) (Elf_Ehdr
*e
, void **out
,
1060 Elf_Addr
*section_addresses
, Elf_Shdr
*sections
,
1061 Elf_Half section_entsize
, Elf_Half num_sections
,
1063 Elf_Addr jumpers
, grub_size_t njumpers
,
1064 const struct grub_install_image_target_desc
*image_target
)
1068 struct fixup_block_list
*lst
, *lst0
;
1069 Elf_Addr current_address
= 0;
1071 lst
= lst0
= xmalloc (sizeof (*lst
) + 2 * 0x1000);
1072 memset (lst
, 0, sizeof (*lst
) + 2 * 0x1000);
1074 for (i
= 0, s
= sections
; i
< num_sections
;
1075 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1076 if ((grub_target_to_host32 (s
->sh_type
) == SHT_REL
) ||
1077 (grub_target_to_host32 (s
->sh_type
) == SHT_RELA
))
1080 Elf_Word rtab_size
, r_size
, num_rs
;
1081 Elf_Off rtab_offset
;
1082 Elf_Addr section_address
;
1085 grub_util_info ("translating the relocation section %s",
1086 strtab
+ grub_le_to_cpu32 (s
->sh_name
));
1088 rtab_size
= grub_target_to_host (s
->sh_size
);
1089 r_size
= grub_target_to_host (s
->sh_entsize
);
1090 rtab_offset
= grub_target_to_host (s
->sh_offset
);
1091 num_rs
= rtab_size
/ r_size
;
1093 section_address
= section_addresses
[grub_le_to_cpu32 (s
->sh_info
)];
1095 for (j
= 0, r
= (Elf_Rel
*) ((char *) e
+ rtab_offset
);
1097 j
++, r
= (Elf_Rel
*) ((char *) r
+ r_size
))
1102 offset
= grub_target_to_host (r
->r_offset
);
1103 info
= grub_target_to_host (r
->r_info
);
1105 /* Necessary to relocate only absolute addresses. */
1106 switch (image_target
->elf_target
)
1109 if (ELF_R_TYPE (info
) == R_386_32
)
1113 addr
= section_address
+ offset
;
1114 grub_util_info ("adding a relocation entry for 0x%"
1115 GRUB_HOST_PRIxLONG_LONG
,
1116 (unsigned long long) addr
);
1118 = SUFFIX (add_fixup_entry
) (&lst
,
1119 GRUB_PE32_REL_BASED_HIGHLOW
,
1120 addr
, 0, current_address
,
1125 if ((ELF_R_TYPE (info
) == R_X86_64_32
) ||
1126 (ELF_R_TYPE (info
) == R_X86_64_32S
))
1128 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1130 else if (ELF_R_TYPE (info
) == R_X86_64_64
)
1134 addr
= section_address
+ offset
;
1135 grub_util_info ("adding a relocation entry for 0x%"
1136 GRUB_HOST_PRIxLONG_LONG
,
1137 (unsigned long long) addr
);
1139 = SUFFIX (add_fixup_entry
) (&lst
,
1140 GRUB_PE32_REL_BASED_DIR64
,
1147 switch (ELF_R_TYPE (info
))
1149 case R_IA64_PCREL64LSB
:
1151 case R_IA64_PCREL21B
:
1152 case R_IA64_LTOFF_FPTR22
:
1153 case R_IA64_LTOFF22X
:
1154 case R_IA64_LTOFF22
:
1155 case R_IA64_GPREL22
:
1156 case R_IA64_SEGREL64LSB
:
1159 case R_IA64_FPTR64LSB
:
1160 case R_IA64_DIR64LSB
:
1165 addr
= section_address
+ offset
;
1166 grub_util_info ("adding a relocation entry for 0x%"
1167 GRUB_HOST_PRIxLONG_LONG
,
1168 (unsigned long long) addr
);
1170 = SUFFIX (add_fixup_entry
) (&lst
,
1171 GRUB_PE32_REL_BASED_DIR64
,
1179 grub_util_error (_("relocation 0x%x is not implemented yet"),
1180 (unsigned int) ELF_R_TYPE (info
));
1185 switch (ELF_R_TYPE (info
))
1187 case R_AARCH64_ABS64
:
1191 addr
= section_address
+ offset
;
1193 = SUFFIX (add_fixup_entry
) (&lst
,
1194 GRUB_PE32_REL_BASED_DIR64
,
1195 addr
, 0, current_address
,
1199 /* Relative relocations do not require fixup entries. */
1200 case R_AARCH64_CALL26
:
1201 case R_AARCH64_JUMP26
:
1204 grub_util_error (_("relocation 0x%x is not implemented yet"),
1205 (unsigned int) ELF_R_TYPE (info
));
1210 #if defined(MKIMAGE_ELF32)
1212 switch (ELF_R_TYPE (info
))
1215 /* Relative relocations do not require fixup entries. */
1217 case R_ARM_THM_CALL
:
1218 case R_ARM_THM_JUMP19
:
1219 case R_ARM_THM_JUMP24
:
1224 addr
= section_address
+ offset
;
1225 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__
, (unsigned int) addr
, (unsigned int) current_address
);
1228 /* Create fixup entry for PE/COFF loader */
1233 addr
= section_address
+ offset
;
1235 = SUFFIX (add_fixup_entry
) (&lst
,
1236 GRUB_PE32_REL_BASED_HIGHLOW
,
1237 addr
, 0, current_address
,
1242 grub_util_error (_("relocation 0x%x is not implemented yet"),
1243 (unsigned int) ELF_R_TYPE (info
));
1247 #endif /* defined(MKIMAGE_ELF32) */
1249 grub_util_error ("unknown machine type 0x%x", image_target
->elf_target
);
1254 if (image_target
->elf_target
== EM_IA_64
)
1255 for (i
= 0; i
< njumpers
; i
++)
1256 current_address
= SUFFIX (add_fixup_entry
) (&lst
,
1257 GRUB_PE32_REL_BASED_DIR64
,
1262 current_address
= SUFFIX (add_fixup_entry
) (&lst
, 0, 0, 1, current_address
, image_target
);
1266 ptr
= *out
= xmalloc (current_address
);
1267 for (lst
= lst0
; lst
; lst
= lst
->next
)
1270 memcpy (ptr
, &lst
->b
, grub_target_to_host32 (lst
->b
.block_size
));
1271 ptr
+= grub_target_to_host32 (lst
->b
.block_size
);
1273 assert ((current_address
+ (grub_uint8_t
*) *out
) == ptr
);
1276 for (lst
= lst0
; lst
; )
1278 struct fixup_block_list
*next
;
1284 return current_address
;
1287 /* Determine if this section is a text section. Return false if this
1288 section is not allocated. */
1290 SUFFIX (is_text_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
1292 if (image_target
->id
!= IMAGE_EFI
1293 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
1295 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
1296 == (SHF_EXECINSTR
| SHF_ALLOC
));
1299 /* Determine if this section is a data section. This assumes that
1300 BSS is also a data section, since the converter initializes BSS
1301 when producing PE32 to avoid a bug in EFI implementations. */
1303 SUFFIX (is_data_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
1305 if (image_target
->id
!= IMAGE_EFI
1306 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
1308 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
1312 /* Return if the ELF header is valid. */
1314 SUFFIX (check_elf_header
) (Elf_Ehdr
*e
, size_t size
, const struct grub_install_image_target_desc
*image_target
)
1316 if (size
< sizeof (*e
)
1317 || e
->e_ident
[EI_MAG0
] != ELFMAG0
1318 || e
->e_ident
[EI_MAG1
] != ELFMAG1
1319 || e
->e_ident
[EI_MAG2
] != ELFMAG2
1320 || e
->e_ident
[EI_MAG3
] != ELFMAG3
1321 || e
->e_ident
[EI_VERSION
] != EV_CURRENT
1322 || e
->e_ident
[EI_CLASS
] != ELFCLASSXX
1323 || e
->e_version
!= grub_host_to_target32 (EV_CURRENT
))
1329 /* Locate section addresses by merging code sections and data sections
1330 into .text and .data, respectively. Return the array of section
1333 SUFFIX (locate_sections
) (const char *kernel_path
,
1334 Elf_Shdr
*sections
, Elf_Half section_entsize
,
1335 Elf_Half num_sections
, const char *strtab
,
1336 size_t *exec_size
, size_t *kernel_sz
,
1338 const struct grub_install_image_target_desc
*image_target
)
1341 Elf_Addr current_address
;
1342 Elf_Addr
*section_addresses
;
1347 section_addresses
= xmalloc (sizeof (*section_addresses
) * num_sections
);
1348 memset (section_addresses
, 0, sizeof (*section_addresses
) * num_sections
);
1350 current_address
= 0;
1352 for (i
= 0, s
= sections
;
1354 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1355 if ((grub_target_to_host (s
->sh_flags
) & SHF_ALLOC
)
1356 && grub_host_to_target32 (s
->sh_addralign
) > *all_align
)
1357 *all_align
= grub_host_to_target32 (s
->sh_addralign
);
1361 for (i
= 0, s
= sections
;
1363 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1364 if (SUFFIX (is_text_section
) (s
, image_target
))
1366 Elf_Word align
= grub_host_to_target_addr (s
->sh_addralign
);
1367 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1369 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1370 align
) - image_target
->vaddr_offset
;
1371 grub_util_info ("locating the section %s at 0x%"
1372 GRUB_HOST_PRIxLONG_LONG
,
1373 name
, (unsigned long long) current_address
);
1374 if (image_target
->id
!= IMAGE_EFI
)
1376 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1377 - image_target
->link_addr
;
1378 if (grub_host_to_target_addr (s
->sh_addr
)
1379 != image_target
->link_addr
)
1382 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
1383 " instead of 0x%llx: ld.gold bug?"),
1385 (unsigned long long) grub_host_to_target_addr (s
->sh_addr
),
1386 (unsigned long long) image_target
->link_addr
);
1387 grub_util_error ("%s", msg
);
1390 section_addresses
[i
] = current_address
;
1391 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1394 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1395 image_target
->section_align
)
1396 - image_target
->vaddr_offset
;
1397 *exec_size
= current_address
;
1400 for (i
= 0, s
= sections
;
1402 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1403 if (SUFFIX (is_data_section
) (s
, image_target
))
1405 Elf_Word align
= grub_host_to_target_addr (s
->sh_addralign
);
1406 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1409 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1411 - image_target
->vaddr_offset
;
1413 grub_util_info ("locating the section %s at 0x%"
1414 GRUB_HOST_PRIxLONG_LONG
,
1415 name
, (unsigned long long) current_address
);
1416 if (image_target
->id
!= IMAGE_EFI
)
1417 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1418 - image_target
->link_addr
;
1419 section_addresses
[i
] = current_address
;
1420 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1423 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1424 image_target
->section_align
) - image_target
->vaddr_offset
;
1425 *kernel_sz
= current_address
;
1426 return section_addresses
;
1430 SUFFIX (load_image
) (const char *kernel_path
, size_t *exec_size
,
1431 size_t *kernel_sz
, size_t *bss_size
,
1432 size_t total_module_size
, grub_uint64_t
*start
,
1433 void **reloc_section
, size_t *reloc_size
,
1435 const struct grub_install_image_target_desc
*image_target
)
1437 char *kernel_img
, *out_img
;
1441 Elf_Addr
*section_addresses
;
1442 Elf_Addr
*section_vaddresses
;
1445 Elf_Half num_sections
;
1446 Elf_Off section_offset
;
1447 Elf_Half section_entsize
;
1448 grub_size_t kernel_size
;
1449 grub_size_t ia64jmp_off
= 0, tramp_off
= 0, ia64_got_off
= 0;
1450 unsigned ia64jmpnum
= 0;
1451 Elf_Shdr
*symtab_section
= 0;
1452 grub_size_t got
= 0;
1456 kernel_size
= grub_util_get_image_size (kernel_path
);
1457 kernel_img
= xmalloc (kernel_size
);
1458 grub_util_load_image (kernel_path
, kernel_img
);
1460 e
= (Elf_Ehdr
*) kernel_img
;
1461 if (! SUFFIX (check_elf_header
) (e
, kernel_size
, image_target
))
1462 grub_util_error ("invalid ELF header");
1464 section_offset
= grub_target_to_host (e
->e_shoff
);
1465 section_entsize
= grub_target_to_host16 (e
->e_shentsize
);
1466 num_sections
= grub_target_to_host16 (e
->e_shnum
);
1468 if (kernel_size
< section_offset
+ section_entsize
* num_sections
)
1469 grub_util_error (_("premature end of file %s"), kernel_path
);
1471 sections
= (Elf_Shdr
*) (kernel_img
+ section_offset
);
1473 /* Relocate sections then symbols in the virtual address space. */
1474 s
= (Elf_Shdr
*) ((char *) sections
1475 + grub_host_to_target16 (e
->e_shstrndx
) * section_entsize
);
1476 strtab
= (char *) e
+ grub_host_to_target_addr (s
->sh_offset
);
1478 section_addresses
= SUFFIX (locate_sections
) (kernel_path
,
1479 sections
, section_entsize
,
1480 num_sections
, strtab
,
1481 exec_size
, kernel_sz
, align
,
1484 section_vaddresses
= xmalloc (sizeof (*section_addresses
) * num_sections
);
1486 for (i
= 0; i
< num_sections
; i
++)
1487 section_vaddresses
[i
] = section_addresses
[i
] + image_target
->vaddr_offset
;
1489 if (image_target
->id
!= IMAGE_EFI
)
1491 Elf_Addr current_address
= *kernel_sz
;
1493 for (i
= 0, s
= sections
;
1495 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1496 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
1498 Elf_Word sec_align
= grub_host_to_target_addr (s
->sh_addralign
);
1499 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1502 current_address
= ALIGN_UP (current_address
1503 + image_target
->vaddr_offset
,
1505 - image_target
->vaddr_offset
;
1507 grub_util_info ("locating the section %s at 0x%"
1508 GRUB_HOST_PRIxLONG_LONG
,
1509 name
, (unsigned long long) current_address
);
1510 if (image_target
->id
!= IMAGE_EFI
)
1511 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1512 - image_target
->link_addr
;
1514 section_vaddresses
[i
] = current_address
1515 + image_target
->vaddr_offset
;
1516 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1518 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1519 image_target
->section_align
)
1520 - image_target
->vaddr_offset
;
1521 *bss_size
= current_address
- *kernel_sz
;
1526 if (image_target
->id
== IMAGE_SPARC64_AOUT
1527 || image_target
->id
== IMAGE_SPARC64_RAW
1528 || image_target
->id
== IMAGE_SPARC64_CDCORE
)
1529 *kernel_sz
= ALIGN_UP (*kernel_sz
, image_target
->mod_align
);
1531 if (image_target
->id
== IMAGE_EFI
)
1533 symtab_section
= NULL
;
1534 for (i
= 0, s
= sections
;
1536 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1537 if (s
->sh_type
== grub_host_to_target32 (SHT_SYMTAB
))
1542 if (! symtab_section
)
1543 grub_util_error ("%s", _("no symbol table"));
1545 #ifdef MKIMAGE_ELF32
1546 if (image_target
->elf_target
== EM_ARM
)
1550 *kernel_sz
= ALIGN_UP (*kernel_sz
, 16);
1552 tramp
= arm_get_trampoline_size (e
, sections
, section_entsize
,
1553 num_sections
, image_target
);
1555 tramp_off
= *kernel_sz
;
1556 *kernel_sz
+= ALIGN_UP (tramp
, 16);
1560 #ifdef MKIMAGE_ELF64
1561 if (image_target
->elf_target
== EM_IA_64
)
1565 *kernel_sz
= ALIGN_UP (*kernel_sz
, 16);
1567 grub_ia64_dl_get_tramp_got_size (e
, &tramp
, &got
);
1569 tramp_off
= *kernel_sz
;
1570 *kernel_sz
+= ALIGN_UP (tramp
, 16);
1572 ia64jmp_off
= *kernel_sz
;
1573 ia64jmpnum
= SUFFIX (count_funcs
) (e
, symtab_section
,
1575 *kernel_sz
+= 16 * ia64jmpnum
;
1577 ia64_got_off
= *kernel_sz
;
1578 *kernel_sz
+= ALIGN_UP (got
, 16);
1586 *reloc_section
= NULL
;
1589 out_img
= xmalloc (*kernel_sz
+ total_module_size
);
1591 if (image_target
->id
== IMAGE_EFI
)
1593 *start
= SUFFIX (relocate_symbols
) (e
, sections
, symtab_section
,
1594 section_vaddresses
, section_entsize
,
1596 (char *) out_img
+ ia64jmp_off
,
1598 + image_target
->vaddr_offset
,
1601 grub_util_error ("start symbol is not defined");
1603 SUFFIX (entry_point
) = (Elf_Addr
) *start
;
1605 /* Resolve addresses in the virtual address space. */
1606 SUFFIX (relocate_addresses
) (e
, sections
, section_addresses
,
1608 num_sections
, strtab
,
1609 out_img
, tramp_off
, ia64_got_off
,
1612 *reloc_size
= SUFFIX (make_reloc_section
) (e
, reloc_section
,
1613 section_vaddresses
, sections
,
1614 section_entsize
, num_sections
,
1616 + image_target
->vaddr_offset
,
1617 2 * ia64jmpnum
+ (got
/ 8),
1621 for (i
= 0, s
= sections
;
1623 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1624 if (SUFFIX (is_data_section
) (s
, image_target
)
1625 || SUFFIX (is_text_section
) (s
, image_target
))
1627 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
1628 memset (out_img
+ section_addresses
[i
], 0,
1629 grub_host_to_target_addr (s
->sh_size
));
1631 memcpy (out_img
+ section_addresses
[i
],
1632 kernel_img
+ grub_host_to_target_addr (s
->sh_offset
),
1633 grub_host_to_target_addr (s
->sh_size
));
1637 free (section_vaddresses
);
1638 free (section_addresses
);
1661 #undef XEN_NOTE_SIZE