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/>.
21 #include <grub/types.h>
23 #include <grub/aout.h>
24 #include <grub/i18n.h>
25 #include <grub/kernel.h>
26 #include <grub/disk.h>
27 #include <grub/emu/misc.h>
28 #include <grub/util/misc.h>
29 #include <grub/util/resolve.h>
30 #include <grub/misc.h>
31 #include <grub/offsets.h>
32 #include <grub/crypto.h>
35 #include <multiboot.h>
42 #include <grub/efi/pe32.h>
43 #include <grub/uboot/image.h>
44 #include <grub/arm/reloc.h>
45 #include <grub/arm64/reloc.h>
46 #include <grub/ia64/reloc.h>
47 #include <grub/osdep/hostfile.h>
48 #include <grub/util/install.h>
49 #include <grub/util/mkimage.h>
51 #include <xen/elfnote.h>
53 #pragma GCC diagnostic ignored "-Wcast-align"
55 #define GRUB_MKIMAGEXX
56 #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
57 #if __SIZEOF_POINTER__ == 8
58 #include "grub-mkimage64.c"
60 #include "grub-mkimage32.c"
64 /* These structures are defined according to the CHRP binding to IEEE1275,
65 "Client Program Format" section. */
67 struct grub_ieee1275_note_desc
69 grub_uint32_t real_mode
;
70 grub_uint32_t real_base
;
71 grub_uint32_t real_size
;
72 grub_uint32_t virt_base
;
73 grub_uint32_t virt_size
;
74 grub_uint32_t load_base
;
77 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
78 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
80 struct grub_ieee1275_note
83 char name
[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME
), 4)];
84 struct grub_ieee1275_note_desc descriptor
;
87 #define GRUB_XEN_NOTE_NAME "Xen"
89 struct fixup_block_list
91 struct fixup_block_list
*next
;
93 struct grub_pe32_fixup_block b
;
96 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
98 struct section_metadata
100 Elf_Half num_sections
;
104 Elf_Half section_entsize
;
110 is_relocatable (const struct grub_install_image_target_desc
*image_target
)
112 return image_target
->id
== IMAGE_EFI
|| image_target
->id
== IMAGE_UBOOT
113 || (image_target
->id
== IMAGE_COREBOOT
&& image_target
->elf_target
== EM_ARM
);
119 * R_ARM_THM_CALL/THM_JUMP24
121 * Relocate Thumb (T32) instruction set relative branches:
125 grub_arm_reloc_thm_call (grub_uint16_t
*target
, Elf32_Addr sym_addr
)
129 offset
= grub_arm_thm_call_get_offset (target
);
131 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr
);
135 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
136 target
, sym_addr
, offset
);
138 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
139 is bigger than 2M (currently under 150K) then we probably have a problem
141 if (offset
< -0x200000 || offset
>= 0x200000)
142 return grub_error (GRUB_ERR_BAD_MODULE
,
143 "THM_CALL Relocation out of range.");
145 grub_dprintf ("dl", " relative destination = %p",
146 (char *) target
+ offset
);
148 return grub_arm_thm_call_set_offset (target
, offset
);
154 * Relocate conditional Thumb (T32) B<c>.W
157 grub_arm_reloc_thm_jump19 (grub_uint16_t
*target
, Elf32_Addr sym_addr
)
162 return grub_error (GRUB_ERR_BAD_MODULE
,
163 "Relocation targeting wrong execution state");
165 offset
= grub_arm_thm_jump19_get_offset (target
);
167 /* Adjust and re-truncate offset */
170 if (!grub_arm_thm_jump19_check_offset (offset
))
171 return grub_error (GRUB_ERR_BAD_MODULE
,
172 "THM_JUMP19 Relocation out of range.");
174 grub_arm_thm_jump19_set_offset (target
, offset
);
176 return GRUB_ERR_NONE
;
182 * Relocate ARM (A32) B
185 grub_arm_reloc_jump24 (grub_uint32_t
*target
, Elf32_Addr sym_addr
)
190 return grub_error (GRUB_ERR_BAD_MODULE
,
191 "Relocation targeting wrong execution state");
193 offset
= grub_arm_jump24_get_offset (target
);
196 if (!grub_arm_jump24_check_offset (offset
))
197 return grub_error (GRUB_ERR_BAD_MODULE
,
198 "JUMP24 Relocation out of range.");
201 grub_arm_jump24_set_offset (target
, offset
);
203 return GRUB_ERR_NONE
;
209 SUFFIX (grub_mkimage_generate_elf
) (const struct grub_install_image_target_desc
*image_target
,
210 int note
, char **core_img
, size_t *core_size
,
211 Elf_Addr target_addr
,
212 struct grub_mkimage_layout
*layout
)
219 int header_size
, footer_size
= 0;
222 int string_size
= sizeof (".text") + sizeof ("mods") + 1;
224 if (image_target
->id
!= IMAGE_LOONGSON_ELF
)
230 footer_size
+= sizeof (struct grub_ieee1275_note
);
232 if (image_target
->id
== IMAGE_XEN
|| image_target
->id
== IMAGE_XEN_PVH
)
236 string_size
+= sizeof (".xen");
237 footer_size
+= (image_target
->id
== IMAGE_XEN
) ? XEN_NOTE_SIZE
: XEN_PVH_NOTE_SIZE
;
239 header_size
= ALIGN_UP (sizeof (*ehdr
) + phnum
* sizeof (*phdr
)
240 + shnum
* sizeof (*shdr
) + string_size
, layout
->align
);
242 program_size
= ALIGN_ADDR (*core_size
);
244 elf_img
= xmalloc (program_size
+ header_size
+ footer_size
);
245 memset (elf_img
, 0, program_size
+ header_size
+ footer_size
);
246 memcpy (elf_img
+ header_size
, *core_img
, *core_size
);
247 ehdr
= (void *) elf_img
;
248 phdr
= (void *) (elf_img
+ sizeof (*ehdr
));
249 shdr
= (void *) (elf_img
+ sizeof (*ehdr
) + phnum
* sizeof (*phdr
));
250 memcpy (ehdr
->e_ident
, ELFMAG
, SELFMAG
);
251 ehdr
->e_ident
[EI_CLASS
] = ELFCLASSXX
;
252 if (!image_target
->bigendian
)
253 ehdr
->e_ident
[EI_DATA
] = ELFDATA2LSB
;
255 ehdr
->e_ident
[EI_DATA
] = ELFDATA2MSB
;
256 ehdr
->e_ident
[EI_VERSION
] = EV_CURRENT
;
257 ehdr
->e_ident
[EI_OSABI
] = ELFOSABI_NONE
;
258 ehdr
->e_type
= grub_host_to_target16 (ET_EXEC
);
259 ehdr
->e_machine
= grub_host_to_target16 (image_target
->elf_target
);
260 ehdr
->e_version
= grub_host_to_target32 (EV_CURRENT
);
262 ehdr
->e_phoff
= grub_host_to_target32 ((char *) phdr
- (char *) ehdr
);
263 ehdr
->e_phentsize
= grub_host_to_target16 (sizeof (*phdr
));
264 ehdr
->e_phnum
= grub_host_to_target16 (phnum
);
266 ehdr
->e_shoff
= grub_host_to_target32 ((grub_uint8_t
*) shdr
267 - (grub_uint8_t
*) ehdr
);
268 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
269 ehdr
->e_shentsize
= grub_host_to_target16 (0);
271 ehdr
->e_shentsize
= grub_host_to_target16 (sizeof (Elf_Shdr
));
272 ehdr
->e_shnum
= grub_host_to_target16 (shnum
);
273 ehdr
->e_shstrndx
= grub_host_to_target16 (1);
275 ehdr
->e_ehsize
= grub_host_to_target16 (sizeof (*ehdr
));
277 phdr
->p_type
= grub_host_to_target32 (PT_LOAD
);
278 phdr
->p_offset
= grub_host_to_target32 (header_size
);
279 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
281 ehdr
->e_entry
= grub_host_to_target32 (target_addr
);
282 phdr
->p_vaddr
= grub_host_to_target32 (target_addr
);
283 phdr
->p_paddr
= grub_host_to_target32 (target_addr
);
284 phdr
->p_align
= grub_host_to_target32 (layout
->align
> image_target
->link_align
?
285 layout
->align
: image_target
->link_align
);
286 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
287 ehdr
->e_flags
= grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
288 | EF_MIPS_PIC
| EF_MIPS_CPIC
);
291 if (image_target
->id
== IMAGE_LOONGSON_ELF
)
293 phdr
->p_filesz
= grub_host_to_target32 (*core_size
);
294 phdr
->p_memsz
= grub_host_to_target32 (*core_size
);
298 grub_uint32_t target_addr_mods
;
299 phdr
->p_filesz
= grub_host_to_target32 (layout
->kernel_size
);
300 if (image_target
->id
== IMAGE_COREBOOT
&& image_target
->elf_target
== EM_ARM
)
301 phdr
->p_memsz
= grub_host_to_target32 (layout
->kernel_size
);
303 phdr
->p_memsz
= grub_host_to_target32 (layout
->kernel_size
+ layout
->bss_size
);
306 phdr
->p_type
= grub_host_to_target32 (PT_GNU_STACK
);
307 phdr
->p_offset
= grub_host_to_target32 (header_size
+ layout
->kernel_size
);
308 phdr
->p_paddr
= phdr
->p_vaddr
= phdr
->p_filesz
= phdr
->p_memsz
= 0;
309 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
310 phdr
->p_align
= grub_host_to_target32 (image_target
->link_align
);
313 phdr
->p_type
= grub_host_to_target32 (PT_LOAD
);
314 phdr
->p_offset
= grub_host_to_target32 (header_size
+ layout
->kernel_size
);
315 phdr
->p_flags
= grub_host_to_target32 (PF_R
| PF_W
| PF_X
);
316 phdr
->p_filesz
= phdr
->p_memsz
317 = grub_host_to_target32 (*core_size
- layout
->kernel_size
);
319 if (image_target
->id
== IMAGE_COREBOOT
&& image_target
->elf_target
== EM_386
)
320 target_addr_mods
= GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR
;
321 else if (image_target
->id
== IMAGE_COREBOOT
&& image_target
->elf_target
== EM_ARM
)
322 target_addr_mods
= ALIGN_UP (target_addr
+ layout
->end
323 + image_target
->mod_gap
,
324 image_target
->mod_align
);
326 target_addr_mods
= ALIGN_UP (target_addr
+ layout
->kernel_size
+ layout
->bss_size
327 + image_target
->mod_gap
,
328 image_target
->mod_align
);
329 phdr
->p_vaddr
= grub_host_to_target_addr (target_addr_mods
);
330 phdr
->p_paddr
= grub_host_to_target_addr (target_addr_mods
);
331 phdr
->p_align
= grub_host_to_target32 (image_target
->link_align
);
334 if (image_target
->id
== IMAGE_XEN
)
336 char *note_start
= (elf_img
+ program_size
+ header_size
);
338 char *ptr
= (char *) note_start
;
340 grub_util_info ("adding XEN NOTE segment");
343 note_ptr
= (Elf_Nhdr
*) ptr
;
344 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
345 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof (PACKAGE_NAME
));
346 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_GUEST_OS
);
347 ptr
+= sizeof (Elf_Nhdr
);
348 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
349 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
350 memcpy (ptr
, PACKAGE_NAME
, sizeof (PACKAGE_NAME
));
351 ptr
+= ALIGN_UP (sizeof (PACKAGE_NAME
), 4);
354 note_ptr
= (Elf_Nhdr
*) ptr
;
355 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
356 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("generic"));
357 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_LOADER
);
358 ptr
+= sizeof (Elf_Nhdr
);
359 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
360 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
361 memcpy (ptr
, "generic", sizeof ("generic"));
362 ptr
+= ALIGN_UP (sizeof ("generic"), 4);
365 note_ptr
= (Elf_Nhdr
*) ptr
;
366 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
367 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("xen-3.0"));
368 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_XEN_VERSION
);
369 ptr
+= sizeof (Elf_Nhdr
);
370 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
371 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
372 memcpy (ptr
, "xen-3.0", sizeof ("xen-3.0"));
373 ptr
+= ALIGN_UP (sizeof ("xen-3.0"), 4);
376 note_ptr
= (Elf_Nhdr
*) ptr
;
377 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
378 note_ptr
->n_descsz
= grub_host_to_target32 (image_target
->voidp_sizeof
);
379 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_ENTRY
);
380 ptr
+= sizeof (Elf_Nhdr
);
381 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
382 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
383 memset (ptr
, 0, image_target
->voidp_sizeof
);
384 ptr
+= image_target
->voidp_sizeof
;
387 note_ptr
= (Elf_Nhdr
*) ptr
;
388 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
389 note_ptr
->n_descsz
= grub_host_to_target32 (image_target
->voidp_sizeof
);
390 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_VIRT_BASE
);
391 ptr
+= sizeof (Elf_Nhdr
);
392 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
393 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
394 memset (ptr
, 0, image_target
->voidp_sizeof
);
395 ptr
+= image_target
->voidp_sizeof
;
398 if (image_target
->elf_target
== EM_386
)
400 note_ptr
= (Elf_Nhdr
*) ptr
;
401 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
402 note_ptr
->n_descsz
= grub_host_to_target32 (sizeof ("yes,bimodal"));
403 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_PAE_MODE
);
404 ptr
+= sizeof (Elf_Nhdr
);
405 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
406 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
407 memcpy (ptr
, "yes", sizeof ("yes"));
408 ptr
+= ALIGN_UP (sizeof ("yes"), 4);
411 assert (XEN_NOTE_SIZE
== (ptr
- note_start
));
414 phdr
->p_type
= grub_host_to_target32 (PT_NOTE
);
415 phdr
->p_flags
= grub_host_to_target32 (PF_R
);
416 phdr
->p_align
= grub_host_to_target32 (image_target
->voidp_sizeof
);
419 phdr
->p_filesz
= grub_host_to_target32 (XEN_NOTE_SIZE
);
421 phdr
->p_offset
= grub_host_to_target32 (header_size
+ program_size
);
424 if (image_target
->id
== IMAGE_XEN_PVH
)
426 char *note_start
= (elf_img
+ program_size
+ header_size
);
428 char *ptr
= (char *) note_start
;
430 grub_util_info ("adding XEN NOTE segment");
433 note_ptr
= (Elf_Nhdr
*) ptr
;
434 note_ptr
->n_namesz
= grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME
));
435 note_ptr
->n_descsz
= grub_host_to_target32 (image_target
->voidp_sizeof
);
436 note_ptr
->n_type
= grub_host_to_target32 (XEN_ELFNOTE_PHYS32_ENTRY
);
437 ptr
+= sizeof (Elf_Nhdr
);
438 memcpy (ptr
, GRUB_XEN_NOTE_NAME
, sizeof (GRUB_XEN_NOTE_NAME
));
439 ptr
+= ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME
), 4);
440 memset (ptr
, 0, image_target
->voidp_sizeof
);
441 *(grub_uint32_t
*) ptr
= GRUB_KERNEL_I386_XEN_PVH_LINK_ADDR
;
442 ptr
+= image_target
->voidp_sizeof
;
444 assert (XEN_PVH_NOTE_SIZE
== (ptr
- note_start
));
447 phdr
->p_type
= grub_host_to_target32 (PT_NOTE
);
448 phdr
->p_flags
= grub_host_to_target32 (PF_R
);
449 phdr
->p_align
= grub_host_to_target32 (image_target
->voidp_sizeof
);
452 phdr
->p_filesz
= grub_host_to_target32 (XEN_PVH_NOTE_SIZE
);
454 phdr
->p_offset
= grub_host_to_target32 (header_size
+ program_size
);
459 int note_size
= sizeof (struct grub_ieee1275_note
);
460 struct grub_ieee1275_note
*note_ptr
= (struct grub_ieee1275_note
*)
461 (elf_img
+ program_size
+ header_size
);
463 grub_util_info ("adding CHRP NOTE segment");
465 note_ptr
->header
.n_namesz
= grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME
));
466 note_ptr
->header
.n_descsz
= grub_host_to_target32 (note_size
);
467 note_ptr
->header
.n_type
= grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE
);
468 strcpy (note_ptr
->name
, GRUB_IEEE1275_NOTE_NAME
);
469 note_ptr
->descriptor
.real_mode
= grub_host_to_target32 (0xffffffff);
470 note_ptr
->descriptor
.real_base
= grub_host_to_target32 (0x00c00000);
471 note_ptr
->descriptor
.real_size
= grub_host_to_target32 (0xffffffff);
472 note_ptr
->descriptor
.virt_base
= grub_host_to_target32 (0xffffffff);
473 note_ptr
->descriptor
.virt_size
= grub_host_to_target32 (0xffffffff);
474 note_ptr
->descriptor
.load_base
= grub_host_to_target32 (0x00004000);
477 phdr
->p_type
= grub_host_to_target32 (PT_NOTE
);
478 phdr
->p_flags
= grub_host_to_target32 (PF_R
);
479 phdr
->p_align
= grub_host_to_target32 (image_target
->voidp_sizeof
);
482 phdr
->p_filesz
= grub_host_to_target32 (note_size
);
484 phdr
->p_offset
= grub_host_to_target32 (header_size
+ program_size
);
488 char *str_start
= (elf_img
+ sizeof (*ehdr
) + phnum
* sizeof (*phdr
)
489 + shnum
* sizeof (*shdr
));
490 char *ptr
= str_start
+ 1;
494 shdr
->sh_name
= grub_host_to_target32 (0);
495 shdr
->sh_type
= grub_host_to_target32 (SHT_STRTAB
);
496 shdr
->sh_addr
= grub_host_to_target_addr (0);
497 shdr
->sh_offset
= grub_host_to_target_addr (str_start
- elf_img
);
498 shdr
->sh_size
= grub_host_to_target32 (string_size
);
499 shdr
->sh_link
= grub_host_to_target32 (0);
500 shdr
->sh_info
= grub_host_to_target32 (0);
501 shdr
->sh_addralign
= grub_host_to_target32 (layout
->align
);
502 shdr
->sh_entsize
= grub_host_to_target32 (0);
505 memcpy (ptr
, ".text", sizeof (".text"));
507 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
508 ptr
+= sizeof (".text");
509 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
510 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
);
511 shdr
->sh_offset
= grub_host_to_target_addr (header_size
);
512 shdr
->sh_size
= grub_host_to_target32 (layout
->kernel_size
);
513 shdr
->sh_link
= grub_host_to_target32 (0);
514 shdr
->sh_info
= grub_host_to_target32 (0);
515 shdr
->sh_addralign
= grub_host_to_target32 (layout
->align
);
516 shdr
->sh_entsize
= grub_host_to_target32 (0);
519 memcpy (ptr
, "mods", sizeof ("mods"));
520 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
521 ptr
+= sizeof ("mods");
522 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
523 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
+ layout
->kernel_size
);
524 shdr
->sh_offset
= grub_host_to_target_addr (header_size
+ layout
->kernel_size
);
525 shdr
->sh_size
= grub_host_to_target32 (*core_size
- layout
->kernel_size
);
526 shdr
->sh_link
= grub_host_to_target32 (0);
527 shdr
->sh_info
= grub_host_to_target32 (0);
528 shdr
->sh_addralign
= grub_host_to_target32 (image_target
->voidp_sizeof
);
529 shdr
->sh_entsize
= grub_host_to_target32 (0);
532 if (image_target
->id
== IMAGE_XEN
|| image_target
->id
== IMAGE_XEN_PVH
)
534 memcpy (ptr
, ".xen", sizeof (".xen"));
535 shdr
->sh_name
= grub_host_to_target32 (ptr
- str_start
);
536 ptr
+= sizeof (".xen");
537 shdr
->sh_type
= grub_host_to_target32 (SHT_PROGBITS
);
538 shdr
->sh_addr
= grub_host_to_target_addr (target_addr
+ layout
->kernel_size
);
539 shdr
->sh_offset
= grub_host_to_target_addr (program_size
+ header_size
);
540 if (image_target
->id
== IMAGE_XEN
)
541 shdr
->sh_size
= grub_host_to_target32 (XEN_NOTE_SIZE
);
543 shdr
->sh_size
= grub_host_to_target32 (XEN_PVH_NOTE_SIZE
);
544 shdr
->sh_link
= grub_host_to_target32 (0);
545 shdr
->sh_info
= grub_host_to_target32 (0);
546 shdr
->sh_addralign
= grub_host_to_target32 (image_target
->voidp_sizeof
);
547 shdr
->sh_entsize
= grub_host_to_target32 (0);
554 *core_size
= program_size
+ header_size
+ footer_size
;
557 /* Relocate symbols; note that this function overwrites the symbol table.
558 Return the address of a start symbol. */
560 SUFFIX (relocate_symbols
) (Elf_Ehdr
*e
, struct section_metadata
*smd
,
561 void *jumpers
, Elf_Addr jumpers_addr
,
562 Elf_Addr bss_start
, Elf_Addr end
,
563 const struct grub_install_image_target_desc
*image_target
)
565 Elf_Word symtab_size
, sym_size
, num_syms
;
566 Elf_Off symtab_offset
;
567 Elf_Addr start_address
= (Elf_Addr
) -1;
570 Elf_Shdr
*symtab_section
;
572 grub_uint64_t
*jptr
= jumpers
;
574 symtab_section
= (Elf_Shdr
*) ((char *) smd
->sections
575 + grub_target_to_host32 (smd
->symtab
->sh_link
)
576 * smd
->section_entsize
);
577 symtab
= (char *) e
+ grub_target_to_host (symtab_section
->sh_offset
);
579 symtab_size
= grub_target_to_host (smd
->symtab
->sh_size
);
580 sym_size
= grub_target_to_host (smd
->symtab
->sh_entsize
);
581 symtab_offset
= grub_target_to_host (smd
->symtab
->sh_offset
);
582 num_syms
= symtab_size
/ sym_size
;
584 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
586 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
588 Elf_Section cur_index
;
591 name
= symtab
+ grub_target_to_host32 (sym
->st_name
);
593 cur_index
= grub_target_to_host16 (sym
->st_shndx
);
594 if (cur_index
== STN_ABS
)
598 else if (cur_index
== STN_UNDEF
)
600 if (sym
->st_name
&& grub_strcmp (name
, "__bss_start") == 0)
601 sym
->st_value
= bss_start
;
602 else if (sym
->st_name
&& grub_strcmp (name
, "_end") == 0)
604 else if (sym
->st_name
)
605 grub_util_error ("undefined symbol %s", name
);
609 else if (cur_index
>= smd
->num_sections
)
610 grub_util_error ("section %d does not exist", cur_index
);
613 sym
->st_value
= (grub_target_to_host (sym
->st_value
)
614 + smd
->vaddrs
[cur_index
]);
617 if (image_target
->elf_target
== EM_IA_64
&& ELF_ST_TYPE (sym
->st_info
)
620 *jptr
= grub_host_to_target64 (sym
->st_value
);
621 sym
->st_value
= (char *) jptr
- (char *) jumpers
+ jumpers_addr
;
626 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
627 " (0x%" GRUB_HOST_PRIxLONG_LONG
")", name
,
628 (unsigned long long) sym
->st_value
,
629 (unsigned long long) smd
->vaddrs
[cur_index
]);
631 if (start_address
== (Elf_Addr
)-1)
632 if (strcmp (name
, "_start") == 0 || strcmp (name
, "start") == 0)
633 start_address
= sym
->st_value
;
636 return start_address
;
639 /* Return the address of a symbol at the index I in the section S. */
641 SUFFIX (get_symbol_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Word i
,
642 const struct grub_install_image_target_desc
*image_target
)
646 sym
= (Elf_Sym
*) ((char *) e
647 + grub_target_to_host (s
->sh_offset
)
648 + i
* grub_target_to_host (s
->sh_entsize
));
649 return sym
->st_value
;
652 /* Return the address of a modified value. */
654 SUFFIX (get_target_address
) (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Addr offset
,
655 const struct grub_install_image_target_desc
*image_target
)
657 return (Elf_Addr
*) ((char *) e
+ grub_target_to_host (s
->sh_offset
) + offset
);
662 SUFFIX (count_funcs
) (Elf_Ehdr
*e
, Elf_Shdr
*symtab_section
,
663 const struct grub_install_image_target_desc
*image_target
)
665 Elf_Word symtab_size
, sym_size
, num_syms
;
666 Elf_Off symtab_offset
;
671 symtab_size
= grub_target_to_host (symtab_section
->sh_size
);
672 sym_size
= grub_target_to_host (symtab_section
->sh_entsize
);
673 symtab_offset
= grub_target_to_host (symtab_section
->sh_offset
);
674 num_syms
= symtab_size
/ sym_size
;
676 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
678 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
679 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
687 /* Deal with relocation information. This function relocates addresses
688 within the virtual address space starting from 0. So only relative
689 addresses can be fully resolved. Absolute addresses must be relocated
690 again by a PE32 relocator when loaded. */
692 arm_get_trampoline_size (Elf_Ehdr
*e
,
694 Elf_Half section_entsize
,
695 Elf_Half num_sections
,
696 const struct grub_install_image_target_desc
*image_target
)
702 for (i
= 0, s
= sections
;
704 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
705 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
706 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
709 Elf_Word rtab_size
, r_size
, num_rs
;
711 Elf_Shdr
*symtab_section
;
714 symtab_section
= (Elf_Shdr
*) ((char *) sections
715 + (grub_target_to_host32 (s
->sh_link
)
718 rtab_size
= grub_target_to_host (s
->sh_size
);
719 r_size
= grub_target_to_host (s
->sh_entsize
);
720 rtab_offset
= grub_target_to_host (s
->sh_offset
);
721 num_rs
= rtab_size
/ r_size
;
723 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
725 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
730 info
= grub_target_to_host (r
->r_info
);
731 sym_addr
= SUFFIX (get_symbol_address
) (e
, symtab_section
,
732 ELF_R_SYM (info
), image_target
);
734 sym_addr
+= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
735 grub_target_to_host (r
->r_addend
) : 0;
737 switch (ELF_R_TYPE (info
))
743 case R_ARM_THM_JUMP24
:
744 case R_ARM_THM_JUMP19
:
756 grub_util_error (_("relocation 0x%x is not implemented yet"),
757 (unsigned int) ELF_R_TYPE (info
));
767 SUFFIX (is_kept_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
);
769 SUFFIX (is_kept_reloc_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
,
770 struct section_metadata
*smd
);
772 /* Deal with relocation information. This function relocates addresses
773 within the virtual address space starting from 0. So only relative
774 addresses can be fully resolved. Absolute addresses must be relocated
775 again by a PE32 relocator when loaded. */
777 SUFFIX (relocate_addrs
) (Elf_Ehdr
*e
, struct section_metadata
*smd
,
778 char *pe_target
, Elf_Addr tramp_off
, Elf_Addr got_off
,
779 const struct grub_install_image_target_desc
*image_target
)
784 struct grub_ia64_trampoline
*tr
= (void *) (pe_target
+ tramp_off
);
785 grub_uint64_t
*gpptr
= (void *) (pe_target
+ got_off
);
786 unsigned unmatched_adr_got_page
= 0;
787 #define MASK19 ((1 << 19) - 1)
789 grub_uint32_t
*tr
= (void *) (pe_target
+ tramp_off
);
792 for (i
= 0, s
= smd
->sections
;
793 i
< smd
->num_sections
;
794 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
795 if ((s
->sh_type
== grub_host_to_target32 (SHT_REL
)) ||
796 (s
->sh_type
== grub_host_to_target32 (SHT_RELA
)))
799 Elf_Word rtab_size
, r_size
, num_rs
;
801 Elf_Word target_section_index
;
802 Elf_Addr target_section_addr
;
803 Elf_Shdr
*target_section
;
806 if (!SUFFIX (is_kept_section
) (s
, image_target
) &&
807 !SUFFIX (is_kept_reloc_section
) (s
, image_target
, smd
))
809 grub_util_info ("not translating relocations for omitted section %s",
810 smd
->strtab
+ grub_le_to_cpu32 (s
->sh_name
));
814 target_section_index
= grub_target_to_host32 (s
->sh_info
);
815 target_section_addr
= smd
->addrs
[target_section_index
];
816 target_section
= (Elf_Shdr
*) ((char *) smd
->sections
817 + (target_section_index
818 * smd
->section_entsize
));
820 grub_util_info ("dealing with the relocation section %s for %s",
821 smd
->strtab
+ grub_target_to_host32 (s
->sh_name
),
822 smd
->strtab
+ grub_target_to_host32 (target_section
->sh_name
));
824 rtab_size
= grub_target_to_host (s
->sh_size
);
825 r_size
= grub_target_to_host (s
->sh_entsize
);
826 rtab_offset
= grub_target_to_host (s
->sh_offset
);
827 num_rs
= rtab_size
/ r_size
;
829 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
831 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
839 offset
= grub_target_to_host (r
->r_offset
);
840 target
= SUFFIX (get_target_address
) (e
, target_section
,
841 offset
, image_target
);
842 info
= grub_target_to_host (r
->r_info
);
843 sym_addr
= SUFFIX (get_symbol_address
) (e
, smd
->symtab
,
844 ELF_R_SYM (info
), image_target
);
846 addend
= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
847 grub_target_to_host (r
->r_addend
) : 0;
849 switch (image_target
->elf_target
)
852 switch (ELF_R_TYPE (info
))
858 /* This is absolute. */
859 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
860 + addend
+ sym_addr
);
861 grub_util_info ("relocating an R_386_32 entry to 0x%"
862 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
863 GRUB_HOST_PRIxLONG_LONG
,
864 (unsigned long long) *target
,
865 (unsigned long long) offset
);
869 /* This is relative. */
870 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
)
872 - target_section_addr
- offset
873 - image_target
->vaddr_offset
);
874 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
875 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
876 GRUB_HOST_PRIxLONG_LONG
,
877 (unsigned long long) *target
,
878 (unsigned long long) offset
);
881 grub_util_error (_("relocation 0x%x is not implemented yet"),
882 (unsigned int) ELF_R_TYPE (info
));
888 switch (ELF_R_TYPE (info
))
895 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
896 + addend
+ sym_addr
);
897 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
898 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
899 GRUB_HOST_PRIxLONG_LONG
,
900 (unsigned long long) *target
,
901 (unsigned long long) offset
);
907 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
908 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
910 - target_section_addr
- offset
911 - image_target
->vaddr_offset
);
912 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
913 GRUB_HOST_PRIxLONG_LONG
,
914 *t32
, (unsigned long long) offset
);
920 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
922 - target_section_addr
- offset
923 - image_target
->vaddr_offset
);
924 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
925 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
926 GRUB_HOST_PRIxLONG_LONG
,
927 (unsigned long long) *target
,
928 (unsigned long long) offset
);
935 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
936 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
937 + addend
+ sym_addr
);
938 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
939 GRUB_HOST_PRIxLONG_LONG
,
940 *t32
, (unsigned long long) offset
);
945 grub_util_error (_("relocation 0x%x is not implemented yet"),
946 (unsigned int) ELF_R_TYPE (info
));
951 switch (ELF_R_TYPE (info
))
953 case R_IA64_PCREL21B
:
956 grub_ia64_make_trampoline (tr
, addend
+ sym_addr
);
957 noff
= ((char *) tr
- (char *) pe_target
958 - target_section_addr
- (offset
& ~3)) >> 4;
961 grub_util_error ("trampoline offset too big (%"
962 GRUB_HOST_PRIxLONG_LONG
")",
963 (unsigned long long) noff
);
964 grub_ia64_add_value_to_slot_20b ((grub_addr_t
) target
, noff
);
968 case R_IA64_LTOFF22X
:
973 sym
= (Elf_Sym
*) ((char *) e
974 + grub_target_to_host (smd
->symtab
->sh_offset
)
975 + ELF_R_SYM (info
) * grub_target_to_host (smd
->symtab
->sh_entsize
));
976 if (ELF_ST_TYPE (sym
->st_info
) == STT_FUNC
)
977 sym_addr
= grub_target_to_host64 (*(grub_uint64_t
*) (pe_target
979 - image_target
->vaddr_offset
));
982 case R_IA64_LTOFF_FPTR22
:
983 *gpptr
= grub_host_to_target64 (addend
+ sym_addr
);
984 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
985 (char *) gpptr
- (char *) pe_target
986 + image_target
->vaddr_offset
);
991 grub_ia64_add_value_to_slot_21 ((grub_addr_t
) target
,
994 case R_IA64_GPREL64I
:
995 grub_ia64_set_immu64 ((grub_addr_t
) target
,
998 case R_IA64_PCREL64LSB
:
999 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
1001 - target_section_addr
- offset
1002 - image_target
->vaddr_offset
);
1005 case R_IA64_SEGREL64LSB
:
1006 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
1007 + addend
+ sym_addr
- target_section_addr
);
1009 case R_IA64_DIR64LSB
:
1010 case R_IA64_FPTR64LSB
:
1011 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
)
1012 + addend
+ sym_addr
);
1013 grub_util_info ("relocating a direct entry to 0x%"
1014 GRUB_HOST_PRIxLONG_LONG
" at the offset 0x%"
1015 GRUB_HOST_PRIxLONG_LONG
,
1016 (unsigned long long)
1017 grub_target_to_host64 (*target
),
1018 (unsigned long long) offset
);
1021 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
1026 grub_util_error (_("relocation 0x%x is not implemented yet"),
1027 (unsigned int) ELF_R_TYPE (info
));
1034 switch (ELF_R_TYPE (info
))
1036 case R_AARCH64_ABS64
:
1038 *target
= grub_host_to_target64 (grub_target_to_host64 (*target
) + sym_addr
);
1041 case R_AARCH64_PREL32
:
1043 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
1044 *t32
= grub_host_to_target64 (grub_target_to_host32 (*t32
)
1046 - target_section_addr
- offset
1047 - image_target
->vaddr_offset
);
1048 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
1049 GRUB_HOST_PRIxLONG_LONG
,
1050 *t32
, (unsigned long long) offset
);
1053 case R_AARCH64_ADD_ABS_LO12_NC
:
1054 grub_arm64_set_abs_lo12 ((grub_uint32_t
*) target
,
1057 case R_AARCH64_LDST64_ABS_LO12_NC
:
1058 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t
*) target
,
1061 case R_AARCH64_JUMP26
:
1062 case R_AARCH64_CALL26
:
1065 sym_addr
-= target_section_addr
+ image_target
->vaddr_offset
;
1066 if (!grub_arm_64_check_xxxx26_offset (sym_addr
))
1067 grub_util_error ("%s", "CALL26 Relocation out of range");
1069 grub_arm64_set_xxxx26_offset((grub_uint32_t
*)target
,
1073 case R_AARCH64_ADR_GOT_PAGE
:
1076 grub_int64_t gpoffset
= (((char *) gpptr
- (char *) pe_target
+ image_target
->vaddr_offset
) & ~0xfffULL
)
1077 - ((offset
+ target_section_addr
+ image_target
->vaddr_offset
) & ~0xfffULL
);
1079 *gpptr
= grub_host_to_target64 (sym_addr
);
1080 unmatched_adr_got_page
++;
1081 if (!grub_arm64_check_hi21_signed (gpoffset
))
1082 grub_util_error ("HI21 out of range");
1083 grub_arm64_set_hi21((grub_uint32_t
*)target
,
1085 for (k
= 0, rel2
= (Elf_Rela
*) ((char *) r
+ r_size
);
1087 k
++, rel2
= (Elf_Rela
*) ((char *) rel2
+ r_size
))
1088 if (ELF_R_SYM (rel2
->r_info
)
1089 == ELF_R_SYM (r
->r_info
)
1090 && r
->r_addend
== rel2
->r_addend
1091 && ELF_R_TYPE (rel2
->r_info
) == R_AARCH64_LD64_GOT_LO12_NC
)
1093 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t
*) SUFFIX (get_target_address
) (e
, target_section
,
1094 grub_target_to_host (rel2
->r_offset
), image_target
),
1095 ((char *) gpptr
- (char *) pe_target
+ image_target
->vaddr_offset
));
1099 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1103 case R_AARCH64_LD64_GOT_LO12_NC
:
1104 if (unmatched_adr_got_page
== 0)
1105 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1106 unmatched_adr_got_page
--;
1108 case R_AARCH64_ADR_PREL_PG_HI21
:
1110 sym_addr
&= ~0xfffULL
;
1111 sym_addr
-= (offset
+ target_section_addr
+ image_target
->vaddr_offset
) & ~0xfffULL
;
1112 if (!grub_arm64_check_hi21_signed (sym_addr
))
1113 grub_util_error ("%s", "CALL26 Relocation out of range");
1115 grub_arm64_set_hi21((grub_uint32_t
*)target
,
1120 grub_util_error (_("relocation 0x%x is not implemented yet"),
1121 (unsigned int) ELF_R_TYPE (info
));
1127 #if defined(MKIMAGE_ELF32)
1131 sym_addr
-= image_target
->vaddr_offset
;
1132 switch (ELF_R_TYPE (info
))
1136 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1137 (int) sym_addr
, (int) sym_addr
);
1138 /* Data will be naturally aligned */
1139 if (image_target
->id
== IMAGE_EFI
)
1141 *target
= grub_host_to_target32 (grub_target_to_host32 (*target
) + sym_addr
);
1144 /* Happens when compiled with -march=armv4.
1145 Since currently we need at least armv5, keep bx as-is.
1149 case R_ARM_THM_CALL
:
1150 case R_ARM_THM_JUMP24
:
1151 case R_ARM_THM_JUMP19
:
1155 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1156 (unsigned long) ((char *) target
1159 sym
= (Elf_Sym
*) ((char *) e
1160 + grub_target_to_host (smd
->symtab
->sh_offset
)
1161 + ELF_R_SYM (info
) * grub_target_to_host (smd
->symtab
->sh_entsize
));
1162 if (ELF_ST_TYPE (sym
->st_info
) != STT_FUNC
)
1164 if (!(sym_addr
& 1))
1166 grub_uint32_t tr_addr
;
1167 grub_int32_t new_offset
;
1168 tr_addr
= (char *) tr
- (char *) pe_target
1169 - target_section_addr
;
1170 new_offset
= sym_addr
- tr_addr
- 12;
1172 if (!grub_arm_jump24_check_offset (new_offset
))
1173 return grub_util_error ("jump24 relocation out of range");
1175 tr
[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1176 tr
[1] = grub_host_to_target32 (((new_offset
>> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1178 sym_addr
= tr_addr
| 1;
1181 /* Thumb instructions can be 16-bit aligned */
1182 if (ELF_R_TYPE (info
) == R_ARM_THM_JUMP19
)
1183 err
= grub_arm_reloc_thm_jump19 ((grub_uint16_t
*) target
, sym_addr
);
1185 err
= grub_arm_reloc_thm_call ((grub_uint16_t
*) target
,
1188 grub_util_error ("%s", grub_errmsg
);
1196 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target
- (char *) e
), sym_addr
);
1199 grub_uint32_t tr_addr
;
1200 grub_int32_t new_offset
;
1201 tr_addr
= (char *) tr
- (char *) pe_target
1202 - target_section_addr
;
1203 new_offset
= sym_addr
- tr_addr
- 12;
1205 /* There is no immediate version of bx, only register one... */
1206 tr
[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1207 tr
[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1208 tr
[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1209 tr
[3] = grub_host_to_target32 (new_offset
| 1);
1214 err
= grub_arm_reloc_jump24 (target
,
1217 grub_util_error ("%s", grub_errmsg
);
1222 grub_util_error (_("relocation 0x%x is not implemented yet"),
1223 (unsigned int) ELF_R_TYPE (info
));
1228 #endif /* MKIMAGE_ELF32 */
1231 grub_uint64_t
*t64
= (grub_uint64_t
*) target
;
1232 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
1233 grub_uint16_t
*t16
= (grub_uint16_t
*) target
;
1234 grub_uint8_t
*t8
= (grub_uint8_t
*) target
;
1235 grub_int64_t off
= (long)sym_addr
- target_section_addr
- offset
1236 - image_target
->vaddr_offset
;
1239 * Instructions and instruction encoding are documented in the RISC-V
1240 * specification. This file is based on version 2.2:
1242 * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
1247 switch (ELF_R_TYPE (info
))
1250 *t8
= *t8
+ sym_addr
;
1253 *t16
= grub_host_to_target16 (grub_target_to_host16 (*t16
) + sym_addr
);
1257 *t32
= grub_host_to_target32 (grub_target_to_host32 (*t32
) + sym_addr
);
1261 *t64
= grub_host_to_target64 (grub_target_to_host64 (*t64
) + sym_addr
);
1265 *t8
= sym_addr
- *t8
;
1268 *t16
= grub_host_to_target16 (grub_target_to_host16 (*t16
) - sym_addr
);
1271 *t32
= grub_host_to_target32 (grub_target_to_host32 (*t32
) - sym_addr
);
1274 *t64
= grub_host_to_target64 (grub_target_to_host64 (*t64
) - sym_addr
);
1276 case R_RISCV_BRANCH
:
1278 grub_uint32_t imm12
= (off
& 0x1000) << (31 - 12);
1279 grub_uint32_t imm11
= (off
& 0x800) >> (11 - 7);
1280 grub_uint32_t imm10_5
= (off
& 0x7e0) << (30 - 10);
1281 grub_uint32_t imm4_1
= (off
& 0x1e) << (11 - 4);
1282 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0x1fff07f)
1283 | imm12
| imm11
| imm10_5
| imm4_1
);
1288 grub_uint32_t imm20
= (off
& 0x100000) << (31 - 20);
1289 grub_uint32_t imm19_12
= (off
& 0xff000);
1290 grub_uint32_t imm11
= (off
& 0x800) << (20 - 11);
1291 grub_uint32_t imm10_1
= (off
& 0x7fe) << (30 - 10);
1292 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0xfff)
1293 | imm20
| imm19_12
| imm11
| imm10_1
);
1298 grub_uint32_t hi20
, lo12
;
1300 if (off
!= (grub_int32_t
)off
)
1301 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr
, (long)target
);
1303 hi20
= (off
+ 0x800) & 0xfffff000;
1304 lo12
= (off
- hi20
) & 0xfff;
1305 t32
[0] = grub_host_to_target32 ((grub_target_to_host32 (t32
[0]) & 0xfff) | hi20
);
1306 t32
[1] = grub_host_to_target32 ((grub_target_to_host32 (t32
[1]) & 0xfffff) | (lo12
<< 20));
1309 case R_RISCV_RVC_BRANCH
:
1311 grub_uint16_t imm8
= (off
& 0x100) << (12 - 8);
1312 grub_uint16_t imm7_6
= (off
& 0xc0) >> (6 - 5);
1313 grub_uint16_t imm5
= (off
& 0x20) >> (5 - 2);
1314 grub_uint16_t imm4_3
= (off
& 0x18) << (12 - 5);
1315 grub_uint16_t imm2_1
= (off
& 0x6) << (12 - 10);
1316 *t16
= grub_host_to_target16 ((grub_target_to_host16 (*t16
) & 0xe383)
1317 | imm8
| imm7_6
| imm5
| imm4_3
| imm2_1
);
1320 case R_RISCV_RVC_JUMP
:
1322 grub_uint16_t imm11
= (off
& 0x800) << (12 - 11);
1323 grub_uint16_t imm10
= (off
& 0x400) >> (10 - 8);
1324 grub_uint16_t imm9_8
= (off
& 0x300) << (12 - 11);
1325 grub_uint16_t imm7
= (off
& 0x80) >> (7 - 6);
1326 grub_uint16_t imm6
= (off
& 0x40) << (12 - 11);
1327 grub_uint16_t imm5
= (off
& 0x20) >> (5 - 2);
1328 grub_uint16_t imm4
= (off
& 0x10) << (12 - 5);
1329 grub_uint16_t imm3_1
= (off
& 0xe) << (12 - 10);
1330 *t16
= grub_host_to_target16 ((grub_target_to_host16 (*t16
) & 0xe003)
1331 | imm11
| imm10
| imm9_8
| imm7
| imm6
1332 | imm5
| imm4
| imm3_1
);
1335 case R_RISCV_PCREL_HI20
:
1339 if (off
!= (grub_int32_t
)off
)
1340 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr
, (long)target
);
1342 hi20
= (off
+ 0x800) & 0xfffff000;
1343 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0xfff) | hi20
);
1346 case R_RISCV_PCREL_LO12_I
:
1347 case R_RISCV_PCREL_LO12_S
:
1351 /* Search backwards for matching HI20 reloc. */
1352 for (k
= j
, rel2
= (Elf_Rela
*) ((char *) r
- r_size
);
1354 k
--, rel2
= (Elf_Rela
*) ((char *) rel2
- r_size
))
1357 Elf_Addr rel2_offset
;
1358 Elf_Addr rel2_sym_addr
;
1359 Elf_Addr rel2_addend
;
1361 grub_int64_t rel2_off
;
1363 rel2_offset
= grub_target_to_host (rel2
->r_offset
);
1364 rel2_info
= grub_target_to_host (rel2
->r_info
);
1365 rel2_loc
= target_section_addr
+ rel2_offset
+ image_target
->vaddr_offset
;
1367 if (ELF_R_TYPE (rel2_info
) == R_RISCV_PCREL_HI20
1368 && rel2_loc
== sym_addr
)
1370 rel2_sym_addr
= SUFFIX (get_symbol_address
)
1371 (e
, smd
->symtab
, ELF_R_SYM (rel2_info
),
1373 rel2_addend
= (s
->sh_type
== grub_target_to_host32 (SHT_RELA
)) ?
1374 grub_target_to_host (rel2
->r_addend
) : 0;
1375 rel2_off
= rel2_sym_addr
+ rel2_addend
- rel2_loc
;
1376 off
= rel2_off
- ((rel2_off
+ 0x800) & 0xfffff000);
1378 if (ELF_R_TYPE (info
) == R_RISCV_PCREL_LO12_I
)
1379 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0xfffff) | (off
& 0xfff) << 20);
1382 grub_uint32_t imm11_5
= (off
& 0xfe0) << (31 - 11);
1383 grub_uint32_t imm4_0
= (off
& 0x1f) << (11 - 4);
1384 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0x1fff07f) | imm11_5
| imm4_0
);
1390 grub_util_error ("cannot find matching HI20 relocation");
1394 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0xfff) | (((grub_int32_t
) sym_addr
+ 0x800) & 0xfffff000));
1396 case R_RISCV_LO12_I
:
1398 grub_int32_t lo12
= (grub_int32_t
) sym_addr
- (((grub_int32_t
) sym_addr
+ 0x800) & 0xfffff000);
1399 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0xfffff) | ((lo12
& 0xfff) << 20));
1402 case R_RISCV_LO12_S
:
1404 grub_int32_t lo12
= (grub_int32_t
) sym_addr
- (((grub_int32_t
) sym_addr
+ 0x800) & 0xfffff000);
1405 grub_uint32_t imm11_5
= (lo12
& 0xfe0) << (31 - 11);
1406 grub_uint32_t imm4_0
= (lo12
& 0x1f) << (11 - 4);
1407 *t32
= grub_host_to_target32 ((grub_target_to_host32 (*t32
) & 0x1fff07f) | imm11_5
| imm4_0
);
1413 grub_util_error (_("relocation 0x%x is not implemented yet"),
1414 (unsigned int) ELF_R_TYPE (info
));
1420 grub_util_error ("unknown architecture type %d",
1421 image_target
->elf_target
);
1427 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1428 after having written to the file OUT. */
1430 add_fixup_entry (struct fixup_block_list
**cblock
, grub_uint16_t type
,
1431 Elf_Addr addr
, int flush
, Elf_Addr current_address
,
1432 const struct grub_install_image_target_desc
*image_target
)
1434 struct grub_pe32_fixup_block
*b
;
1436 b
= &((*cblock
)->b
);
1438 /* First, check if it is necessary to write out the current block. */
1439 if ((*cblock
)->state
)
1441 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
1447 /* Add as much padding as necessary to align the address
1448 with a section boundary. */
1449 Elf_Addr next_address
;
1450 unsigned padding_size
;
1453 next_address
= current_address
+ b
->block_size
;
1454 padding_size
= ((ALIGN_UP (next_address
, image_target
->section_align
)
1457 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1458 grub_util_info ("adding %d padding fixup entries", padding_size
);
1459 while (padding_size
--)
1461 b
->entries
[cur_index
++] = 0;
1465 else while (b
->block_size
& (8 - 1))
1467 /* If not aligned with a 32-bit boundary, add
1471 grub_util_info ("adding a padding fixup entry");
1472 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1473 b
->entries
[cur_index
] = 0;
1478 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1479 b
->block_size
, b
->page_rva
);
1480 size
= b
->block_size
;
1481 current_address
+= size
;
1482 b
->page_rva
= grub_host_to_target32 (b
->page_rva
);
1483 b
->block_size
= grub_host_to_target32 (b
->block_size
);
1484 (*cblock
)->next
= xmalloc (sizeof (**cblock
) + 2 * 0x1000);
1485 memset ((*cblock
)->next
, 0, sizeof (**cblock
) + 2 * 0x1000);
1486 *cblock
= (*cblock
)->next
;
1490 b
= &((*cblock
)->b
);
1494 grub_uint16_t entry
;
1497 /* If not allocated yet, allocate a block with enough entries. */
1498 if (! (*cblock
)->state
)
1500 (*cblock
)->state
= 1;
1502 /* The spec does not mention the requirement of a Page RVA.
1503 Here, align the address with a 4K boundary for safety. */
1504 b
->page_rva
= (addr
& ~(0x1000 - 1));
1505 b
->block_size
= sizeof (*b
);
1509 if (b
->block_size
>= sizeof (*b
) + 2 * 0x1000)
1510 grub_util_error ("too many fixup entries");
1512 /* Add a new entry. */
1513 cur_index
= ((b
->block_size
- sizeof (*b
)) >> 1);
1514 entry
= GRUB_PE32_FIXUP_ENTRY (type
, addr
- b
->page_rva
);
1515 b
->entries
[cur_index
] = grub_host_to_target16 (entry
);
1519 return current_address
;
1524 struct raw_reloc
*next
;
1525 grub_uint32_t offset
;
1526 enum raw_reloc_type
{
1527 RAW_RELOC_NONE
= -1,
1533 struct translate_context
1536 struct fixup_block_list
*lst
, *lst0
;
1537 Elf_Addr current_address
;
1540 struct raw_reloc
*raw_relocs
;
1544 translate_reloc_start (struct translate_context
*ctx
,
1545 const struct grub_install_image_target_desc
*image_target
)
1547 grub_memset (ctx
, 0, sizeof (*ctx
));
1548 if (image_target
->id
== IMAGE_EFI
)
1550 ctx
->lst
= ctx
->lst0
= xmalloc (sizeof (*ctx
->lst
) + 2 * 0x1000);
1551 memset (ctx
->lst
, 0, sizeof (*ctx
->lst
) + 2 * 0x1000);
1552 ctx
->current_address
= 0;
1557 translate_relocation_pe (struct translate_context
*ctx
,
1560 const struct grub_install_image_target_desc
*image_target
)
1562 /* Necessary to relocate only absolute addresses. */
1563 switch (image_target
->elf_target
)
1566 if (ELF_R_TYPE (info
) == R_386_32
)
1568 grub_util_info ("adding a relocation entry for 0x%"
1569 GRUB_HOST_PRIxLONG_LONG
,
1570 (unsigned long long) addr
);
1571 ctx
->current_address
1572 = add_fixup_entry (&ctx
->lst
,
1573 GRUB_PE32_REL_BASED_HIGHLOW
,
1574 addr
, 0, ctx
->current_address
,
1579 if ((ELF_R_TYPE (info
) == R_X86_64_32
) ||
1580 (ELF_R_TYPE (info
) == R_X86_64_32S
))
1582 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1584 else if (ELF_R_TYPE (info
) == R_X86_64_64
)
1586 grub_util_info ("adding a relocation entry for 0x%"
1587 GRUB_HOST_PRIxLONG_LONG
,
1588 (unsigned long long) addr
);
1589 ctx
->current_address
1590 = add_fixup_entry (&ctx
->lst
,
1591 GRUB_PE32_REL_BASED_DIR64
,
1593 0, ctx
->current_address
,
1598 switch (ELF_R_TYPE (info
))
1600 case R_IA64_PCREL64LSB
:
1602 case R_IA64_PCREL21B
:
1603 case R_IA64_LTOFF_FPTR22
:
1604 case R_IA64_LTOFF22X
:
1605 case R_IA64_LTOFF22
:
1606 case R_IA64_GPREL22
:
1607 case R_IA64_GPREL64I
:
1608 case R_IA64_SEGREL64LSB
:
1611 case R_IA64_FPTR64LSB
:
1612 case R_IA64_DIR64LSB
:
1615 grub_util_info ("adding a relocation entry for 0x%"
1616 GRUB_HOST_PRIxLONG_LONG
,
1617 (unsigned long long) addr
);
1618 ctx
->current_address
1619 = add_fixup_entry (&ctx
->lst
,
1620 GRUB_PE32_REL_BASED_DIR64
,
1622 0, ctx
->current_address
,
1628 grub_util_error (_("relocation 0x%x is not implemented yet"),
1629 (unsigned int) ELF_R_TYPE (info
));
1634 switch (ELF_R_TYPE (info
))
1636 case R_AARCH64_ABS64
:
1638 ctx
->current_address
1639 = add_fixup_entry (&ctx
->lst
,
1640 GRUB_PE32_REL_BASED_DIR64
,
1641 addr
, 0, ctx
->current_address
,
1645 /* Relative relocations do not require fixup entries. */
1646 case R_AARCH64_CALL26
:
1647 case R_AARCH64_JUMP26
:
1648 case R_AARCH64_PREL32
:
1650 /* Page-relative relocations do not require fixup entries. */
1651 case R_AARCH64_ADR_PREL_PG_HI21
:
1652 /* We page-align the whole kernel, so no need
1655 case R_AARCH64_ADD_ABS_LO12_NC
:
1656 case R_AARCH64_LDST64_ABS_LO12_NC
:
1659 /* GOT is relocated separately. */
1660 case R_AARCH64_ADR_GOT_PAGE
:
1661 case R_AARCH64_LD64_GOT_LO12_NC
:
1665 grub_util_error (_("relocation 0x%x is not implemented yet"),
1666 (unsigned int) ELF_R_TYPE (info
));
1671 #if defined(MKIMAGE_ELF32)
1673 switch (ELF_R_TYPE (info
))
1676 /* Relative relocations do not require fixup entries. */
1678 case R_ARM_THM_CALL
:
1679 case R_ARM_THM_JUMP19
:
1680 case R_ARM_THM_JUMP24
:
1683 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__
, (unsigned int) addr
, (unsigned int) ctx
->current_address
);
1686 /* Create fixup entry for PE/COFF loader */
1689 ctx
->current_address
1690 = add_fixup_entry (&ctx
->lst
,
1691 GRUB_PE32_REL_BASED_HIGHLOW
,
1692 addr
, 0, ctx
->current_address
,
1697 grub_util_error (_("relocation 0x%x is not implemented yet"),
1698 (unsigned int) ELF_R_TYPE (info
));
1702 #endif /* defined(MKIMAGE_ELF32) */
1704 switch (ELF_R_TYPE (info
))
1708 ctx
->current_address
1709 = add_fixup_entry (&ctx
->lst
,
1710 GRUB_PE32_REL_BASED_HIGHLOW
,
1711 addr
, 0, ctx
->current_address
,
1717 ctx
->current_address
1718 = add_fixup_entry (&ctx
->lst
,
1719 GRUB_PE32_REL_BASED_DIR64
,
1720 addr
, 0, ctx
->current_address
,
1724 /* Relative relocations do not require fixup entries. */
1725 case R_RISCV_BRANCH
:
1728 case R_RISCV_PCREL_HI20
:
1729 case R_RISCV_PCREL_LO12_I
:
1730 case R_RISCV_PCREL_LO12_S
:
1731 case R_RISCV_RVC_BRANCH
:
1732 case R_RISCV_RVC_JUMP
:
1735 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__
, (unsigned int) addr
, (unsigned int) ctx
->current_address
);
1739 ctx
->current_address
1740 = add_fixup_entry (&ctx
->lst
,
1741 GRUB_PE32_REL_BASED_RISCV_HI20
,
1742 addr
, 0, ctx
->current_address
,
1746 case R_RISCV_LO12_I
:
1748 ctx
->current_address
1749 = add_fixup_entry (&ctx
->lst
,
1750 GRUB_PE32_REL_BASED_RISCV_LOW12I
,
1751 addr
, 0, ctx
->current_address
,
1755 case R_RISCV_LO12_S
:
1757 ctx
->current_address
1758 = add_fixup_entry (&ctx
->lst
,
1759 GRUB_PE32_REL_BASED_RISCV_LOW12S
,
1760 addr
, 0, ctx
->current_address
,
1767 grub_util_error (_("relocation 0x%x is not implemented yet"),
1768 (unsigned int) ELF_R_TYPE (info
));
1773 grub_util_error ("unknown machine type 0x%x", image_target
->elf_target
);
1777 static enum raw_reloc_type
1778 classify_raw_reloc (Elf_Addr info
,
1779 const struct grub_install_image_target_desc
*image_target
)
1781 /* Necessary to relocate only absolute addresses. */
1782 switch (image_target
->elf_target
)
1785 switch (ELF_R_TYPE (info
))
1789 case R_ARM_THM_CALL
:
1790 case R_ARM_THM_JUMP19
:
1791 case R_ARM_THM_JUMP24
:
1793 return RAW_RELOC_NONE
;
1795 return RAW_RELOC_32
;
1797 grub_util_error (_("relocation 0x%x is not implemented yet"),
1798 (unsigned int) ELF_R_TYPE (info
));
1803 grub_util_error ("unknown machine type 0x%x", image_target
->elf_target
);
1808 translate_relocation_raw (struct translate_context
*ctx
,
1811 const struct grub_install_image_target_desc
*image_target
)
1813 enum raw_reloc_type
class = classify_raw_reloc (info
, image_target
);
1814 struct raw_reloc
*rel
;
1815 if (class == RAW_RELOC_NONE
)
1817 rel
= xmalloc (sizeof (*rel
));
1818 rel
->next
= ctx
->raw_relocs
;
1821 ctx
->raw_relocs
= rel
;
1825 translate_relocation (struct translate_context
*ctx
,
1828 const struct grub_install_image_target_desc
*image_target
)
1830 if (image_target
->id
== IMAGE_EFI
)
1831 translate_relocation_pe (ctx
, addr
, info
, image_target
);
1833 translate_relocation_raw (ctx
, addr
, info
, image_target
);
1837 finish_reloc_translation_pe (struct translate_context
*ctx
, struct grub_mkimage_layout
*layout
,
1838 const struct grub_install_image_target_desc
*image_target
)
1840 ctx
->current_address
= add_fixup_entry (&ctx
->lst
, 0, 0, 1, ctx
->current_address
, image_target
);
1844 layout
->reloc_section
= ptr
= xmalloc (ctx
->current_address
);
1845 for (ctx
->lst
= ctx
->lst0
; ctx
->lst
; ctx
->lst
= ctx
->lst
->next
)
1846 if (ctx
->lst
->state
)
1848 memcpy (ptr
, &ctx
->lst
->b
, grub_target_to_host32 (ctx
->lst
->b
.block_size
));
1849 ptr
+= grub_target_to_host32 (ctx
->lst
->b
.block_size
);
1851 assert ((ctx
->current_address
+ (grub_uint8_t
*) layout
->reloc_section
) == ptr
);
1854 for (ctx
->lst
= ctx
->lst0
; ctx
->lst
; )
1856 struct fixup_block_list
*next
;
1857 next
= ctx
->lst
->next
;
1862 layout
->reloc_size
= ctx
->current_address
;
1863 if (image_target
->elf_target
== EM_ARM
&& layout
->reloc_size
> GRUB_KERNEL_ARM_STACK_SIZE
)
1864 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
1865 "This breaks assembly assumptions. Please increase stack size",
1866 (int) layout
->reloc_size
,
1867 (int) GRUB_KERNEL_ARM_STACK_SIZE
);
1872 <type 0 relocations>
1874 <type 1 relocations>
1877 <type n relocations>
1879 each relocation starts with 32-bit offset. Rest depends on relocation.
1880 mkimage stops when it sees first unknown type or end marker.
1881 This allows images to be created with mismatched mkimage and
1882 kernel as long as no relocations are present in kernel that mkimage
1883 isn't aware of (in which case mkimage aborts).
1884 This also allows simple assembly to do the relocs.
1887 #define RAW_SEPARATOR 0xfffffffe
1888 #define RAW_END_MARKER 0xffffffff
1891 finish_reloc_translation_raw (struct translate_context
*ctx
, struct grub_mkimage_layout
*layout
,
1892 const struct grub_install_image_target_desc
*image_target
)
1894 size_t count
= 0, sz
;
1895 enum raw_reloc_type highest
= RAW_RELOC_NONE
;
1896 enum raw_reloc_type curtype
;
1897 struct raw_reloc
*cur
;
1899 if (!ctx
->raw_relocs
)
1901 layout
->reloc_section
= p
= xmalloc (sizeof (grub_uint32_t
));
1902 p
[0] = RAW_END_MARKER
;
1903 layout
->reloc_size
= sizeof (grub_uint32_t
);
1906 for (cur
= ctx
->raw_relocs
; cur
; cur
= cur
->next
)
1909 if (cur
->type
> highest
)
1910 highest
= cur
->type
;
1912 /* highest separators, count relocations and one end marker. */
1913 sz
= (highest
+ count
+ 1) * sizeof (grub_uint32_t
);
1914 layout
->reloc_section
= p
= xmalloc (sz
);
1915 for (curtype
= 0; curtype
<= highest
; curtype
++)
1917 /* Support for special cases would go here. */
1918 for (cur
= ctx
->raw_relocs
; cur
; cur
= cur
->next
)
1919 if (cur
->type
== curtype
)
1923 *p
++ = RAW_SEPARATOR
;
1925 *--p
= RAW_END_MARKER
;
1926 layout
->reloc_size
= sz
;
1930 finish_reloc_translation (struct translate_context
*ctx
, struct grub_mkimage_layout
*layout
,
1931 const struct grub_install_image_target_desc
*image_target
)
1933 if (image_target
->id
== IMAGE_EFI
)
1934 finish_reloc_translation_pe (ctx
, layout
, image_target
);
1936 finish_reloc_translation_raw (ctx
, layout
, image_target
);
1941 create_u64_fixups (struct translate_context
*ctx
,
1942 Elf_Addr jumpers
, grub_size_t njumpers
,
1943 const struct grub_install_image_target_desc
*image_target
)
1946 assert (image_target
->id
== IMAGE_EFI
);
1947 for (i
= 0; i
< njumpers
; i
++)
1948 ctx
->current_address
= add_fixup_entry (&ctx
->lst
,
1949 GRUB_PE32_REL_BASED_DIR64
,
1951 0, ctx
->current_address
,
1955 /* Make a .reloc section. */
1957 make_reloc_section (Elf_Ehdr
*e
, struct grub_mkimage_layout
*layout
,
1958 struct section_metadata
*smd
,
1959 const struct grub_install_image_target_desc
*image_target
)
1963 struct translate_context ctx
;
1965 translate_reloc_start (&ctx
, image_target
);
1967 for (i
= 0, s
= smd
->sections
; i
< smd
->num_sections
;
1968 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
1969 if ((grub_target_to_host32 (s
->sh_type
) == SHT_REL
) ||
1970 (grub_target_to_host32 (s
->sh_type
) == SHT_RELA
))
1973 Elf_Word rtab_size
, r_size
, num_rs
;
1974 Elf_Off rtab_offset
;
1975 Elf_Addr section_address
;
1978 if (!SUFFIX (is_kept_reloc_section
) (s
, image_target
, smd
))
1980 grub_util_info ("not translating the skipped relocation section %s",
1981 smd
->strtab
+ grub_le_to_cpu32 (s
->sh_name
));
1985 grub_util_info ("translating the relocation section %s",
1986 smd
->strtab
+ grub_le_to_cpu32 (s
->sh_name
));
1988 rtab_size
= grub_target_to_host (s
->sh_size
);
1989 r_size
= grub_target_to_host (s
->sh_entsize
);
1990 rtab_offset
= grub_target_to_host (s
->sh_offset
);
1991 num_rs
= rtab_size
/ r_size
;
1993 section_address
= smd
->vaddrs
[grub_le_to_cpu32 (s
->sh_info
)];
1995 for (j
= 0, r
= (Elf_Rel
*) ((char *) e
+ rtab_offset
);
1997 j
++, r
= (Elf_Rel
*) ((char *) r
+ r_size
))
2003 offset
= grub_target_to_host (r
->r_offset
);
2004 info
= grub_target_to_host (r
->r_info
);
2006 addr
= section_address
+ offset
;
2008 translate_relocation (&ctx
, addr
, info
, image_target
);
2012 if (image_target
->elf_target
== EM_IA_64
)
2013 create_u64_fixups (&ctx
,
2015 + image_target
->vaddr_offset
,
2016 2 * layout
->ia64jmpnum
,
2018 if (image_target
->elf_target
== EM_IA_64
|| image_target
->elf_target
== EM_AARCH64
)
2019 create_u64_fixups (&ctx
,
2021 + image_target
->vaddr_offset
,
2022 (layout
->got_size
/ 8),
2025 finish_reloc_translation (&ctx
, layout
, image_target
);
2028 /* Determine if this section is a text section. Return false if this
2029 section is not allocated. */
2031 SUFFIX (is_text_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
2033 if (!is_relocatable (image_target
)
2034 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
2036 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
2037 == (SHF_EXECINSTR
| SHF_ALLOC
));
2040 /* Determine if this section is a data section. */
2042 SUFFIX (is_data_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
2044 if (!is_relocatable (image_target
)
2045 && grub_target_to_host32 (s
->sh_type
) != SHT_PROGBITS
)
2047 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
2048 == SHF_ALLOC
) && !(grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
);
2052 SUFFIX (is_bss_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
2054 if (!is_relocatable (image_target
))
2056 return ((grub_target_to_host (s
->sh_flags
) & (SHF_EXECINSTR
| SHF_ALLOC
))
2057 == SHF_ALLOC
) && (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
);
2060 /* Determine if a section is going to be in the final output */
2062 SUFFIX (is_kept_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
)
2064 /* We keep .text and .data */
2065 if (SUFFIX (is_text_section
) (s
, image_target
)
2066 || SUFFIX (is_data_section
) (s
, image_target
))
2070 * And we keep .bss if we're producing PE binaries or the target doesn't
2071 * have a relocating loader. Platforms other than EFI and U-boot shouldn't
2072 * have .bss in their binaries as we build with -Wl,-Ttext.
2074 if (SUFFIX (is_bss_section
) (s
, image_target
)
2075 && (image_target
->id
== IMAGE_EFI
|| !is_relocatable (image_target
)))
2078 /* Otherwise this is not a section we're keeping in the final output. */
2083 SUFFIX (is_kept_reloc_section
) (Elf_Shdr
*s
, const struct grub_install_image_target_desc
*image_target
,
2084 struct section_metadata
*smd
)
2088 const char *name
= smd
->strtab
+ grub_host_to_target32 (s
->sh_name
);
2090 if (!strncmp (name
, ".rela.", 6))
2092 else if (!strncmp (name
, ".rel.", 5))
2097 for (i
= 0, s
= smd
->sections
; i
< smd
->num_sections
;
2098 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
2100 const char *sname
= smd
->strtab
+ grub_host_to_target32 (s
->sh_name
);
2101 if (strcmp (sname
, name
))
2104 return SUFFIX (is_kept_section
) (s
, image_target
);
2110 /* Return if the ELF header is valid. */
2112 SUFFIX (check_elf_header
) (Elf_Ehdr
*e
, size_t size
, const struct grub_install_image_target_desc
*image_target
)
2114 if (size
< sizeof (*e
)
2115 || e
->e_ident
[EI_MAG0
] != ELFMAG0
2116 || e
->e_ident
[EI_MAG1
] != ELFMAG1
2117 || e
->e_ident
[EI_MAG2
] != ELFMAG2
2118 || e
->e_ident
[EI_MAG3
] != ELFMAG3
2119 || e
->e_ident
[EI_VERSION
] != EV_CURRENT
2120 || e
->e_ident
[EI_CLASS
] != ELFCLASSXX
2121 || e
->e_version
!= grub_host_to_target32 (EV_CURRENT
))
2128 SUFFIX (put_section
) (Elf_Shdr
*s
, int i
,
2129 Elf_Addr current_address
,
2130 struct section_metadata
*smd
,
2131 const struct grub_install_image_target_desc
*image_target
)
2133 Elf_Word align
= grub_host_to_target_addr (s
->sh_addralign
);
2134 const char *name
= smd
->strtab
+ grub_host_to_target32 (s
->sh_name
);
2137 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
2139 - image_target
->vaddr_offset
;
2141 grub_util_info ("locating the section %s at 0x%"
2142 GRUB_HOST_PRIxLONG_LONG
,
2143 name
, (unsigned long long) current_address
);
2144 if (!is_relocatable (image_target
))
2145 current_address
= grub_host_to_target_addr (s
->sh_addr
)
2146 - image_target
->link_addr
;
2147 smd
->addrs
[i
] = current_address
;
2148 current_address
+= grub_host_to_target_addr (s
->sh_size
);
2149 return current_address
;
2153 * Locate section addresses by merging code sections and data sections
2154 * into .text and .data, respectively.
2157 SUFFIX (locate_sections
) (Elf_Ehdr
*e
, const char *kernel_path
,
2158 struct section_metadata
*smd
,
2159 struct grub_mkimage_layout
*layout
,
2160 const struct grub_install_image_target_desc
*image_target
)
2166 /* Page-aligning simplifies relocation handling. */
2167 if (image_target
->elf_target
== EM_AARCH64
)
2168 layout
->align
= 4096;
2170 layout
->kernel_size
= 0;
2172 for (i
= 0, s
= smd
->sections
;
2173 i
< smd
->num_sections
;
2174 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
2175 if ((grub_target_to_host (s
->sh_flags
) & SHF_ALLOC
)
2176 && grub_host_to_target32 (s
->sh_addralign
) > layout
->align
)
2177 layout
->align
= grub_host_to_target32 (s
->sh_addralign
);
2180 for (i
= 0, s
= smd
->sections
;
2181 i
< smd
->num_sections
;
2182 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
2183 if (SUFFIX (is_text_section
) (s
, image_target
))
2185 layout
->kernel_size
= SUFFIX (put_section
) (s
, i
, layout
->kernel_size
,
2187 if (!is_relocatable (image_target
) &&
2188 grub_host_to_target_addr (s
->sh_addr
) != image_target
->link_addr
)
2191 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
2192 " instead of 0x%llx: ld.gold bug?"),
2194 (unsigned long long) grub_host_to_target_addr (s
->sh_addr
),
2195 (unsigned long long) image_target
->link_addr
);
2196 grub_util_error ("%s", msg
);
2200 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
+ image_target
->vaddr_offset
,
2201 image_target
->section_align
)
2202 - image_target
->vaddr_offset
;
2203 layout
->exec_size
= layout
->kernel_size
;
2206 for (i
= 0, s
= smd
->sections
;
2207 i
< smd
->num_sections
;
2208 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
2209 if (SUFFIX (is_data_section
) (s
, image_target
))
2210 layout
->kernel_size
= SUFFIX (put_section
) (s
, i
, layout
->kernel_size
, smd
,
2213 #ifdef MKIMAGE_ELF32
2214 if (image_target
->elf_target
== EM_ARM
)
2217 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
+ image_target
->vaddr_offset
,
2218 image_target
->section_align
) - image_target
->vaddr_offset
;
2220 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
, 16);
2222 tramp
= arm_get_trampoline_size (e
, smd
->sections
, smd
->section_entsize
,
2223 smd
->num_sections
, image_target
);
2225 layout
->tramp_off
= layout
->kernel_size
;
2226 layout
->kernel_size
+= ALIGN_UP (tramp
, 16);
2230 layout
->bss_start
= layout
->kernel_size
;
2231 layout
->end
= layout
->kernel_size
;
2234 for (i
= 0, s
= smd
->sections
;
2235 i
< smd
->num_sections
;
2236 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
->section_entsize
))
2238 if (SUFFIX (is_bss_section
) (s
, image_target
))
2239 layout
->end
= SUFFIX (put_section
) (s
, i
, layout
->end
, smd
, image_target
);
2242 * This must to be in the last time this function passes through the loop.
2244 smd
->vaddrs
[i
] = smd
->addrs
[i
] + image_target
->vaddr_offset
;
2247 layout
->end
= ALIGN_UP (layout
->end
+ image_target
->vaddr_offset
,
2248 image_target
->section_align
) - image_target
->vaddr_offset
;
2249 /* Explicitly initialize BSS
2250 when producing PE32 to avoid a bug in EFI implementations.
2251 Platforms other than EFI and U-boot shouldn't have .bss in
2252 their binaries as we build with -Wl,-Ttext.
2254 if (image_target
->id
== IMAGE_EFI
|| !is_relocatable (image_target
))
2255 layout
->kernel_size
= layout
->end
;
2259 SUFFIX (grub_mkimage_load_image
) (const char *kernel_path
,
2260 size_t total_module_size
,
2261 struct grub_mkimage_layout
*layout
,
2262 const struct grub_install_image_target_desc
*image_target
)
2264 char *kernel_img
, *out_img
;
2265 struct section_metadata smd
= { 0, 0, 0, 0, 0, 0, 0 };
2269 Elf_Off section_offset
;
2270 grub_size_t kernel_size
;
2272 grub_memset (layout
, 0, sizeof (*layout
));
2274 layout
->start_address
= 0;
2276 kernel_size
= grub_util_get_image_size (kernel_path
);
2277 kernel_img
= xmalloc (kernel_size
);
2278 grub_util_load_image (kernel_path
, kernel_img
);
2280 e
= (Elf_Ehdr
*) kernel_img
;
2281 if (! SUFFIX (check_elf_header
) (e
, kernel_size
, image_target
))
2282 grub_util_error ("invalid ELF header");
2284 section_offset
= grub_target_to_host (e
->e_shoff
);
2285 smd
.section_entsize
= grub_target_to_host16 (e
->e_shentsize
);
2286 smd
.num_sections
= grub_target_to_host16 (e
->e_shnum
);
2288 if (kernel_size
< section_offset
2289 + (grub_uint32_t
) smd
.section_entsize
* smd
.num_sections
)
2290 grub_util_error (_("premature end of file %s"), kernel_path
);
2292 smd
.sections
= (Elf_Shdr
*) (kernel_img
+ section_offset
);
2294 /* Relocate sections then symbols in the virtual address space. */
2295 s
= (Elf_Shdr
*) ((char *) smd
.sections
2296 + grub_host_to_target16 (e
->e_shstrndx
) * smd
.section_entsize
);
2297 smd
.strtab
= (char *) e
+ grub_host_to_target_addr (s
->sh_offset
);
2299 smd
.addrs
= xmalloc (sizeof (*smd
.addrs
) * smd
.num_sections
);
2300 memset (smd
.addrs
, 0, sizeof (*smd
.addrs
) * smd
.num_sections
);
2301 smd
.vaddrs
= xmalloc (sizeof (*smd
.vaddrs
) * smd
.num_sections
);
2302 memset (smd
.vaddrs
, 0, sizeof (*smd
.vaddrs
) * smd
.num_sections
);
2304 SUFFIX (locate_sections
) (e
, kernel_path
, &smd
, layout
, image_target
);
2306 if (!is_relocatable (image_target
))
2308 Elf_Addr current_address
= layout
->kernel_size
;
2310 for (i
= 0, s
= smd
.sections
;
2311 i
< smd
.num_sections
;
2312 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
.section_entsize
))
2313 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
2315 Elf_Word sec_align
= grub_host_to_target_addr (s
->sh_addralign
);
2316 const char *name
= smd
.strtab
+ grub_host_to_target32 (s
->sh_name
);
2319 current_address
= ALIGN_UP (current_address
2320 + image_target
->vaddr_offset
,
2322 - image_target
->vaddr_offset
;
2324 grub_util_info ("locating the section %s at 0x%"
2325 GRUB_HOST_PRIxLONG_LONG
,
2326 name
, (unsigned long long) current_address
);
2327 if (!is_relocatable (image_target
))
2328 current_address
= grub_host_to_target_addr (s
->sh_addr
)
2329 - image_target
->link_addr
;
2331 smd
.vaddrs
[i
] = current_address
2332 + image_target
->vaddr_offset
;
2333 current_address
+= grub_host_to_target_addr (s
->sh_size
);
2335 current_address
= ALIGN_UP (current_address
+ image_target
->vaddr_offset
,
2336 image_target
->section_align
)
2337 - image_target
->vaddr_offset
;
2338 layout
->bss_size
= current_address
- layout
->kernel_size
;
2341 layout
->bss_size
= 0;
2343 if (image_target
->id
== IMAGE_SPARC64_AOUT
2344 || image_target
->id
== IMAGE_SPARC64_RAW
2345 || image_target
->id
== IMAGE_UBOOT
2346 || image_target
->id
== IMAGE_COREBOOT
2347 || image_target
->id
== IMAGE_SPARC64_CDCORE
)
2348 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
, image_target
->mod_align
);
2350 if (is_relocatable (image_target
))
2353 for (i
= 0, s
= smd
.sections
;
2354 i
< smd
.num_sections
;
2355 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
.section_entsize
))
2356 if (s
->sh_type
== grub_host_to_target32 (SHT_SYMTAB
))
2362 grub_util_error ("%s", _("no symbol table"));
2363 #ifdef MKIMAGE_ELF64
2364 if (image_target
->elf_target
== EM_IA_64
)
2368 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
, 16);
2370 grub_ia64_dl_get_tramp_got_size (e
, &tramp
, &layout
->got_size
);
2372 layout
->tramp_off
= layout
->kernel_size
;
2373 layout
->kernel_size
+= ALIGN_UP (tramp
, 16);
2375 layout
->ia64jmp_off
= layout
->kernel_size
;
2376 layout
->ia64jmpnum
= SUFFIX (count_funcs
) (e
, smd
.symtab
,
2378 layout
->kernel_size
+= 16 * layout
->ia64jmpnum
;
2380 layout
->got_off
= layout
->kernel_size
;
2381 layout
->kernel_size
+= ALIGN_UP (layout
->got_size
, 16);
2383 if (image_target
->elf_target
== EM_AARCH64
)
2387 layout
->kernel_size
= ALIGN_UP (layout
->kernel_size
, 16);
2389 grub_arm64_dl_get_tramp_got_size (e
, &tramp
, &layout
->got_size
);
2391 layout
->got_off
= layout
->kernel_size
;
2392 layout
->kernel_size
+= ALIGN_UP (layout
->got_size
, 16);
2398 layout
->reloc_size
= 0;
2399 layout
->reloc_section
= NULL
;
2402 out_img
= xmalloc (layout
->kernel_size
+ total_module_size
);
2403 memset (out_img
, 0, layout
->kernel_size
+ total_module_size
);
2405 if (is_relocatable (image_target
))
2407 layout
->start_address
= SUFFIX (relocate_symbols
) (e
, &smd
,
2408 (char *) out_img
+ layout
->ia64jmp_off
,
2409 layout
->ia64jmp_off
+ image_target
->vaddr_offset
,
2410 layout
->bss_start
, layout
->end
, image_target
);
2412 if (layout
->start_address
== (Elf_Addr
) -1)
2413 grub_util_error ("start symbol is not defined");
2415 /* Resolve addrs in the virtual address space. */
2416 SUFFIX (relocate_addrs
) (e
, &smd
, out_img
, layout
->tramp_off
,
2417 layout
->got_off
, image_target
);
2419 make_reloc_section (e
, layout
, &smd
, image_target
);
2420 if (image_target
->id
!= IMAGE_EFI
)
2422 out_img
= xrealloc (out_img
, layout
->kernel_size
+ total_module_size
2423 + ALIGN_UP (layout
->reloc_size
, image_target
->mod_align
));
2424 memcpy (out_img
+ layout
->kernel_size
, layout
->reloc_section
, layout
->reloc_size
);
2425 memset (out_img
+ layout
->kernel_size
+ layout
->reloc_size
, 0,
2426 total_module_size
+ ALIGN_UP (layout
->reloc_size
, image_target
->mod_align
) - layout
->reloc_size
);
2427 layout
->kernel_size
+= ALIGN_UP (layout
->reloc_size
, image_target
->mod_align
);
2431 for (i
= 0, s
= smd
.sections
;
2432 i
< smd
.num_sections
;
2433 i
++, s
= (Elf_Shdr
*) ((char *) s
+ smd
.section_entsize
))
2434 if (SUFFIX (is_kept_section
) (s
, image_target
))
2436 if (grub_target_to_host32 (s
->sh_type
) == SHT_NOBITS
)
2437 memset (out_img
+ smd
.addrs
[i
], 0,
2438 grub_host_to_target_addr (s
->sh_size
));
2440 memcpy (out_img
+ smd
.addrs
[i
],
2441 kernel_img
+ grub_host_to_target_addr (s
->sh_offset
),
2442 grub_host_to_target_addr (s
->sh_size
));