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%llx (0x%llx)", name
,
438 (unsigned long long) sym
->st_value
,
439 (unsigned long long) section_addresses
[cur_index
]);
442 if (strcmp (name
, "_start") == 0 || strcmp (name
, "start") == 0)
443 start_address
= sym
->st_value
;
446 return start_address
;
449 /* Return the address of a symbol at the index I in the section S. */
451 SUFFIX (get_symbol_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Word i
,
452 const struct grub_install_image_target_desc
*image_target
)
456 sym
= (Elf_Sym
*) ((char *) e
457 + grub_target_to_host (s
->sh_offset
)
458 + i
* grub_target_to_host (s
->sh_entsize
));
459 return sym
->st_value
;
462 /* Return the address of a modified value. */
464 SUFFIX (get_target_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Addr offset
,
465 const struct grub_install_image_target_desc
*image_target
)
467 return (Elf_Addr
*) ((char *) e
+ grub_target_to_host (s
->sh_offset
) + offset
);
472 SUFFIX (count_funcs
) (Elf_Ehdr
*e
, Elf_Shdr
*symtab_section
,
473 const struct grub_install_image_target_desc
*image_target
)
475 Elf_Word symtab_size
, sym_size
, num_syms
;
476 Elf_Off symtab_offset
;
481 symtab_size
= grub_target_to_host (symtab_section
->sh_size
);
482 sym_size
= grub_target_to_host (symtab_section
->sh_entsize
);
483 symtab_offset
= grub_target_to_host (symtab_section
->sh_offset
);
484 num_syms
= symtab_size
/ sym_size
;
486 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
488 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
489 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
497 /* Deal with relocation information. This function relocates addresses
498 within the virtual address space starting from 0. So only relative
499 addresses can be fully resolved. Absolute addresses must be relocated
500 again by a PE32 relocator when loaded. */
502 arm_get_trampoline_size (Elf_Ehdr
*e
,
504 Elf_Half section_entsize
,
505 Elf_Half num_sections
,
506 const struct grub_install_image_target_desc
*image_target
)
512 for (i
= 0, s
= sections
;
514 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
515 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
516 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
519 Elf_Word rtab_size
, r_size
, num_rs
;
521 Elf_Shdr
*symtab_section
;
524 symtab_section
= (Elf_Shdr
*) ((char *) sections
525 + (grub_target_to_host32 (s
->sh_link
)
528 rtab_size
= grub_target_to_host (s
->sh_size
);
529 r_size
= grub_target_to_host (s
->sh_entsize
);
530 rtab_offset
= grub_target_to_host (s
->sh_offset
);
531 num_rs
= rtab_size
/ r_size
;
533 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
535 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
540 info
= grub_target_to_host (r
->r_info
);
541 sym_addr
= SUFFIX (get_symbol_address
) (e
, symtab_section
,
542 ELF_R_SYM (info
), image_target
);
544 sym_addr
+= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
545 grub_target_to_host (r
->r_addend
) : 0;
547 switch (ELF_R_TYPE (info
))
553 case R_ARM_THM_JUMP24
:
554 case R_ARM_THM_JUMP19
:
566 grub_util_error (_("relocation 0x%x is not implemented yet!"), ELF_R_TYPE (info
));
575 /* Deal with relocation information. This function relocates addresses
576 within the virtual address space starting from 0. So only relative
577 addresses can be fully resolved. Absolute addresses must be relocated
578 again by a PE32 relocator when loaded. */
580 SUFFIX (relocate_addresses
) (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
581 Elf_Addr
*section_addresses
,
582 Elf_Half section_entsize
, Elf_Half num_sections
,
584 char *pe_target
, Elf_Addr tramp_off
,
586 const struct grub_install_image_target_desc
*image_target
)
591 struct grub_ia64_trampoline
*tr
= (void *) (pe_target
+ tramp_off
);
592 grub_uint64_t
*gpptr
= (void *) (pe_target
+ got_off
);
593 #define MASK19 ((1 << 19) - 1)
595 grub_uint32_t
*tr
= (void *) (pe_target
+ tramp_off
);
598 for (i
= 0, s
= sections
;
600 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
601 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
602 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
605 Elf_Word rtab_size
, r_size
, num_rs
;
607 Elf_Shdr
*symtab_section
;
608 Elf_Word target_section_index
;
609 Elf_Addr target_section_addr
;
610 Elf_Shdr
*target_section
;
613 symtab_section
= (Elf_Shdr
*) ((char *) sections
614 + (grub_target_to_host32 (s
->sh_link
)
616 target_section_index
= grub_target_to_host32 (s
->sh_info
);
617 target_section_addr
= section_addresses
[target_section_index
];
618 target_section
= (Elf_Shdr
*) ((char *) sections
619 + (target_section_index
622 grub_util_info ("dealing with the relocation section %s for %s",
623 strtab
+ grub_target_to_host32 (s
->sh_name
),
624 strtab
+ grub_target_to_host32 (target_section
->sh_name
));
626 rtab_size
= grub_target_to_host (s
->sh_size
);
627 r_size
= grub_target_to_host (s
->sh_entsize
);
628 rtab_offset
= grub_target_to_host (s
->sh_offset
);
629 num_rs
= rtab_size
/ r_size
;
631 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
633 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
641 offset
= grub_target_to_host (r
->r_offset
);
642 target
= SUFFIX (get_target_address
) (e
, target_section
,
643 offset
, image_target
);
644 info
= grub_target_to_host (r
->r_info
);
645 sym_addr
= SUFFIX (get_symbol_address
) (e
, symtab_section
,
646 ELF_R_SYM (info
), image_target
);
648 addend
= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
649 grub_target_to_host (r
->r_addend
) : 0;
651 switch (image_target
->elf_target
)
654 switch (ELF_R_TYPE (info
))
660 /* This is absolute. */
661 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
662 + addend
+ sym_addr
);
663 grub_util_info ("relocating an R_386_32 entry to 0x%llx at the offset 0x%llx",
664 (unsigned long long) *target
,
665 (unsigned long long) offset
);
669 /* This is relative. */
670 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
672 - target_section_addr
- offset
673 - image_target
->vaddr_offset
);
674 grub_util_info ("relocating an R_386_PC32 entry to 0x%llx at the offset 0x%llx",
675 (unsigned long long) *target
,
676 (unsigned long long) offset
);
679 grub_util_error (_("relocation 0x%llx is not implemented yet"),
680 (unsigned long long) ELF_R_TYPE (info
));
686 switch (ELF_R_TYPE (info
))
693 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
694 + addend
+ sym_addr
);
695 grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
696 (unsigned long long) *target
,
697 (unsigned long long) offset
);
702 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
703 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
705 - target_section_addr
- offset
706 - image_target
->vaddr_offset
);
707 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
708 *t32
, (unsigned long long) offset
);
715 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
716 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
717 + addend
+ sym_addr
);
718 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
719 *t32
, (unsigned long long) offset
);
724 grub_util_error (_("relocation 0x%llx is not implemented yet"),
725 (unsigned long long) ELF_R_TYPE (info
));
730 switch (ELF_R_TYPE (info
))
732 case R_IA64_PCREL21B
:
735 grub_ia64_make_trampoline (tr
, addend
+ sym_addr
);
736 noff
= ((char *) tr
- (char *) pe_target
737 - target_section_addr
- (offset
& ~3)) >> 4;
740 grub_util_error ("trampoline offset too big (%"
741 PRIxGRUB_UINT64_T
")", noff
);
742 grub_ia64_add_value_to_slot_20b ((grub_addr_t
) target
, noff
);
746 case R_IA64_LTOFF22X
:
751 sym
= (Elf_Sym
*) ((char *) e
752 + grub_target_to_host (symtab_section
->sh_offset
)
753 + ELF_R_SYM (info
) * grub_target_to_host (symtab_section
->sh_entsize
));
754 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
755 sym_addr
= grub_target_to_host64 (*(grub_uint64_t
*) (pe_target
757 - image_target
->vaddr_offset
));
759 case R_IA64_LTOFF_FPTR22
:
760 *gpptr
= grub_host_to_target64 (addend
+ sym_addr
);
761 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
762 (char *) gpptr
- (char *) pe_target
763 + image_target
->vaddr_offset
);
768 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
771 case R_IA64_PCREL64LSB
:
772 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
774 - target_section_addr
- offset
775 - image_target
->vaddr_offset
);
778 case R_IA64_SEGREL64LSB
:
779 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
780 + addend
+ sym_addr
- target_section_addr
);
782 case R_IA64_DIR64LSB
:
783 case R_IA64_FPTR64LSB
:
784 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
785 + addend
+ sym_addr
);
786 grub_util_info ("relocating a direct entry to 0x%"
787 PRIxGRUB_UINT64_T
" at the offset 0x%llx",
788 grub_target_to_host64 (*target
),
789 (unsigned long long) offset
);
792 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
797 grub_util_error (_("relocation 0x%llx is not implemented yet"),
798 (unsigned long long) ELF_R_TYPE (info
));
805 switch (ELF_R_TYPE (info
))
807 case R_AARCH64_ABS64
:
809 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
) + sym_addr
);
812 case R_AARCH64_JUMP26
:
813 case R_AARCH64_CALL26
:
816 sym_addr
-= SUFFIX (entry_point
);
817 if (!grub_arm_64_check_xxxx26_offset (sym_addr
))
818 grub_util_error ("%s", _("CALL26 Relocation out of range"));
820 grub_arm64_set_xxxx26_offset((grub_uint32_t
*)target
,
825 grub_util_error (_("relocation %d is not implemented yet"),
826 (unsigned long long) ELF_R_TYPE (info
));
832 #if defined(MKIMAGE_ELF32)
836 sym_addr
-= SUFFIX (entry_point
);
837 switch (ELF_R_TYPE (info
))
841 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
842 (int) sym_addr
, (int) sym_addr
);
843 /* Data will be naturally aligned */
845 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
) + sym_addr
);
848 /* Happens when compiled with -march=armv4.
849 Since currently we need at least armv5, keep bx as-is.
854 case R_ARM_THM_JUMP24
:
855 case R_ARM_THM_JUMP19
:
858 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
859 (unsigned long) ((char *) target
864 grub_uint32_t tr_addr
;
865 grub_int32_t new_offset
;
866 tr_addr
= (char *) tr
- (char *) pe_target
867 - target_section_addr
;
868 new_offset
= sym_addr
- tr_addr
- 12;
870 if (!grub_arm_jump24_check_offset (new_offset
))
871 return grub_util_error ("jump24 relocation out of range");
873 tr
[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
874 tr
[1] = grub_host_to_target32 (((new_offset
>> 2) & 0xffffff) | 0xea000000); /* b new_offset */
876 sym_addr
= tr_addr
| 1;
879 /* Thumb instructions can be 16-bit aligned */
880 if (ELF_R_TYPE (info
) == R_ARM_THM_JUMP19
)
881 err
= grub_arm_reloc_thm_jump19 ((grub_uint16_t
*) target
, sym_addr
);
883 err
= grub_arm_reloc_thm_call ((grub_uint16_t
*) target
,
886 grub_util_error ("%s", grub_errmsg
);
894 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target
- (char *) e
), sym_addr
);
897 grub_uint32_t tr_addr
;
898 grub_int32_t new_offset
;
899 tr_addr
= (char *) tr
- (char *) pe_target
900 - target_section_addr
;
901 new_offset
= sym_addr
- tr_addr
- 12;
903 /* There is no immediate version of bx, only register one... */
904 tr
[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
905 tr
[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
906 tr
[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
907 tr
[3] = grub_host_to_target32 (new_offset
| 1);
912 err
= grub_arm_reloc_jump24 (target
,
915 grub_util_error ("%s", grub_errmsg
);
920 grub_util_error (_("relocation 0x%x is not implemented yet!"), ELF_R_TYPE (info
));
925 #endif /* MKIMAGE_ELF32 */
927 grub_util_error ("unknown architecture type %d",
928 image_target
->elf_target
);
934 /* Add a PE32's fixup entry for a relocation. Return the resulting address
935 after having written to the file OUT. */
937 SUFFIX (add_fixup_entry
) (struct fixup_block_list
**cblock
, grub_uint16_t type
,
938 Elf_Addr addr
, int flush
, Elf_Addr current_address
,
939 const struct grub_install_image_target_desc
*image_target
)
941 struct grub_pe32_fixup_block
*b
;
945 /* First, check if it is necessary to write out the current block. */
946 if ((*cblock
)->state
)
948 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
954 /* Add as much padding as necessary to align the address
955 with a section boundary. */
956 Elf_Addr next_address
;
957 unsigned padding_size
;
960 next_address
= current_address
+ b
->block_size
;
961 padding_size
= ((ALIGN_UP (next_address
, image_target
->section_align
)
964 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
965 grub_util_info ("adding %d padding fixup entries", padding_size
);
966 while (padding_size
--)
968 b
->entries
[cur_index
++] = 0;
972 else while (b
->block_size
& (8 - 1))
974 /* If not aligned with a 32-bit boundary, add
978 grub_util_info ("adding a padding fixup entry");
979 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
980 b
->entries
[cur_index
] = 0;
985 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
986 b
->block_size
, b
->page_rva
);
987 size
= b
->block_size
;
988 current_address
+= size
;
989 b
->page_rva
= grub_host_to_target32 (b
->page_rva
);
990 b
->block_size
= grub_host_to_target32 (b
->block_size
);
991 (*cblock
)->next
= xmalloc (sizeof (**cblock
) + 2 * 0x1000);
992 memset ((*cblock
)->next
, 0, sizeof (**cblock
) + 2 * 0x1000);
993 *cblock
= (*cblock
)->next
;
1001 grub_uint16_t entry
;
1004 /* If not allocated yet, allocate a block with enough entries. */
1005 if (! (*cblock
)->state
)
1007 (*cblock
)->state
= 1;
1009 /* The spec does not mention the requirement of a Page RVA.
1010 Here, align the address with a 4K boundary for safety. */
1011 b
->page_rva
= (addr
& ~(0x1000 - 1));
1012 b
->block_size
= sizeof (*b
);
1016 if (b
->block_size
>= sizeof (*b
) + 2 * 0x1000)
1017 grub_util_error ("too many fixup entries");
1019 /* Add a new entry. */
1020 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1021 entry
= GRUB_PE32_FIXUP_ENTRY (type
, addr
- b
->page_rva
);
1022 b
->entries
[cur_index
] = grub_host_to_target16 (entry
);
1026 return current_address
;
1029 /* Make a .reloc section. */
1031 SUFFIX (make_reloc_section
) (Elf_Ehdr
*e
, void **out
,
1032 Elf_Addr
*section_addresses
, Elf_Shdr
*sections
,
1033 Elf_Half section_entsize
, Elf_Half num_sections
,
1035 Elf_Addr jumpers
, grub_size_t njumpers
,
1036 const struct grub_install_image_target_desc
*image_target
)
1040 struct fixup_block_list
*lst
, *lst0
;
1041 Elf_Addr current_address
= 0;
1043 lst
= lst0
= xmalloc (sizeof (*lst
) + 2 * 0x1000);
1044 memset (lst
, 0, sizeof (*lst
) + 2 * 0x1000);
1046 for (i
= 0, s
= sections
; i
< num_sections
;
1047 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1048 if ((grub_target_to_host32 (s
->sh_type
) == SHT_REL
) ||
1049 (grub_target_to_host32 (s
->sh_type
) == SHT_RELA
))
1052 Elf_Word rtab_size
, r_size
, num_rs
;
1053 Elf_Off rtab_offset
;
1054 Elf_Addr section_address
;
1057 grub_util_info ("translating the relocation section %s",
1058 strtab
+ grub_le_to_cpu32 (s
->sh_name
));
1060 rtab_size
= grub_target_to_host (s
->sh_size
);
1061 r_size
= grub_target_to_host (s
->sh_entsize
);
1062 rtab_offset
= grub_target_to_host (s
->sh_offset
);
1063 num_rs
= rtab_size
/ r_size
;
1065 section_address
= section_addresses
[grub_le_to_cpu32 (s
->sh_info
)];
1067 for (j
= 0, r
= (Elf_Rel
*) ((char *) e
+ rtab_offset
);
1069 j
++, r
= (Elf_Rel
*) ((char *) r
+ r_size
))
1074 offset
= grub_target_to_host (r
->r_offset
);
1075 info
= grub_target_to_host (r
->r_info
);
1077 /* Necessary to relocate only absolute addresses. */
1078 switch (image_target
->elf_target
)
1081 if (ELF_R_TYPE (info
) == R_386_32
)
1085 addr
= section_address
+ offset
;
1086 grub_util_info ("adding a relocation entry for 0x%llx",
1087 (unsigned long long) addr
);
1089 = SUFFIX (add_fixup_entry
) (&lst
,
1090 GRUB_PE32_REL_BASED_HIGHLOW
,
1091 addr
, 0, current_address
,
1096 if ((ELF_R_TYPE (info
) == R_X86_64_32
) ||
1097 (ELF_R_TYPE (info
) == R_X86_64_32S
))
1099 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1101 else if (ELF_R_TYPE (info
) == R_X86_64_64
)
1105 addr
= section_address
+ offset
;
1106 grub_util_info ("adding a relocation entry for 0x%llx",
1107 (unsigned long long) addr
);
1109 = SUFFIX (add_fixup_entry
) (&lst
,
1110 GRUB_PE32_REL_BASED_DIR64
,
1117 switch (ELF_R_TYPE (info
))
1119 case R_IA64_PCREL64LSB
:
1121 case R_IA64_PCREL21B
:
1122 case R_IA64_LTOFF_FPTR22
:
1123 case R_IA64_LTOFF22X
:
1124 case R_IA64_LTOFF22
:
1125 case R_IA64_GPREL22
:
1126 case R_IA64_SEGREL64LSB
:
1129 case R_IA64_FPTR64LSB
:
1130 case R_IA64_DIR64LSB
:
1135 addr
= section_address
+ offset
;
1136 grub_util_info ("adding a relocation entry for 0x%llx",
1137 (unsigned long long) addr
);
1139 = SUFFIX (add_fixup_entry
) (&lst
,
1140 GRUB_PE32_REL_BASED_DIR64
,
1148 grub_util_error (_("relocation 0x%llx is not implemented yet"),
1149 (unsigned long long) ELF_R_TYPE (info
));
1154 switch (ELF_R_TYPE (info
))
1156 case R_AARCH64_ABS64
:
1160 addr
= section_address
+ offset
;
1162 = SUFFIX (add_fixup_entry
) (&lst
,
1163 GRUB_PE32_REL_BASED_DIR64
,
1164 addr
, 0, current_address
,
1168 /* Relative relocations do not require fixup entries. */
1169 case R_AARCH64_CALL26
:
1170 case R_AARCH64_JUMP26
:
1173 grub_util_error (_("fixup for relocation %d is not implemented yet"),
1174 (unsigned long long) ELF_R_TYPE (info
));
1179 #if defined(MKIMAGE_ELF32)
1181 switch (ELF_R_TYPE (info
))
1184 /* Relative relocations do not require fixup entries. */
1186 case R_ARM_THM_CALL
:
1187 case R_ARM_THM_JUMP19
:
1188 case R_ARM_THM_JUMP24
:
1193 addr
= section_address
+ offset
;
1194 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__
, (unsigned int) addr
, (unsigned int) current_address
);
1197 /* Create fixup entry for PE/COFF loader */
1202 addr
= section_address
+ offset
;
1204 = SUFFIX (add_fixup_entry
) (&lst
,
1205 GRUB_PE32_REL_BASED_HIGHLOW
,
1206 addr
, 0, current_address
,
1211 grub_util_error (_("fixup for relocation 0x%x not implemented"), ELF_R_TYPE (info
));
1215 #endif /* defined(MKIMAGE_ELF32) */
1217 grub_util_error ("unknown machine type 0x%x", image_target
->elf_target
);
1222 if (image_target
->elf_target
== EM_IA_64
)
1223 for (i
= 0; i
< njumpers
; i
++)
1224 current_address
= SUFFIX (add_fixup_entry
) (&lst
,
1225 GRUB_PE32_REL_BASED_DIR64
,
1230 current_address
= SUFFIX (add_fixup_entry
) (&lst
, 0, 0, 1, current_address
, image_target
);
1234 ptr
= *out
= xmalloc (current_address
);
1235 for (lst
= lst0
; lst
; lst
= lst
->next
)
1238 memcpy (ptr
, &lst
->b
, grub_target_to_host32 (lst
->b
.block_size
));
1239 ptr
+= grub_target_to_host32 (lst
->b
.block_size
);
1241 assert ((current_address
+ (grub_uint8_t
*) *out
) == ptr
);
1244 for (lst
= lst0
; lst
; )
1246 struct fixup_block_list
*next
;
1252 return current_address
;
1255 /* Determine if this section is a text section. Return false if this
1256 section is not allocated. */
1258 SUFFIX (is_text_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
1260 if (image_target
->id
!= IMAGE_EFI
1261 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
1263 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
1264 == (SHF_EXECINSTR
| SHF_ALLOC
));
1267 /* Determine if this section is a data section. This assumes that
1268 BSS is also a data section, since the converter initializes BSS
1269 when producing PE32 to avoid a bug in EFI implementations. */
1271 SUFFIX (is_data_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
1273 if (image_target
->id
!= IMAGE_EFI
1274 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
1276 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
1280 /* Return if the ELF header is valid. */
1282 SUFFIX (check_elf_header
) (Elf_Ehdr
*e
, size_t size
, const struct grub_install_image_target_desc
*image_target
)
1284 if (size
< sizeof (*e
)
1285 || e
->e_ident
[EI_MAG0
] != ELFMAG0
1286 || e
->e_ident
[EI_MAG1
] != ELFMAG1
1287 || e
->e_ident
[EI_MAG2
] != ELFMAG2
1288 || e
->e_ident
[EI_MAG3
] != ELFMAG3
1289 || e
->e_ident
[EI_VERSION
] != EV_CURRENT
1290 || e
->e_ident
[EI_CLASS
] != ELFCLASSXX
1291 || e
->e_version
!= grub_host_to_target32 (EV_CURRENT
))
1297 /* Locate section addresses by merging code sections and data sections
1298 into .text and .data, respectively. Return the array of section
1301 SUFFIX (locate_sections
) (const char *kernel_path
,
1302 Elf_Shdr
*sections
, Elf_Half section_entsize
,
1303 Elf_Half num_sections
, const char *strtab
,
1304 size_t *exec_size
, size_t *kernel_sz
,
1306 const struct grub_install_image_target_desc
*image_target
)
1309 Elf_Addr current_address
;
1310 Elf_Addr
*section_addresses
;
1315 section_addresses
= xmalloc (sizeof (*section_addresses
) * num_sections
);
1316 memset (section_addresses
, 0, sizeof (*section_addresses
) * num_sections
);
1318 current_address
= 0;
1320 for (i
= 0, s
= sections
;
1322 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1323 if ((grub_target_to_host (s
->sh_flags
) & SHF_ALLOC
)
1324 && grub_host_to_target32 (s
->sh_addralign
) > *all_align
)
1325 *all_align
= grub_host_to_target32 (s
->sh_addralign
);
1329 for (i
= 0, s
= sections
;
1331 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1332 if (SUFFIX (is_text_section
) (s
, image_target
))
1334 Elf_Word align
= grub_host_to_target_addr (s
->sh_addralign
);
1335 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1337 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1338 align
) - image_target
->vaddr_offset
;
1339 grub_util_info ("locating the section %s at 0x%llx",
1340 name
, (unsigned long long) current_address
);
1341 if (image_target
->id
!= IMAGE_EFI
)
1343 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1344 - image_target
->link_addr
;
1345 if (grub_host_to_target_addr (s
->sh_addr
)
1346 != image_target
->link_addr
)
1347 grub_util_error ("`%s' is miscompiled: it's start address is 0x%llx"
1348 " instead of 0x%llx: ld.gold bug?",
1350 (unsigned long long) grub_host_to_target_addr (s
->sh_addr
),
1351 (unsigned long long) image_target
->link_addr
);
1353 section_addresses
[i
] = current_address
;
1354 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1357 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1358 image_target
->section_align
)
1359 - image_target
->vaddr_offset
;
1360 *exec_size
= current_address
;
1363 for (i
= 0, s
= sections
;
1365 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1366 if (SUFFIX (is_data_section
) (s
, image_target
))
1368 Elf_Word align
= grub_host_to_target_addr (s
->sh_addralign
);
1369 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1372 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1374 - image_target
->vaddr_offset
;
1376 grub_util_info ("locating the section %s at 0x%llx",
1377 name
, (unsigned long long) current_address
);
1378 if (image_target
->id
!= IMAGE_EFI
)
1379 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1380 - image_target
->link_addr
;
1381 section_addresses
[i
] = current_address
;
1382 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1385 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1386 image_target
->section_align
) - image_target
->vaddr_offset
;
1387 *kernel_sz
= current_address
;
1388 return section_addresses
;
1392 SUFFIX (load_image
) (const char *kernel_path
, size_t *exec_size
,
1393 size_t *kernel_sz
, size_t *bss_size
,
1394 size_t total_module_size
, grub_uint64_t
*start
,
1395 void **reloc_section
, size_t *reloc_size
,
1397 const struct grub_install_image_target_desc
*image_target
)
1399 char *kernel_img
, *out_img
;
1403 Elf_Addr
*section_addresses
;
1404 Elf_Addr
*section_vaddresses
;
1407 Elf_Half num_sections
;
1408 Elf_Off section_offset
;
1409 Elf_Half section_entsize
;
1410 grub_size_t kernel_size
;
1411 grub_size_t ia64jmp_off
= 0, tramp_off
= 0, ia64_got_off
= 0;
1412 unsigned ia64jmpnum
= 0;
1413 Elf_Shdr
*symtab_section
= 0;
1414 grub_size_t got
= 0;
1418 kernel_size
= grub_util_get_image_size (kernel_path
);
1419 kernel_img
= xmalloc (kernel_size
);
1420 grub_util_load_image (kernel_path
, kernel_img
);
1422 e
= (Elf_Ehdr
*) kernel_img
;
1423 if (! SUFFIX (check_elf_header
) (e
, kernel_size
, image_target
))
1424 grub_util_error ("invalid ELF header");
1426 section_offset
= grub_target_to_host (e
->e_shoff
);
1427 section_entsize
= grub_target_to_host16 (e
->e_shentsize
);
1428 num_sections
= grub_target_to_host16 (e
->e_shnum
);
1430 if (kernel_size
< section_offset
+ section_entsize
* num_sections
)
1431 grub_util_error (_("premature end of file %s"), kernel_path
);
1433 sections
= (Elf_Shdr
*) (kernel_img
+ section_offset
);
1435 /* Relocate sections then symbols in the virtual address space. */
1436 s
= (Elf_Shdr
*) ((char *) sections
1437 + grub_host_to_target16 (e
->e_shstrndx
) * section_entsize
);
1438 strtab
= (char *) e
+ grub_host_to_target_addr (s
->sh_offset
);
1440 section_addresses
= SUFFIX (locate_sections
) (kernel_path
,
1441 sections
, section_entsize
,
1442 num_sections
, strtab
,
1443 exec_size
, kernel_sz
, align
,
1446 section_vaddresses
= xmalloc (sizeof (*section_addresses
) * num_sections
);
1448 for (i
= 0; i
< num_sections
; i
++)
1449 section_vaddresses
[i
] = section_addresses
[i
] + image_target
->vaddr_offset
;
1451 if (image_target
->id
!= IMAGE_EFI
)
1453 Elf_Addr current_address
= *kernel_sz
;
1455 for (i
= 0, s
= sections
;
1457 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1458 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
1460 Elf_Word sec_align
= grub_host_to_target_addr (s
->sh_addralign
);
1461 const char *name
= strtab
+ grub_host_to_target32 (s
->sh_name
);
1464 current_address
= ALIGN_UP (current_address
1465 + image_target
->vaddr_offset
,
1467 - image_target
->vaddr_offset
;
1469 grub_util_info ("locating the section %s at 0x%llx",
1470 name
, (unsigned long long) current_address
);
1471 if (image_target
->id
!= IMAGE_EFI
)
1472 current_address
= grub_host_to_target_addr (s
->sh_addr
)
1473 - image_target
->link_addr
;
1475 section_vaddresses
[i
] = current_address
1476 + image_target
->vaddr_offset
;
1477 current_address
+= grub_host_to_target_addr (s
->sh_size
);
1479 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
1480 image_target
->section_align
)
1481 - image_target
->vaddr_offset
;
1482 *bss_size
= current_address
- *kernel_sz
;
1487 if (image_target
->id
== IMAGE_SPARC64_AOUT
1488 || image_target
->id
== IMAGE_SPARC64_RAW
1489 || image_target
->id
== IMAGE_SPARC64_CDCORE
)
1490 *kernel_sz
= ALIGN_UP (*kernel_sz
, image_target
->mod_align
);
1492 if (image_target
->id
== IMAGE_EFI
)
1494 symtab_section
= NULL
;
1495 for (i
= 0, s
= sections
;
1497 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1498 if (s
->sh_type
== grub_host_to_target32 (SHT_SYMTAB
))
1504 #ifdef MKIMAGE_ELF32
1505 if (image_target
->elf_target
== EM_ARM
)
1509 *kernel_sz
= ALIGN_UP (*kernel_sz
, 16);
1511 tramp
= arm_get_trampoline_size (e
, sections
, section_entsize
,
1512 num_sections
, image_target
);
1514 tramp_off
= *kernel_sz
;
1515 *kernel_sz
+= ALIGN_UP (tramp
, 16);
1519 #ifdef MKIMAGE_ELF64
1520 if (image_target
->elf_target
== EM_IA_64
)
1524 *kernel_sz
= ALIGN_UP (*kernel_sz
, 16);
1526 grub_ia64_dl_get_tramp_got_size (e
, &tramp
, &got
);
1528 tramp_off
= *kernel_sz
;
1529 *kernel_sz
+= ALIGN_UP (tramp
, 16);
1531 ia64jmp_off
= *kernel_sz
;
1532 ia64jmpnum
= SUFFIX (count_funcs
) (e
, symtab_section
,
1534 *kernel_sz
+= 16 * ia64jmpnum
;
1536 ia64_got_off
= *kernel_sz
;
1537 *kernel_sz
+= ALIGN_UP (got
, 16);
1541 if (! symtab_section
)
1542 grub_util_error ("%s", _("no symbol table"));
1547 *reloc_section
= NULL
;
1550 out_img
= xmalloc (*kernel_sz
+ total_module_size
);
1552 if (image_target
->id
== IMAGE_EFI
)
1554 *start
= SUFFIX (relocate_symbols
) (e
, sections
, symtab_section
,
1555 section_vaddresses
, section_entsize
,
1557 (char *) out_img
+ ia64jmp_off
,
1559 + image_target
->vaddr_offset
,
1562 grub_util_error ("start symbol is not defined");
1564 SUFFIX (entry_point
) = (Elf_Addr
) *start
;
1566 /* Resolve addresses in the virtual address space. */
1567 SUFFIX (relocate_addresses
) (e
, sections
, section_addresses
,
1569 num_sections
, strtab
,
1570 out_img
, tramp_off
, ia64_got_off
,
1573 *reloc_size
= SUFFIX (make_reloc_section
) (e
, reloc_section
,
1574 section_vaddresses
, sections
,
1575 section_entsize
, num_sections
,
1577 + image_target
->vaddr_offset
,
1578 2 * ia64jmpnum
+ (got
/ 8),
1582 for (i
= 0, s
= sections
;
1584 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
1585 if (SUFFIX (is_data_section
) (s
, image_target
)
1586 || SUFFIX (is_text_section
) (s
, image_target
))
1588 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
1589 memset (out_img
+ section_addresses
[i
], 0,
1590 grub_host_to_target_addr (s
->sh_size
));
1592 memcpy (out_img
+ section_addresses
[i
],
1593 kernel_img
+ grub_host_to_target_addr (s
->sh_offset
),
1594 grub_host_to_target_addr (s
->sh_size
));
1598 free (section_vaddresses
);
1599 free (section_addresses
);
1622 #undef XEN_NOTE_SIZE