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 #pragma GCC diagnostic ignored "-Wcast-align"
53 #define GRUB_MKIMAGEXX
54 #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
55 #if __SIZEOF_POINTER__ == 8
56 #include "grub-mkimage64.c"
58 #include "grub-mkimage32.c"
62 /* These structures are defined according to the CHRP binding to IEEE1275,
63 "Client Program Format" section. */
65 struct grub_ieee1275_note_desc
67 grub_uint32_t real_mode;
68 grub_uint32_t real_base;
69 grub_uint32_t real_size;
70 grub_uint32_t virt_base;
71 grub_uint32_t virt_size;
72 grub_uint32_t load_base;
75 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
76 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
78 struct grub_ieee1275_note
81 char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
82 struct grub_ieee1275_note_desc descriptor;
85 #define GRUB_XEN_NOTE_NAME "Xen"
87 struct fixup_block_list
89 struct fixup_block_list *next;
91 struct grub_pe32_fixup_block b;
94 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
97 is_relocatable (const struct grub_install_image_target_desc *image_target)
99 return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
100 || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
106 * R_ARM_THM_CALL/THM_JUMP24
108 * Relocate Thumb (T32) instruction set relative branches:
112 grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
116 offset = grub_arm_thm_call_get_offset (target);
118 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
122 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
123 target, sym_addr, offset);
125 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
126 is bigger than 2M (currently under 150K) then we probably have a problem
128 if (offset < -0x200000 || offset >= 0x200000)
129 return grub_error (GRUB_ERR_BAD_MODULE,
130 "THM_CALL Relocation out of range.");
132 grub_dprintf ("dl", " relative destination = %p",
133 (char *) target + offset);
135 return grub_arm_thm_call_set_offset (target, offset);
141 * Relocate conditional Thumb (T32) B<c>.W
144 grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
149 return grub_error (GRUB_ERR_BAD_MODULE,
150 "Relocation targeting wrong execution state");
152 offset = grub_arm_thm_jump19_get_offset (target);
154 /* Adjust and re-truncate offset */
157 if (!grub_arm_thm_jump19_check_offset (offset))
158 return grub_error (GRUB_ERR_BAD_MODULE,
159 "THM_JUMP19 Relocation out of range.");
161 grub_arm_thm_jump19_set_offset (target, offset);
163 return GRUB_ERR_NONE;
169 * Relocate ARM (A32) B
172 grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
177 return grub_error (GRUB_ERR_BAD_MODULE,
178 "Relocation targeting wrong execution state");
180 offset = grub_arm_jump24_get_offset (target);
183 if (!grub_arm_jump24_check_offset (offset))
184 return grub_error (GRUB_ERR_BAD_MODULE,
185 "JUMP24 Relocation out of range.");
188 grub_arm_jump24_set_offset (target, offset);
190 return GRUB_ERR_NONE;
196 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
197 int note, char **core_img, size_t *core_size,
198 Elf_Addr target_addr,
199 struct grub_mkimage_layout *layout)
206 int header_size, footer_size = 0;
209 int string_size = sizeof (".text") + sizeof ("mods") + 1;
211 if (image_target->id != IMAGE_LOONGSON_ELF)
217 footer_size += sizeof (struct grub_ieee1275_note);
219 if (image_target->id == IMAGE_XEN)
223 string_size += sizeof (".xen");
224 footer_size += XEN_NOTE_SIZE;
226 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
227 + shnum * sizeof (*shdr) + string_size, layout->align);
229 program_size = ALIGN_ADDR (*core_size);
231 elf_img = xmalloc (program_size + header_size + footer_size);
232 memset (elf_img, 0, program_size + header_size + footer_size);
233 memcpy (elf_img + header_size, *core_img, *core_size);
234 ehdr = (void *) elf_img;
235 phdr = (void *) (elf_img + sizeof (*ehdr));
236 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
237 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
238 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
239 if (!image_target->bigendian)
240 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
242 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
243 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
244 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
245 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
246 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
247 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
249 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
250 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
251 ehdr->e_phnum = grub_host_to_target16 (phnum);
253 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
254 - (grub_uint8_t *) ehdr);
255 if (image_target->id == IMAGE_LOONGSON_ELF)
256 ehdr->e_shentsize = grub_host_to_target16 (0);
258 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
259 ehdr->e_shnum = grub_host_to_target16 (shnum);
260 ehdr->e_shstrndx = grub_host_to_target16 (1);
262 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
264 phdr->p_type = grub_host_to_target32 (PT_LOAD);
265 phdr->p_offset = grub_host_to_target32 (header_size);
266 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
268 ehdr->e_entry = grub_host_to_target32 (target_addr);
269 phdr->p_vaddr = grub_host_to_target32 (target_addr);
270 phdr->p_paddr = grub_host_to_target32 (target_addr);
271 phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
272 layout->align : image_target->link_align);
273 if (image_target->id == IMAGE_LOONGSON_ELF)
274 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
275 | EF_MIPS_PIC | EF_MIPS_CPIC);
278 if (image_target->id == IMAGE_LOONGSON_ELF)
280 phdr->p_filesz = grub_host_to_target32 (*core_size);
281 phdr->p_memsz = grub_host_to_target32 (*core_size);
285 grub_uint32_t target_addr_mods;
286 phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
287 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
288 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
290 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
293 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
294 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
295 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
296 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
297 phdr->p_align = grub_host_to_target32 (image_target->link_align);
300 phdr->p_type = grub_host_to_target32 (PT_LOAD);
301 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
302 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
303 phdr->p_filesz = phdr->p_memsz
304 = grub_host_to_target32 (*core_size - layout->kernel_size);
306 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
307 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
308 else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
309 target_addr_mods = ALIGN_UP (target_addr + layout->end
310 + image_target->mod_gap,
311 image_target->mod_align);
313 target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
314 + image_target->mod_gap,
315 image_target->mod_align);
316 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
317 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
318 phdr->p_align = grub_host_to_target32 (image_target->link_align);
321 if (image_target->id == IMAGE_XEN)
323 char *note_start = (elf_img + program_size + header_size);
325 char *ptr = (char *) note_start;
327 grub_util_info ("adding XEN NOTE segment");
330 note_ptr = (Elf_Nhdr *) ptr;
331 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
332 note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
333 note_ptr->n_type = grub_host_to_target32 (6);
334 ptr += sizeof (Elf_Nhdr);
335 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
336 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
337 memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
338 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
341 note_ptr = (Elf_Nhdr *) ptr;
342 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
343 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
344 note_ptr->n_type = grub_host_to_target32 (8);
345 ptr += sizeof (Elf_Nhdr);
346 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
347 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
348 memcpy (ptr, "generic", sizeof ("generic"));
349 ptr += ALIGN_UP (sizeof ("generic"), 4);
352 note_ptr = (Elf_Nhdr *) ptr;
353 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
354 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
355 note_ptr->n_type = grub_host_to_target32 (5);
356 ptr += sizeof (Elf_Nhdr);
357 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
358 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
359 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
360 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
363 note_ptr = (Elf_Nhdr *) ptr;
364 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
365 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
366 note_ptr->n_type = grub_host_to_target32 (1);
367 ptr += sizeof (Elf_Nhdr);
368 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
369 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
370 memset (ptr, 0, image_target->voidp_sizeof);
371 ptr += image_target->voidp_sizeof;
374 note_ptr = (Elf_Nhdr *) ptr;
375 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
376 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
377 note_ptr->n_type = grub_host_to_target32 (3);
378 ptr += sizeof (Elf_Nhdr);
379 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
380 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
381 memset (ptr, 0, image_target->voidp_sizeof);
382 ptr += image_target->voidp_sizeof;
385 if (image_target->elf_target == EM_386)
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 (sizeof ("yes,bimodal"));
390 note_ptr->n_type = grub_host_to_target32 (9);
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 memcpy (ptr, "yes", sizeof ("yes"));
395 ptr += ALIGN_UP (sizeof ("yes"), 4);
398 assert (XEN_NOTE_SIZE == (ptr - note_start));
401 phdr->p_type = grub_host_to_target32 (PT_NOTE);
402 phdr->p_flags = grub_host_to_target32 (PF_R);
403 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
406 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
408 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
413 int note_size = sizeof (struct grub_ieee1275_note);
414 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
415 (elf_img + program_size + header_size);
417 grub_util_info ("adding CHRP NOTE segment");
419 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
420 note_ptr->header.n_descsz = grub_host_to_target32 (note_size);
421 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
422 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
423 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
424 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
425 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
426 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
427 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
428 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
431 phdr->p_type = grub_host_to_target32 (PT_NOTE);
432 phdr->p_flags = grub_host_to_target32 (PF_R);
433 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
436 phdr->p_filesz = grub_host_to_target32 (note_size);
438 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
442 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
443 + shnum * sizeof (*shdr));
444 char *ptr = str_start + 1;
448 shdr->sh_name = grub_host_to_target32 (0);
449 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
450 shdr->sh_addr = grub_host_to_target_addr (0);
451 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
452 shdr->sh_size = grub_host_to_target32 (string_size);
453 shdr->sh_link = grub_host_to_target32 (0);
454 shdr->sh_info = grub_host_to_target32 (0);
455 shdr->sh_addralign = grub_host_to_target32 (layout->align);
456 shdr->sh_entsize = grub_host_to_target32 (0);
459 memcpy (ptr, ".text", sizeof (".text"));
461 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
462 ptr += sizeof (".text");
463 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
464 shdr->sh_addr = grub_host_to_target_addr (target_addr);
465 shdr->sh_offset = grub_host_to_target_addr (header_size);
466 shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
467 shdr->sh_link = grub_host_to_target32 (0);
468 shdr->sh_info = grub_host_to_target32 (0);
469 shdr->sh_addralign = grub_host_to_target32 (layout->align);
470 shdr->sh_entsize = grub_host_to_target32 (0);
473 memcpy (ptr, "mods", sizeof ("mods"));
474 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
475 ptr += sizeof ("mods");
476 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
477 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
478 shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
479 shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
480 shdr->sh_link = grub_host_to_target32 (0);
481 shdr->sh_info = grub_host_to_target32 (0);
482 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
483 shdr->sh_entsize = grub_host_to_target32 (0);
486 if (image_target->id == IMAGE_XEN)
488 memcpy (ptr, ".xen", sizeof (".xen"));
489 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
490 ptr += sizeof (".xen");
491 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
492 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
493 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
494 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
495 shdr->sh_link = grub_host_to_target32 (0);
496 shdr->sh_info = grub_host_to_target32 (0);
497 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
498 shdr->sh_entsize = grub_host_to_target32 (0);
505 *core_size = program_size + header_size + footer_size;
508 /* Relocate symbols; note that this function overwrites the symbol table.
509 Return the address of a start symbol. */
511 SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
512 Elf_Shdr *symtab_section, Elf_Addr *section_vaddresses,
513 Elf_Half section_entsize, Elf_Half num_sections,
514 void *jumpers, Elf_Addr jumpers_addr,
515 Elf_Addr bss_start, Elf_Addr end,
516 const struct grub_install_image_target_desc *image_target)
518 Elf_Word symtab_size, sym_size, num_syms;
519 Elf_Off symtab_offset;
520 Elf_Addr start_address = (Elf_Addr) -1;
523 Elf_Shdr *symtab_link_section;
525 grub_uint64_t *jptr = jumpers;
528 = (Elf_Shdr *) ((char *) sections
529 + (grub_target_to_host32 (symtab_section->sh_link)
531 symtab = (char *) e + grub_target_to_host (symtab_link_section->sh_offset);
533 symtab_size = grub_target_to_host (symtab_section->sh_size);
534 sym_size = grub_target_to_host (symtab_section->sh_entsize);
535 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
536 num_syms = symtab_size / sym_size;
538 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
540 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
542 Elf_Section cur_index;
545 name = symtab + grub_target_to_host32 (sym->st_name);
547 cur_index = grub_target_to_host16 (sym->st_shndx);
548 if (cur_index == STN_ABS)
552 else if (cur_index == STN_UNDEF)
554 if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
555 sym->st_value = bss_start;
556 else if (sym->st_name && grub_strcmp (name, "_end") == 0)
558 else if (sym->st_name)
559 grub_util_error ("undefined symbol %s", name);
563 else if (cur_index >= num_sections)
564 grub_util_error ("section %d does not exist", cur_index);
567 sym->st_value = (grub_target_to_host (sym->st_value)
568 + section_vaddresses[cur_index]);
571 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
574 *jptr = grub_host_to_target64 (sym->st_value);
575 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
580 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
581 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
582 (unsigned long long) sym->st_value,
583 (unsigned long long) section_vaddresses[cur_index]);
585 if (start_address == (Elf_Addr)-1)
586 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
587 start_address = sym->st_value;
590 return start_address;
593 /* Return the address of a symbol at the index I in the section S. */
595 SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
596 const struct grub_install_image_target_desc *image_target)
600 sym = (Elf_Sym *) ((char *) e
601 + grub_target_to_host (s->sh_offset)
602 + i * grub_target_to_host (s->sh_entsize));
603 return sym->st_value;
606 /* Return the address of a modified value. */
608 SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
609 const struct grub_install_image_target_desc *image_target)
611 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
616 SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
617 const struct grub_install_image_target_desc *image_target)
619 Elf_Word symtab_size, sym_size, num_syms;
620 Elf_Off symtab_offset;
625 symtab_size = grub_target_to_host (symtab_section->sh_size);
626 sym_size = grub_target_to_host (symtab_section->sh_entsize);
627 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
628 num_syms = symtab_size / sym_size;
630 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
632 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
633 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
641 /* Deal with relocation information. This function relocates addresses
642 within the virtual address space starting from 0. So only relative
643 addresses can be fully resolved. Absolute addresses must be relocated
644 again by a PE32 relocator when loaded. */
646 arm_get_trampoline_size (Elf_Ehdr *e,
648 Elf_Half section_entsize,
649 Elf_Half num_sections,
650 const struct grub_install_image_target_desc *image_target)
656 for (i = 0, s = sections;
658 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
659 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
660 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
663 Elf_Word rtab_size, r_size, num_rs;
665 Elf_Shdr *symtab_section;
668 symtab_section = (Elf_Shdr *) ((char *) sections
669 + (grub_target_to_host32 (s->sh_link)
672 rtab_size = grub_target_to_host (s->sh_size);
673 r_size = grub_target_to_host (s->sh_entsize);
674 rtab_offset = grub_target_to_host (s->sh_offset);
675 num_rs = rtab_size / r_size;
677 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
679 j++, r = (Elf_Rela *) ((char *) r + r_size))
684 info = grub_target_to_host (r->r_info);
685 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
686 ELF_R_SYM (info), image_target);
688 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
689 grub_target_to_host (r->r_addend) : 0;
691 switch (ELF_R_TYPE (info))
697 case R_ARM_THM_JUMP24:
698 case R_ARM_THM_JUMP19:
710 grub_util_error (_("relocation 0x%x is not implemented yet"),
711 (unsigned int) ELF_R_TYPE (info));
720 /* Deal with relocation information. This function relocates addresses
721 within the virtual address space starting from 0. So only relative
722 addresses can be fully resolved. Absolute addresses must be relocated
723 again by a PE32 relocator when loaded. */
725 SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
726 Elf_Addr *section_addresses,
727 Elf_Half section_entsize, Elf_Half num_sections,
729 char *pe_target, Elf_Addr tramp_off,
731 const struct grub_install_image_target_desc *image_target)
736 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
737 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
738 unsigned unmatched_adr_got_page = 0;
739 #define MASK19 ((1 << 19) - 1)
741 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
744 for (i = 0, s = sections;
746 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
747 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
748 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
751 Elf_Word rtab_size, r_size, num_rs;
753 Elf_Shdr *symtab_section;
754 Elf_Word target_section_index;
755 Elf_Addr target_section_addr;
756 Elf_Shdr *target_section;
759 symtab_section = (Elf_Shdr *) ((char *) sections
760 + (grub_target_to_host32 (s->sh_link)
762 target_section_index = grub_target_to_host32 (s->sh_info);
763 target_section_addr = section_addresses[target_section_index];
764 target_section = (Elf_Shdr *) ((char *) sections
765 + (target_section_index
768 grub_util_info ("dealing with the relocation section %s for %s",
769 strtab + grub_target_to_host32 (s->sh_name),
770 strtab + grub_target_to_host32 (target_section->sh_name));
772 rtab_size = grub_target_to_host (s->sh_size);
773 r_size = grub_target_to_host (s->sh_entsize);
774 rtab_offset = grub_target_to_host (s->sh_offset);
775 num_rs = rtab_size / r_size;
777 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
779 j++, r = (Elf_Rela *) ((char *) r + r_size))
787 offset = grub_target_to_host (r->r_offset);
788 target = SUFFIX (get_target_address) (e, target_section,
789 offset, image_target);
790 info = grub_target_to_host (r->r_info);
791 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
792 ELF_R_SYM (info), image_target);
794 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
795 grub_target_to_host (r->r_addend) : 0;
797 switch (image_target->elf_target)
800 switch (ELF_R_TYPE (info))
806 /* This is absolute. */
807 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
808 + addend + sym_addr);
809 grub_util_info ("relocating an R_386_32 entry to 0x%"
810 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
811 GRUB_HOST_PRIxLONG_LONG,
812 (unsigned long long) *target,
813 (unsigned long long) offset);
817 /* This is relative. */
818 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
820 - target_section_addr - offset
821 - image_target->vaddr_offset);
822 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
823 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
824 GRUB_HOST_PRIxLONG_LONG,
825 (unsigned long long) *target,
826 (unsigned long long) offset);
829 grub_util_error (_("relocation 0x%x is not implemented yet"),
830 (unsigned int) ELF_R_TYPE (info));
836 switch (ELF_R_TYPE (info))
843 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
844 + addend + sym_addr);
845 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
846 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
847 GRUB_HOST_PRIxLONG_LONG,
848 (unsigned long long) *target,
849 (unsigned long long) offset);
855 grub_uint32_t *t32 = (grub_uint32_t *) target;
856 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
858 - target_section_addr - offset
859 - image_target->vaddr_offset);
860 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
861 GRUB_HOST_PRIxLONG_LONG,
862 *t32, (unsigned long long) offset);
868 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
870 - target_section_addr - offset
871 - image_target->vaddr_offset);
872 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
873 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
874 GRUB_HOST_PRIxLONG_LONG,
875 (unsigned long long) *target,
876 (unsigned long long) offset);
883 grub_uint32_t *t32 = (grub_uint32_t *) target;
884 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
885 + addend + sym_addr);
886 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
887 GRUB_HOST_PRIxLONG_LONG,
888 *t32, (unsigned long long) offset);
893 grub_util_error (_("relocation 0x%x is not implemented yet"),
894 (unsigned int) ELF_R_TYPE (info));
899 switch (ELF_R_TYPE (info))
901 case R_IA64_PCREL21B:
904 grub_ia64_make_trampoline (tr, addend + sym_addr);
905 noff = ((char *) tr - (char *) pe_target
906 - target_section_addr - (offset & ~3)) >> 4;
909 grub_util_error ("trampoline offset too big (%"
910 GRUB_HOST_PRIxLONG_LONG ")",
911 (unsigned long long) noff);
912 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
916 case R_IA64_LTOFF22X:
921 sym = (Elf_Sym *) ((char *) e
922 + grub_target_to_host (symtab_section->sh_offset)
923 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
924 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
925 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
927 - image_target->vaddr_offset));
930 case R_IA64_LTOFF_FPTR22:
931 *gpptr = grub_host_to_target64 (addend + sym_addr);
932 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
933 (char *) gpptr - (char *) pe_target
934 + image_target->vaddr_offset);
939 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
942 case R_IA64_GPREL64I:
943 grub_ia64_set_immu64 ((grub_addr_t) target,
946 case R_IA64_PCREL64LSB:
947 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
949 - target_section_addr - offset
950 - image_target->vaddr_offset);
953 case R_IA64_SEGREL64LSB:
954 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
955 + addend + sym_addr - target_section_addr);
957 case R_IA64_DIR64LSB:
958 case R_IA64_FPTR64LSB:
959 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
960 + addend + sym_addr);
961 grub_util_info ("relocating a direct entry to 0x%"
962 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
963 GRUB_HOST_PRIxLONG_LONG,
965 grub_target_to_host64 (*target),
966 (unsigned long long) offset);
969 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
974 grub_util_error (_("relocation 0x%x is not implemented yet"),
975 (unsigned int) ELF_R_TYPE (info));
982 switch (ELF_R_TYPE (info))
984 case R_AARCH64_ABS64:
986 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
989 case R_AARCH64_PREL32:
991 grub_uint32_t *t32 = (grub_uint32_t *) target;
992 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
994 - target_section_addr - offset
995 - image_target->vaddr_offset);
996 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
997 GRUB_HOST_PRIxLONG_LONG,
998 *t32, (unsigned long long) offset);
1001 case R_AARCH64_ADD_ABS_LO12_NC:
1002 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
1005 case R_AARCH64_LDST64_ABS_LO12_NC:
1006 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
1009 case R_AARCH64_JUMP26:
1010 case R_AARCH64_CALL26:
1013 sym_addr -= target_section_addr + image_target->vaddr_offset;
1014 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1015 grub_util_error ("%s", "CALL26 Relocation out of range");
1017 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1021 case R_AARCH64_ADR_GOT_PAGE:
1024 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1025 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1027 *gpptr = grub_host_to_target64 (sym_addr);
1028 unmatched_adr_got_page++;
1029 if (!grub_arm64_check_hi21_signed (gpoffset))
1030 grub_util_error ("HI21 out of range");
1031 grub_arm64_set_hi21((grub_uint32_t *)target,
1033 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1035 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1036 if (ELF_R_SYM (rel2->r_info)
1037 == ELF_R_SYM (r->r_info)
1038 && r->r_addend == rel2->r_addend
1039 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1041 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1042 grub_target_to_host (rel2->r_offset), image_target),
1043 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1047 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1051 case R_AARCH64_LD64_GOT_LO12_NC:
1052 if (unmatched_adr_got_page == 0)
1053 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1054 unmatched_adr_got_page--;
1056 case R_AARCH64_ADR_PREL_PG_HI21:
1058 sym_addr &= ~0xfffULL;
1059 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1060 if (!grub_arm64_check_hi21_signed (sym_addr))
1061 grub_util_error ("%s", "CALL26 Relocation out of range");
1063 grub_arm64_set_hi21((grub_uint32_t *)target,
1068 grub_util_error (_("relocation 0x%x is not implemented yet"),
1069 (unsigned int) ELF_R_TYPE (info));
1075 #if defined(MKIMAGE_ELF32)
1079 sym_addr -= image_target->vaddr_offset;
1080 switch (ELF_R_TYPE (info))
1084 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1085 (int) sym_addr, (int) sym_addr);
1086 /* Data will be naturally aligned */
1087 if (image_target->id == IMAGE_EFI)
1089 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1092 /* Happens when compiled with -march=armv4.
1093 Since currently we need at least armv5, keep bx as-is.
1097 case R_ARM_THM_CALL:
1098 case R_ARM_THM_JUMP24:
1099 case R_ARM_THM_JUMP19:
1103 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1104 (unsigned long) ((char *) target
1107 sym = (Elf_Sym *) ((char *) e
1108 + grub_target_to_host (symtab_section->sh_offset)
1109 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
1110 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1112 if (!(sym_addr & 1))
1114 grub_uint32_t tr_addr;
1115 grub_int32_t new_offset;
1116 tr_addr = (char *) tr - (char *) pe_target
1117 - target_section_addr;
1118 new_offset = sym_addr - tr_addr - 12;
1120 if (!grub_arm_jump24_check_offset (new_offset))
1121 return grub_util_error ("jump24 relocation out of range");
1123 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1124 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1126 sym_addr = tr_addr | 1;
1129 /* Thumb instructions can be 16-bit aligned */
1130 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1131 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1133 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1136 grub_util_error ("%s", grub_errmsg);
1144 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1147 grub_uint32_t tr_addr;
1148 grub_int32_t new_offset;
1149 tr_addr = (char *) tr - (char *) pe_target
1150 - target_section_addr;
1151 new_offset = sym_addr - tr_addr - 12;
1153 /* There is no immediate version of bx, only register one... */
1154 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1155 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1156 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1157 tr[3] = grub_host_to_target32 (new_offset | 1);
1162 err = grub_arm_reloc_jump24 (target,
1165 grub_util_error ("%s", grub_errmsg);
1170 grub_util_error (_("relocation 0x%x is not implemented yet"),
1171 (unsigned int) ELF_R_TYPE (info));
1176 #endif /* MKIMAGE_ELF32 */
1178 grub_util_error ("unknown architecture type %d",
1179 image_target->elf_target);
1185 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1186 after having written to the file OUT. */
1188 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1189 Elf_Addr addr, int flush, Elf_Addr current_address,
1190 const struct grub_install_image_target_desc *image_target)
1192 struct grub_pe32_fixup_block *b;
1194 b = &((*cblock)->b);
1196 /* First, check if it is necessary to write out the current block. */
1197 if ((*cblock)->state)
1199 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
1205 /* Add as much padding as necessary to align the address
1206 with a section boundary. */
1207 Elf_Addr next_address;
1208 unsigned padding_size;
1211 next_address = current_address + b->block_size;
1212 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1215 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1216 grub_util_info ("adding %d padding fixup entries", padding_size);
1217 while (padding_size--)
1219 b->entries[cur_index++] = 0;
1223 else while (b->block_size & (8 - 1))
1225 /* If not aligned with a 32-bit boundary, add
1229 grub_util_info ("adding a padding fixup entry");
1230 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1231 b->entries[cur_index] = 0;
1236 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1237 b->block_size, b->page_rva);
1238 size = b->block_size;
1239 current_address += size;
1240 b->page_rva = grub_host_to_target32 (b->page_rva);
1241 b->block_size = grub_host_to_target32 (b->block_size);
1242 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1243 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1244 *cblock = (*cblock)->next;
1248 b = &((*cblock)->b);
1252 grub_uint16_t entry;
1255 /* If not allocated yet, allocate a block with enough entries. */
1256 if (! (*cblock)->state)
1258 (*cblock)->state = 1;
1260 /* The spec does not mention the requirement of a Page RVA.
1261 Here, align the address with a 4K boundary for safety. */
1262 b->page_rva = (addr & ~(0x1000 - 1));
1263 b->block_size = sizeof (*b);
1267 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1268 grub_util_error ("too many fixup entries");
1270 /* Add a new entry. */
1271 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1272 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
1273 b->entries[cur_index] = grub_host_to_target16 (entry);
1277 return current_address;
1282 struct raw_reloc *next;
1283 grub_uint32_t offset;
1284 enum raw_reloc_type {
1285 RAW_RELOC_NONE = -1,
1291 struct translate_context
1294 struct fixup_block_list *lst, *lst0;
1295 Elf_Addr current_address;
1298 struct raw_reloc *raw_relocs;
1302 translate_reloc_start (struct translate_context *ctx,
1303 const struct grub_install_image_target_desc *image_target)
1305 grub_memset (ctx, 0, sizeof (*ctx));
1306 if (image_target->id == IMAGE_EFI)
1308 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1309 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1310 ctx->current_address = 0;
1315 translate_relocation_pe (struct translate_context *ctx,
1318 const struct grub_install_image_target_desc *image_target)
1320 /* Necessary to relocate only absolute addresses. */
1321 switch (image_target->elf_target)
1324 if (ELF_R_TYPE (info) == R_386_32)
1326 grub_util_info ("adding a relocation entry for 0x%"
1327 GRUB_HOST_PRIxLONG_LONG,
1328 (unsigned long long) addr);
1329 ctx->current_address
1330 = add_fixup_entry (&ctx->lst,
1331 GRUB_PE32_REL_BASED_HIGHLOW,
1332 addr, 0, ctx->current_address,
1337 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1338 (ELF_R_TYPE (info) == R_X86_64_32S))
1340 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1342 else if (ELF_R_TYPE (info) == R_X86_64_64)
1344 grub_util_info ("adding a relocation entry for 0x%"
1345 GRUB_HOST_PRIxLONG_LONG,
1346 (unsigned long long) addr);
1347 ctx->current_address
1348 = add_fixup_entry (&ctx->lst,
1349 GRUB_PE32_REL_BASED_DIR64,
1351 0, ctx->current_address,
1356 switch (ELF_R_TYPE (info))
1358 case R_IA64_PCREL64LSB:
1360 case R_IA64_PCREL21B:
1361 case R_IA64_LTOFF_FPTR22:
1362 case R_IA64_LTOFF22X:
1363 case R_IA64_LTOFF22:
1364 case R_IA64_GPREL22:
1365 case R_IA64_GPREL64I:
1366 case R_IA64_SEGREL64LSB:
1369 case R_IA64_FPTR64LSB:
1370 case R_IA64_DIR64LSB:
1373 grub_util_info ("adding a relocation entry for 0x%"
1374 GRUB_HOST_PRIxLONG_LONG,
1375 (unsigned long long) addr);
1376 ctx->current_address
1377 = add_fixup_entry (&ctx->lst,
1378 GRUB_PE32_REL_BASED_DIR64,
1380 0, ctx->current_address,
1386 grub_util_error (_("relocation 0x%x is not implemented yet"),
1387 (unsigned int) ELF_R_TYPE (info));
1392 switch (ELF_R_TYPE (info))
1394 case R_AARCH64_ABS64:
1396 ctx->current_address
1397 = add_fixup_entry (&ctx->lst,
1398 GRUB_PE32_REL_BASED_DIR64,
1399 addr, 0, ctx->current_address,
1403 /* Relative relocations do not require fixup entries. */
1404 case R_AARCH64_CALL26:
1405 case R_AARCH64_JUMP26:
1406 case R_AARCH64_PREL32:
1408 /* Page-relative relocations do not require fixup entries. */
1409 case R_AARCH64_ADR_PREL_PG_HI21:
1410 /* We page-align the whole kernel, so no need
1413 case R_AARCH64_ADD_ABS_LO12_NC:
1414 case R_AARCH64_LDST64_ABS_LO12_NC:
1417 /* GOT is relocated separately. */
1418 case R_AARCH64_ADR_GOT_PAGE:
1419 case R_AARCH64_LD64_GOT_LO12_NC:
1423 grub_util_error (_("relocation 0x%x is not implemented yet"),
1424 (unsigned int) ELF_R_TYPE (info));
1429 #if defined(MKIMAGE_ELF32)
1431 switch (ELF_R_TYPE (info))
1434 /* Relative relocations do not require fixup entries. */
1436 case R_ARM_THM_CALL:
1437 case R_ARM_THM_JUMP19:
1438 case R_ARM_THM_JUMP24:
1441 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1444 /* Create fixup entry for PE/COFF loader */
1447 ctx->current_address
1448 = add_fixup_entry (&ctx->lst,
1449 GRUB_PE32_REL_BASED_HIGHLOW,
1450 addr, 0, ctx->current_address,
1455 grub_util_error (_("relocation 0x%x is not implemented yet"),
1456 (unsigned int) ELF_R_TYPE (info));
1460 #endif /* defined(MKIMAGE_ELF32) */
1462 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1466 static enum raw_reloc_type
1467 classify_raw_reloc (Elf_Addr info,
1468 const struct grub_install_image_target_desc *image_target)
1470 /* Necessary to relocate only absolute addresses. */
1471 switch (image_target->elf_target)
1474 switch (ELF_R_TYPE (info))
1478 case R_ARM_THM_CALL:
1479 case R_ARM_THM_JUMP19:
1480 case R_ARM_THM_JUMP24:
1482 return RAW_RELOC_NONE;
1484 return RAW_RELOC_32;
1486 grub_util_error (_("relocation 0x%x is not implemented yet"),
1487 (unsigned int) ELF_R_TYPE (info));
1492 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1497 translate_relocation_raw (struct translate_context *ctx,
1500 const struct grub_install_image_target_desc *image_target)
1502 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
1503 struct raw_reloc *rel;
1504 if (class == RAW_RELOC_NONE)
1506 rel = xmalloc (sizeof (*rel));
1507 rel->next = ctx->raw_relocs;
1510 ctx->raw_relocs = rel;
1514 translate_relocation (struct translate_context *ctx,
1517 const struct grub_install_image_target_desc *image_target)
1519 if (image_target->id == IMAGE_EFI)
1520 translate_relocation_pe (ctx, addr, info, image_target);
1522 translate_relocation_raw (ctx, addr, info, image_target);
1526 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1527 const struct grub_install_image_target_desc *image_target)
1529 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
1533 layout->reloc_section = ptr = xmalloc (ctx->current_address);
1534 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
1535 if (ctx->lst->state)
1537 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
1538 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
1540 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
1543 for (ctx->lst = ctx->lst0; ctx->lst; )
1545 struct fixup_block_list *next;
1546 next = ctx->lst->next;
1551 layout->reloc_size = ctx->current_address;
1552 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
1553 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
1554 "This breaks assembly assumptions. Please increase stack size",
1555 (int) layout->reloc_size,
1556 (int) GRUB_KERNEL_ARM_STACK_SIZE);
1561 <type 0 relocations>
1563 <type 1 relocations>
1566 <type n relocations>
1568 each relocation starts with 32-bit offset. Rest depends on relocation.
1569 mkimage stops when it sees first unknown type or end marker.
1570 This allows images to be created with mismatched mkimage and
1571 kernel as long as no relocations are present in kernel that mkimage
1572 isn't aware of (in which case mkimage aborts).
1573 This also allows simple assembly to do the relocs.
1576 #define RAW_SEPARATOR 0xfffffffe
1577 #define RAW_END_MARKER 0xffffffff
1580 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1581 const struct grub_install_image_target_desc *image_target)
1583 size_t count = 0, sz;
1584 enum raw_reloc_type highest = RAW_RELOC_NONE;
1585 enum raw_reloc_type curtype;
1586 struct raw_reloc *cur;
1588 if (!ctx->raw_relocs)
1590 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
1591 p[0] = RAW_END_MARKER;
1592 layout->reloc_size = sizeof (grub_uint32_t);
1595 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1598 if (cur->type > highest)
1599 highest = cur->type;
1601 /* highest separators, count relocations and one end marker. */
1602 sz = (highest + count + 1) * sizeof (grub_uint32_t);
1603 layout->reloc_section = p = xmalloc (sz);
1604 for (curtype = 0; curtype <= highest; curtype++)
1606 /* Support for special cases would go here. */
1607 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1608 if (cur->type == curtype)
1612 *p++ = RAW_SEPARATOR;
1614 *--p = RAW_END_MARKER;
1615 layout->reloc_size = sz;
1619 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1620 const struct grub_install_image_target_desc *image_target)
1622 if (image_target->id == IMAGE_EFI)
1623 finish_reloc_translation_pe (ctx, layout, image_target);
1625 finish_reloc_translation_raw (ctx, layout, image_target);
1630 create_u64_fixups (struct translate_context *ctx,
1631 Elf_Addr jumpers, grub_size_t njumpers,
1632 const struct grub_install_image_target_desc *image_target)
1635 assert (image_target->id == IMAGE_EFI);
1636 for (i = 0; i < njumpers; i++)
1637 ctx->current_address = add_fixup_entry (&ctx->lst,
1638 GRUB_PE32_REL_BASED_DIR64,
1640 0, ctx->current_address,
1644 /* Make a .reloc section. */
1646 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
1647 Elf_Addr *section_vaddresses, Elf_Shdr *sections,
1648 Elf_Half section_entsize, Elf_Half num_sections,
1650 const struct grub_install_image_target_desc *image_target)
1654 struct translate_context ctx;
1656 translate_reloc_start (&ctx, image_target);
1658 for (i = 0, s = sections; i < num_sections;
1659 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1660 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1661 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
1664 Elf_Word rtab_size, r_size, num_rs;
1665 Elf_Off rtab_offset;
1666 Elf_Addr section_address;
1669 grub_util_info ("translating the relocation section %s",
1670 strtab + grub_le_to_cpu32 (s->sh_name));
1672 rtab_size = grub_target_to_host (s->sh_size);
1673 r_size = grub_target_to_host (s->sh_entsize);
1674 rtab_offset = grub_target_to_host (s->sh_offset);
1675 num_rs = rtab_size / r_size;
1677 section_address = section_vaddresses[grub_le_to_cpu32 (s->sh_info)];
1679 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1681 j++, r = (Elf_Rel *) ((char *) r + r_size))
1687 offset = grub_target_to_host (r->r_offset);
1688 info = grub_target_to_host (r->r_info);
1690 addr = section_address + offset;
1692 translate_relocation (&ctx, addr, info, image_target);
1696 if (image_target->elf_target == EM_IA_64)
1697 create_u64_fixups (&ctx,
1699 + image_target->vaddr_offset,
1700 2 * layout->ia64jmpnum,
1702 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
1703 create_u64_fixups (&ctx,
1705 + image_target->vaddr_offset,
1706 (layout->got_size / 8),
1709 finish_reloc_translation (&ctx, layout, image_target);
1712 /* Determine if this section is a text section. Return false if this
1713 section is not allocated. */
1715 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1717 if (!is_relocatable (image_target)
1718 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1720 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1721 == (SHF_EXECINSTR | SHF_ALLOC));
1724 /* Determine if this section is a data section. */
1726 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1728 if (!is_relocatable (image_target)
1729 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1731 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1732 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1736 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1738 if (!is_relocatable (image_target))
1740 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1741 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1744 /* Return if the ELF header is valid. */
1746 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
1748 if (size < sizeof (*e)
1749 || e->e_ident[EI_MAG0] != ELFMAG0
1750 || e->e_ident[EI_MAG1] != ELFMAG1
1751 || e->e_ident[EI_MAG2] != ELFMAG2
1752 || e->e_ident[EI_MAG3] != ELFMAG3
1753 || e->e_ident[EI_VERSION] != EV_CURRENT
1754 || e->e_ident[EI_CLASS] != ELFCLASSXX
1755 || e->e_version != grub_host_to_target32 (EV_CURRENT))
1762 SUFFIX (put_section) (Elf_Shdr *s, int i,
1763 Elf_Addr current_address,
1764 Elf_Addr *section_addresses,
1766 const struct grub_install_image_target_desc *image_target)
1768 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
1769 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1772 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1774 - image_target->vaddr_offset;
1776 grub_util_info ("locating the section %s at 0x%"
1777 GRUB_HOST_PRIxLONG_LONG,
1778 name, (unsigned long long) current_address);
1779 if (!is_relocatable (image_target))
1780 current_address = grub_host_to_target_addr (s->sh_addr)
1781 - image_target->link_addr;
1782 section_addresses[i] = current_address;
1783 current_address += grub_host_to_target_addr (s->sh_size);
1784 return current_address;
1787 /* Locate section addresses by merging code sections and data sections
1788 into .text and .data, respectively. Return the array of section
1791 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
1792 Elf_Shdr *sections, Elf_Half section_entsize,
1793 Elf_Half num_sections, const char *strtab,
1794 struct grub_mkimage_layout *layout,
1795 const struct grub_install_image_target_desc *image_target)
1798 Elf_Addr *section_addresses;
1802 /* Page-aligning simplifies relocation handling. */
1803 if (image_target->elf_target == EM_AARCH64)
1804 layout->align = 4096;
1806 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
1807 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
1809 layout->kernel_size = 0;
1811 for (i = 0, s = sections;
1813 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1814 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
1815 && grub_host_to_target32 (s->sh_addralign) > layout->align)
1816 layout->align = grub_host_to_target32 (s->sh_addralign);
1820 for (i = 0, s = sections;
1822 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1823 if (SUFFIX (is_text_section) (s, image_target))
1825 layout->kernel_size = SUFFIX (put_section) (s, i,
1826 layout->kernel_size,
1830 if (!is_relocatable (image_target) &&
1831 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
1834 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
1835 " instead of 0x%llx: ld.gold bug?"),
1837 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
1838 (unsigned long long) image_target->link_addr);
1839 grub_util_error ("%s", msg);
1843 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1844 image_target->section_align)
1845 - image_target->vaddr_offset;
1846 layout->exec_size = layout->kernel_size;
1849 for (i = 0, s = sections;
1851 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1852 if (SUFFIX (is_data_section) (s, image_target))
1853 layout->kernel_size = SUFFIX (put_section) (s, i,
1854 layout->kernel_size,
1859 #ifdef MKIMAGE_ELF32
1860 if (image_target->elf_target == EM_ARM)
1863 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1864 image_target->section_align) - image_target->vaddr_offset;
1866 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
1868 tramp = arm_get_trampoline_size (e, sections, section_entsize,
1869 num_sections, image_target);
1871 layout->tramp_off = layout->kernel_size;
1872 layout->kernel_size += ALIGN_UP (tramp, 16);
1876 layout->bss_start = layout->kernel_size;
1877 layout->end = layout->kernel_size;
1880 for (i = 0, s = sections;
1882 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1883 if (SUFFIX (is_bss_section) (s, image_target))
1884 layout->end = SUFFIX (put_section) (s, i,
1890 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
1891 image_target->section_align) - image_target->vaddr_offset;
1892 /* Explicitly initialize BSS
1893 when producing PE32 to avoid a bug in EFI implementations.
1894 Platforms other than EFI and U-boot shouldn't have .bss in
1895 their binaries as we build with -Wl,-Ttext.
1897 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
1898 layout->kernel_size = layout->end;
1900 return section_addresses;
1904 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
1905 size_t total_module_size,
1906 struct grub_mkimage_layout *layout,
1907 const struct grub_install_image_target_desc *image_target)
1909 char *kernel_img, *out_img;
1913 Elf_Addr *section_addresses;
1914 Elf_Addr *section_vaddresses;
1917 Elf_Half num_sections;
1918 Elf_Off section_offset;
1919 Elf_Half section_entsize;
1920 grub_size_t kernel_size;
1921 Elf_Shdr *symtab_section = 0;
1923 grub_memset (layout, 0, sizeof (*layout));
1925 layout->start_address = 0;
1927 kernel_size = grub_util_get_image_size (kernel_path);
1928 kernel_img = xmalloc (kernel_size);
1929 grub_util_load_image (kernel_path, kernel_img);
1931 e = (Elf_Ehdr *) kernel_img;
1932 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
1933 grub_util_error ("invalid ELF header");
1935 section_offset = grub_target_to_host (e->e_shoff);
1936 section_entsize = grub_target_to_host16 (e->e_shentsize);
1937 num_sections = grub_target_to_host16 (e->e_shnum);
1939 if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections)
1940 grub_util_error (_("premature end of file %s"), kernel_path);
1942 sections = (Elf_Shdr *) (kernel_img + section_offset);
1944 /* Relocate sections then symbols in the virtual address space. */
1945 s = (Elf_Shdr *) ((char *) sections
1946 + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
1947 strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
1949 section_addresses = SUFFIX (locate_sections) (e, kernel_path,
1950 sections, section_entsize,
1951 num_sections, strtab,
1955 section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
1957 for (i = 0; i < num_sections; i++)
1958 section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
1960 if (!is_relocatable (image_target))
1962 Elf_Addr current_address = layout->kernel_size;
1964 for (i = 0, s = sections;
1966 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1967 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1969 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
1970 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1973 current_address = ALIGN_UP (current_address
1974 + image_target->vaddr_offset,
1976 - image_target->vaddr_offset;
1978 grub_util_info ("locating the section %s at 0x%"
1979 GRUB_HOST_PRIxLONG_LONG,
1980 name, (unsigned long long) current_address);
1981 if (!is_relocatable (image_target))
1982 current_address = grub_host_to_target_addr (s->sh_addr)
1983 - image_target->link_addr;
1985 section_vaddresses[i] = current_address
1986 + image_target->vaddr_offset;
1987 current_address += grub_host_to_target_addr (s->sh_size);
1989 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1990 image_target->section_align)
1991 - image_target->vaddr_offset;
1992 layout->bss_size = current_address - layout->kernel_size;
1995 layout->bss_size = 0;
1997 if (image_target->id == IMAGE_SPARC64_AOUT
1998 || image_target->id == IMAGE_SPARC64_RAW
1999 || image_target->id == IMAGE_UBOOT
2000 || image_target->id == IMAGE_COREBOOT
2001 || image_target->id == IMAGE_SPARC64_CDCORE)
2002 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
2004 if (is_relocatable (image_target))
2006 symtab_section = NULL;
2007 for (i = 0, s = sections;
2009 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2010 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2015 if (! symtab_section)
2016 grub_util_error ("%s", _("no symbol table"));
2017 #ifdef MKIMAGE_ELF64
2018 if (image_target->elf_target == EM_IA_64)
2022 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2024 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2026 layout->tramp_off = layout->kernel_size;
2027 layout->kernel_size += ALIGN_UP (tramp, 16);
2029 layout->ia64jmp_off = layout->kernel_size;
2030 layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
2032 layout->kernel_size += 16 * layout->ia64jmpnum;
2034 layout->got_off = layout->kernel_size;
2035 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2037 if (image_target->elf_target == EM_AARCH64)
2041 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2043 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2045 layout->got_off = layout->kernel_size;
2046 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2052 layout->reloc_size = 0;
2053 layout->reloc_section = NULL;
2056 out_img = xmalloc (layout->kernel_size + total_module_size);
2057 memset (out_img, 0, layout->kernel_size + total_module_size);
2059 if (is_relocatable (image_target))
2061 layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
2062 section_vaddresses, section_entsize,
2064 (char *) out_img + layout->ia64jmp_off,
2066 + image_target->vaddr_offset,
2070 if (layout->start_address == (Elf_Addr) -1)
2071 grub_util_error ("start symbol is not defined");
2073 /* Resolve addresses in the virtual address space. */
2074 SUFFIX (relocate_addresses) (e, sections, section_addresses,
2076 num_sections, strtab,
2077 out_img, layout->tramp_off,
2081 make_reloc_section (e, layout,
2082 section_vaddresses, sections,
2083 section_entsize, num_sections,
2086 if (image_target->id != IMAGE_EFI)
2088 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2089 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2090 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2091 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2092 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2093 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2097 for (i = 0, s = sections;
2099 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2100 if (SUFFIX (is_data_section) (s, image_target)
2101 /* Explicitly initialize BSS
2102 when producing PE32 to avoid a bug in EFI implementations.
2103 Platforms other than EFI and U-boot shouldn't have .bss in
2104 their binaries as we build with -Wl,-Ttext.
2106 || (SUFFIX (is_bss_section) (s, image_target) && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2107 || SUFFIX (is_text_section) (s, image_target))
2109 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2110 memset (out_img + section_addresses[i], 0,
2111 grub_host_to_target_addr (s->sh_size));
2113 memcpy (out_img + section_addresses[i],
2114 kernel_img + grub_host_to_target_addr (s->sh_offset),
2115 grub_host_to_target_addr (s->sh_size));
2119 free (section_vaddresses);
2120 free (section_addresses);