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))
96 struct section_metadata
98 Elf_Half num_sections;
102 Elf_Half section_entsize;
108 is_relocatable (const struct grub_install_image_target_desc *image_target)
110 return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
111 || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
117 * R_ARM_THM_CALL/THM_JUMP24
119 * Relocate Thumb (T32) instruction set relative branches:
123 grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
127 offset = grub_arm_thm_call_get_offset (target);
129 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
133 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
134 target, sym_addr, offset);
136 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
137 is bigger than 2M (currently under 150K) then we probably have a problem
139 if (offset < -0x200000 || offset >= 0x200000)
140 return grub_error (GRUB_ERR_BAD_MODULE,
141 "THM_CALL Relocation out of range.");
143 grub_dprintf ("dl", " relative destination = %p",
144 (char *) target + offset);
146 return grub_arm_thm_call_set_offset (target, offset);
152 * Relocate conditional Thumb (T32) B<c>.W
155 grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
160 return grub_error (GRUB_ERR_BAD_MODULE,
161 "Relocation targeting wrong execution state");
163 offset = grub_arm_thm_jump19_get_offset (target);
165 /* Adjust and re-truncate offset */
168 if (!grub_arm_thm_jump19_check_offset (offset))
169 return grub_error (GRUB_ERR_BAD_MODULE,
170 "THM_JUMP19 Relocation out of range.");
172 grub_arm_thm_jump19_set_offset (target, offset);
174 return GRUB_ERR_NONE;
180 * Relocate ARM (A32) B
183 grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
188 return grub_error (GRUB_ERR_BAD_MODULE,
189 "Relocation targeting wrong execution state");
191 offset = grub_arm_jump24_get_offset (target);
194 if (!grub_arm_jump24_check_offset (offset))
195 return grub_error (GRUB_ERR_BAD_MODULE,
196 "JUMP24 Relocation out of range.");
199 grub_arm_jump24_set_offset (target, offset);
201 return GRUB_ERR_NONE;
207 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
208 int note, char **core_img, size_t *core_size,
209 Elf_Addr target_addr,
210 struct grub_mkimage_layout *layout)
217 int header_size, footer_size = 0;
220 int string_size = sizeof (".text") + sizeof ("mods") + 1;
222 if (image_target->id != IMAGE_LOONGSON_ELF)
228 footer_size += sizeof (struct grub_ieee1275_note);
230 if (image_target->id == IMAGE_XEN)
234 string_size += sizeof (".xen");
235 footer_size += XEN_NOTE_SIZE;
237 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
238 + shnum * sizeof (*shdr) + string_size, layout->align);
240 program_size = ALIGN_ADDR (*core_size);
242 elf_img = xmalloc (program_size + header_size + footer_size);
243 memset (elf_img, 0, program_size + header_size + footer_size);
244 memcpy (elf_img + header_size, *core_img, *core_size);
245 ehdr = (void *) elf_img;
246 phdr = (void *) (elf_img + sizeof (*ehdr));
247 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
248 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
249 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
250 if (!image_target->bigendian)
251 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
253 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
254 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
255 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
256 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
257 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
258 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
260 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
261 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
262 ehdr->e_phnum = grub_host_to_target16 (phnum);
264 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
265 - (grub_uint8_t *) ehdr);
266 if (image_target->id == IMAGE_LOONGSON_ELF)
267 ehdr->e_shentsize = grub_host_to_target16 (0);
269 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
270 ehdr->e_shnum = grub_host_to_target16 (shnum);
271 ehdr->e_shstrndx = grub_host_to_target16 (1);
273 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
275 phdr->p_type = grub_host_to_target32 (PT_LOAD);
276 phdr->p_offset = grub_host_to_target32 (header_size);
277 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
279 ehdr->e_entry = grub_host_to_target32 (target_addr);
280 phdr->p_vaddr = grub_host_to_target32 (target_addr);
281 phdr->p_paddr = grub_host_to_target32 (target_addr);
282 phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
283 layout->align : image_target->link_align);
284 if (image_target->id == IMAGE_LOONGSON_ELF)
285 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
286 | EF_MIPS_PIC | EF_MIPS_CPIC);
289 if (image_target->id == IMAGE_LOONGSON_ELF)
291 phdr->p_filesz = grub_host_to_target32 (*core_size);
292 phdr->p_memsz = grub_host_to_target32 (*core_size);
296 grub_uint32_t target_addr_mods;
297 phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
298 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
299 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
301 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
304 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
305 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
306 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
307 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
308 phdr->p_align = grub_host_to_target32 (image_target->link_align);
311 phdr->p_type = grub_host_to_target32 (PT_LOAD);
312 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
313 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
314 phdr->p_filesz = phdr->p_memsz
315 = grub_host_to_target32 (*core_size - layout->kernel_size);
317 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
318 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
319 else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
320 target_addr_mods = ALIGN_UP (target_addr + layout->end
321 + image_target->mod_gap,
322 image_target->mod_align);
324 target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
325 + image_target->mod_gap,
326 image_target->mod_align);
327 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
328 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
329 phdr->p_align = grub_host_to_target32 (image_target->link_align);
332 if (image_target->id == IMAGE_XEN)
334 char *note_start = (elf_img + program_size + header_size);
336 char *ptr = (char *) note_start;
338 grub_util_info ("adding XEN NOTE segment");
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 (PACKAGE_NAME));
344 note_ptr->n_type = grub_host_to_target32 (6);
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, PACKAGE_NAME, sizeof (PACKAGE_NAME));
349 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 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 ("generic"));
355 note_ptr->n_type = grub_host_to_target32 (8);
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, "generic", sizeof ("generic"));
360 ptr += ALIGN_UP (sizeof ("generic"), 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 (sizeof ("xen-3.0"));
366 note_ptr->n_type = grub_host_to_target32 (5);
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 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
371 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
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 (1);
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 note_ptr = (Elf_Nhdr *) ptr;
386 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
387 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
388 note_ptr->n_type = grub_host_to_target32 (3);
389 ptr += sizeof (Elf_Nhdr);
390 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
391 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
392 memset (ptr, 0, image_target->voidp_sizeof);
393 ptr += image_target->voidp_sizeof;
396 if (image_target->elf_target == EM_386)
398 note_ptr = (Elf_Nhdr *) ptr;
399 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
400 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
401 note_ptr->n_type = grub_host_to_target32 (9);
402 ptr += sizeof (Elf_Nhdr);
403 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
404 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
405 memcpy (ptr, "yes", sizeof ("yes"));
406 ptr += ALIGN_UP (sizeof ("yes"), 4);
409 assert (XEN_NOTE_SIZE == (ptr - note_start));
412 phdr->p_type = grub_host_to_target32 (PT_NOTE);
413 phdr->p_flags = grub_host_to_target32 (PF_R);
414 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
417 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
419 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
424 int note_size = sizeof (struct grub_ieee1275_note);
425 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
426 (elf_img + program_size + header_size);
428 grub_util_info ("adding CHRP NOTE segment");
430 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
431 note_ptr->header.n_descsz = grub_host_to_target32 (note_size);
432 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
433 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
434 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
435 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
436 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
437 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
438 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
439 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
442 phdr->p_type = grub_host_to_target32 (PT_NOTE);
443 phdr->p_flags = grub_host_to_target32 (PF_R);
444 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
447 phdr->p_filesz = grub_host_to_target32 (note_size);
449 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
453 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
454 + shnum * sizeof (*shdr));
455 char *ptr = str_start + 1;
459 shdr->sh_name = grub_host_to_target32 (0);
460 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
461 shdr->sh_addr = grub_host_to_target_addr (0);
462 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
463 shdr->sh_size = grub_host_to_target32 (string_size);
464 shdr->sh_link = grub_host_to_target32 (0);
465 shdr->sh_info = grub_host_to_target32 (0);
466 shdr->sh_addralign = grub_host_to_target32 (layout->align);
467 shdr->sh_entsize = grub_host_to_target32 (0);
470 memcpy (ptr, ".text", sizeof (".text"));
472 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
473 ptr += sizeof (".text");
474 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
475 shdr->sh_addr = grub_host_to_target_addr (target_addr);
476 shdr->sh_offset = grub_host_to_target_addr (header_size);
477 shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
478 shdr->sh_link = grub_host_to_target32 (0);
479 shdr->sh_info = grub_host_to_target32 (0);
480 shdr->sh_addralign = grub_host_to_target32 (layout->align);
481 shdr->sh_entsize = grub_host_to_target32 (0);
484 memcpy (ptr, "mods", sizeof ("mods"));
485 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
486 ptr += sizeof ("mods");
487 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
488 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
489 shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
490 shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
491 shdr->sh_link = grub_host_to_target32 (0);
492 shdr->sh_info = grub_host_to_target32 (0);
493 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
494 shdr->sh_entsize = grub_host_to_target32 (0);
497 if (image_target->id == IMAGE_XEN)
499 memcpy (ptr, ".xen", sizeof (".xen"));
500 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
501 ptr += sizeof (".xen");
502 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
503 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
504 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
505 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
506 shdr->sh_link = grub_host_to_target32 (0);
507 shdr->sh_info = grub_host_to_target32 (0);
508 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
509 shdr->sh_entsize = grub_host_to_target32 (0);
516 *core_size = program_size + header_size + footer_size;
519 /* Relocate symbols; note that this function overwrites the symbol table.
520 Return the address of a start symbol. */
522 SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
523 void *jumpers, Elf_Addr jumpers_addr,
524 Elf_Addr bss_start, Elf_Addr end,
525 const struct grub_install_image_target_desc *image_target)
527 Elf_Word symtab_size, sym_size, num_syms;
528 Elf_Off symtab_offset;
529 Elf_Addr start_address = (Elf_Addr) -1;
532 Elf_Shdr *symtab_section;
534 grub_uint64_t *jptr = jumpers;
536 symtab_section = (Elf_Shdr *) ((char *) smd->sections
537 + grub_target_to_host32 (smd->symtab->sh_link)
538 * smd->section_entsize);
539 symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
541 symtab_size = grub_target_to_host (smd->symtab->sh_size);
542 sym_size = grub_target_to_host (smd->symtab->sh_entsize);
543 symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
544 num_syms = symtab_size / sym_size;
546 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
548 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
550 Elf_Section cur_index;
553 name = symtab + grub_target_to_host32 (sym->st_name);
555 cur_index = grub_target_to_host16 (sym->st_shndx);
556 if (cur_index == STN_ABS)
560 else if (cur_index == STN_UNDEF)
562 if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
563 sym->st_value = bss_start;
564 else if (sym->st_name && grub_strcmp (name, "_end") == 0)
566 else if (sym->st_name)
567 grub_util_error ("undefined symbol %s", name);
571 else if (cur_index >= smd->num_sections)
572 grub_util_error ("section %d does not exist", cur_index);
575 sym->st_value = (grub_target_to_host (sym->st_value)
576 + smd->vaddrs[cur_index]);
579 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
582 *jptr = grub_host_to_target64 (sym->st_value);
583 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
588 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
589 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
590 (unsigned long long) sym->st_value,
591 (unsigned long long) smd->vaddrs[cur_index]);
593 if (start_address == (Elf_Addr)-1)
594 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
595 start_address = sym->st_value;
598 return start_address;
601 /* Return the address of a symbol at the index I in the section S. */
603 SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
604 const struct grub_install_image_target_desc *image_target)
608 sym = (Elf_Sym *) ((char *) e
609 + grub_target_to_host (s->sh_offset)
610 + i * grub_target_to_host (s->sh_entsize));
611 return sym->st_value;
614 /* Return the address of a modified value. */
616 SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
617 const struct grub_install_image_target_desc *image_target)
619 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
624 SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
625 const struct grub_install_image_target_desc *image_target)
627 Elf_Word symtab_size, sym_size, num_syms;
628 Elf_Off symtab_offset;
633 symtab_size = grub_target_to_host (symtab_section->sh_size);
634 sym_size = grub_target_to_host (symtab_section->sh_entsize);
635 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
636 num_syms = symtab_size / sym_size;
638 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
640 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
641 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
649 /* Deal with relocation information. This function relocates addresses
650 within the virtual address space starting from 0. So only relative
651 addresses can be fully resolved. Absolute addresses must be relocated
652 again by a PE32 relocator when loaded. */
654 arm_get_trampoline_size (Elf_Ehdr *e,
656 Elf_Half section_entsize,
657 Elf_Half num_sections,
658 const struct grub_install_image_target_desc *image_target)
664 for (i = 0, s = sections;
666 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
667 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
668 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
671 Elf_Word rtab_size, r_size, num_rs;
673 Elf_Shdr *symtab_section;
676 symtab_section = (Elf_Shdr *) ((char *) sections
677 + (grub_target_to_host32 (s->sh_link)
680 rtab_size = grub_target_to_host (s->sh_size);
681 r_size = grub_target_to_host (s->sh_entsize);
682 rtab_offset = grub_target_to_host (s->sh_offset);
683 num_rs = rtab_size / r_size;
685 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
687 j++, r = (Elf_Rela *) ((char *) r + r_size))
692 info = grub_target_to_host (r->r_info);
693 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
694 ELF_R_SYM (info), image_target);
696 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
697 grub_target_to_host (r->r_addend) : 0;
699 switch (ELF_R_TYPE (info))
705 case R_ARM_THM_JUMP24:
706 case R_ARM_THM_JUMP19:
718 grub_util_error (_("relocation 0x%x is not implemented yet"),
719 (unsigned int) ELF_R_TYPE (info));
728 /* Deal with relocation information. This function relocates addresses
729 within the virtual address space starting from 0. So only relative
730 addresses can be fully resolved. Absolute addresses must be relocated
731 again by a PE32 relocator when loaded. */
733 SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
734 char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
735 const struct grub_install_image_target_desc *image_target)
740 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
741 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
742 unsigned unmatched_adr_got_page = 0;
743 #define MASK19 ((1 << 19) - 1)
745 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
748 for (i = 0, s = smd->sections;
749 i < smd->num_sections;
750 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
751 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
752 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
755 Elf_Word rtab_size, r_size, num_rs;
757 Elf_Word target_section_index;
758 Elf_Addr target_section_addr;
759 Elf_Shdr *target_section;
762 target_section_index = grub_target_to_host32 (s->sh_info);
763 target_section_addr = smd->addrs[target_section_index];
764 target_section = (Elf_Shdr *) ((char *) smd->sections
765 + (target_section_index
766 * smd->section_entsize));
768 grub_util_info ("dealing with the relocation section %s for %s",
769 smd->strtab + grub_target_to_host32 (s->sh_name),
770 smd->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, smd->symtab,
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 (smd->symtab->sh_offset)
923 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->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 (smd->symtab->sh_offset)
1109 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->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 struct section_metadata *smd,
1648 const struct grub_install_image_target_desc *image_target)
1652 struct translate_context ctx;
1654 translate_reloc_start (&ctx, image_target);
1656 for (i = 0, s = smd->sections; i < smd->num_sections;
1657 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1658 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1659 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
1662 Elf_Word rtab_size, r_size, num_rs;
1663 Elf_Off rtab_offset;
1664 Elf_Addr section_address;
1667 grub_util_info ("translating the relocation section %s",
1668 smd->strtab + grub_le_to_cpu32 (s->sh_name));
1670 rtab_size = grub_target_to_host (s->sh_size);
1671 r_size = grub_target_to_host (s->sh_entsize);
1672 rtab_offset = grub_target_to_host (s->sh_offset);
1673 num_rs = rtab_size / r_size;
1675 section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
1677 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1679 j++, r = (Elf_Rel *) ((char *) r + r_size))
1685 offset = grub_target_to_host (r->r_offset);
1686 info = grub_target_to_host (r->r_info);
1688 addr = section_address + offset;
1690 translate_relocation (&ctx, addr, info, image_target);
1694 if (image_target->elf_target == EM_IA_64)
1695 create_u64_fixups (&ctx,
1697 + image_target->vaddr_offset,
1698 2 * layout->ia64jmpnum,
1700 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
1701 create_u64_fixups (&ctx,
1703 + image_target->vaddr_offset,
1704 (layout->got_size / 8),
1707 finish_reloc_translation (&ctx, layout, image_target);
1710 /* Determine if this section is a text section. Return false if this
1711 section is not allocated. */
1713 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1715 if (!is_relocatable (image_target)
1716 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1718 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1719 == (SHF_EXECINSTR | SHF_ALLOC));
1722 /* Determine if this section is a data section. */
1724 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1726 if (!is_relocatable (image_target)
1727 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1729 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1730 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1734 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1736 if (!is_relocatable (image_target))
1738 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1739 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1742 /* Return if the ELF header is valid. */
1744 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
1746 if (size < sizeof (*e)
1747 || e->e_ident[EI_MAG0] != ELFMAG0
1748 || e->e_ident[EI_MAG1] != ELFMAG1
1749 || e->e_ident[EI_MAG2] != ELFMAG2
1750 || e->e_ident[EI_MAG3] != ELFMAG3
1751 || e->e_ident[EI_VERSION] != EV_CURRENT
1752 || e->e_ident[EI_CLASS] != ELFCLASSXX
1753 || e->e_version != grub_host_to_target32 (EV_CURRENT))
1760 SUFFIX (put_section) (Elf_Shdr *s, int i,
1761 Elf_Addr current_address,
1762 struct section_metadata *smd,
1763 const struct grub_install_image_target_desc *image_target)
1765 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
1766 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
1769 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1771 - image_target->vaddr_offset;
1773 grub_util_info ("locating the section %s at 0x%"
1774 GRUB_HOST_PRIxLONG_LONG,
1775 name, (unsigned long long) current_address);
1776 if (!is_relocatable (image_target))
1777 current_address = grub_host_to_target_addr (s->sh_addr)
1778 - image_target->link_addr;
1779 smd->addrs[i] = current_address;
1780 current_address += grub_host_to_target_addr (s->sh_size);
1781 return current_address;
1785 * Locate section addresses by merging code sections and data sections
1786 * into .text and .data, respectively.
1789 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
1790 struct section_metadata *smd,
1791 struct grub_mkimage_layout *layout,
1792 const struct grub_install_image_target_desc *image_target)
1798 /* Page-aligning simplifies relocation handling. */
1799 if (image_target->elf_target == EM_AARCH64)
1800 layout->align = 4096;
1802 layout->kernel_size = 0;
1804 for (i = 0, s = smd->sections;
1805 i < smd->num_sections;
1806 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1807 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
1808 && grub_host_to_target32 (s->sh_addralign) > layout->align)
1809 layout->align = grub_host_to_target32 (s->sh_addralign);
1812 for (i = 0, s = smd->sections;
1813 i < smd->num_sections;
1814 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1815 if (SUFFIX (is_text_section) (s, image_target))
1817 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
1819 if (!is_relocatable (image_target) &&
1820 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
1823 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
1824 " instead of 0x%llx: ld.gold bug?"),
1826 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
1827 (unsigned long long) image_target->link_addr);
1828 grub_util_error ("%s", msg);
1832 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1833 image_target->section_align)
1834 - image_target->vaddr_offset;
1835 layout->exec_size = layout->kernel_size;
1838 for (i = 0, s = smd->sections;
1839 i < smd->num_sections;
1840 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1841 if (SUFFIX (is_data_section) (s, image_target))
1842 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
1845 #ifdef MKIMAGE_ELF32
1846 if (image_target->elf_target == EM_ARM)
1849 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1850 image_target->section_align) - image_target->vaddr_offset;
1852 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
1854 tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
1855 smd->num_sections, image_target);
1857 layout->tramp_off = layout->kernel_size;
1858 layout->kernel_size += ALIGN_UP (tramp, 16);
1862 layout->bss_start = layout->kernel_size;
1863 layout->end = layout->kernel_size;
1866 for (i = 0, s = smd->sections;
1867 i < smd->num_sections;
1868 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1870 if (SUFFIX (is_bss_section) (s, image_target))
1871 layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
1874 * This must to be in the last time this function passes through the loop.
1876 smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
1879 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
1880 image_target->section_align) - image_target->vaddr_offset;
1881 /* Explicitly initialize BSS
1882 when producing PE32 to avoid a bug in EFI implementations.
1883 Platforms other than EFI and U-boot shouldn't have .bss in
1884 their binaries as we build with -Wl,-Ttext.
1886 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
1887 layout->kernel_size = layout->end;
1891 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
1892 size_t total_module_size,
1893 struct grub_mkimage_layout *layout,
1894 const struct grub_install_image_target_desc *image_target)
1896 char *kernel_img, *out_img;
1897 struct section_metadata smd = { 0, };
1901 Elf_Off section_offset;
1902 grub_size_t kernel_size;
1904 grub_memset (layout, 0, sizeof (*layout));
1906 layout->start_address = 0;
1908 kernel_size = grub_util_get_image_size (kernel_path);
1909 kernel_img = xmalloc (kernel_size);
1910 grub_util_load_image (kernel_path, kernel_img);
1912 e = (Elf_Ehdr *) kernel_img;
1913 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
1914 grub_util_error ("invalid ELF header");
1916 section_offset = grub_target_to_host (e->e_shoff);
1917 smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
1918 smd.num_sections = grub_target_to_host16 (e->e_shnum);
1920 if (kernel_size < section_offset
1921 + (grub_uint32_t) smd.section_entsize * smd.num_sections)
1922 grub_util_error (_("premature end of file %s"), kernel_path);
1924 smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
1926 /* Relocate sections then symbols in the virtual address space. */
1927 s = (Elf_Shdr *) ((char *) smd.sections
1928 + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
1929 smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
1931 smd.addrs = xmalloc (sizeof (*smd.addrs) * smd.num_sections);
1932 memset (smd.addrs, 0, sizeof (*smd.addrs) * smd.num_sections);
1933 smd.vaddrs = xmalloc (sizeof (*smd.vaddrs) * smd.num_sections);
1934 memset (smd.vaddrs, 0, sizeof (*smd.vaddrs) * smd.num_sections);
1936 SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
1938 if (!is_relocatable (image_target))
1940 Elf_Addr current_address = layout->kernel_size;
1942 for (i = 0, s = smd.sections;
1943 i < smd.num_sections;
1944 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
1945 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1947 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
1948 const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
1951 current_address = ALIGN_UP (current_address
1952 + image_target->vaddr_offset,
1954 - image_target->vaddr_offset;
1956 grub_util_info ("locating the section %s at 0x%"
1957 GRUB_HOST_PRIxLONG_LONG,
1958 name, (unsigned long long) current_address);
1959 if (!is_relocatable (image_target))
1960 current_address = grub_host_to_target_addr (s->sh_addr)
1961 - image_target->link_addr;
1963 smd.vaddrs[i] = current_address
1964 + image_target->vaddr_offset;
1965 current_address += grub_host_to_target_addr (s->sh_size);
1967 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1968 image_target->section_align)
1969 - image_target->vaddr_offset;
1970 layout->bss_size = current_address - layout->kernel_size;
1973 layout->bss_size = 0;
1975 if (image_target->id == IMAGE_SPARC64_AOUT
1976 || image_target->id == IMAGE_SPARC64_RAW
1977 || image_target->id == IMAGE_UBOOT
1978 || image_target->id == IMAGE_COREBOOT
1979 || image_target->id == IMAGE_SPARC64_CDCORE)
1980 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
1982 if (is_relocatable (image_target))
1985 for (i = 0, s = smd.sections;
1986 i < smd.num_sections;
1987 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
1988 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
1994 grub_util_error ("%s", _("no symbol table"));
1995 #ifdef MKIMAGE_ELF64
1996 if (image_target->elf_target == EM_IA_64)
2000 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2002 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2004 layout->tramp_off = layout->kernel_size;
2005 layout->kernel_size += ALIGN_UP (tramp, 16);
2007 layout->ia64jmp_off = layout->kernel_size;
2008 layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
2010 layout->kernel_size += 16 * layout->ia64jmpnum;
2012 layout->got_off = layout->kernel_size;
2013 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2015 if (image_target->elf_target == EM_AARCH64)
2019 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2021 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2023 layout->got_off = layout->kernel_size;
2024 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2030 layout->reloc_size = 0;
2031 layout->reloc_section = NULL;
2034 out_img = xmalloc (layout->kernel_size + total_module_size);
2035 memset (out_img, 0, layout->kernel_size + total_module_size);
2037 if (is_relocatable (image_target))
2039 layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
2040 (char *) out_img + layout->ia64jmp_off,
2041 layout->ia64jmp_off + image_target->vaddr_offset,
2042 layout->bss_start, layout->end, image_target);
2044 if (layout->start_address == (Elf_Addr) -1)
2045 grub_util_error ("start symbol is not defined");
2047 /* Resolve addrs in the virtual address space. */
2048 SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
2049 layout->got_off, image_target);
2051 make_reloc_section (e, layout, &smd, image_target);
2052 if (image_target->id != IMAGE_EFI)
2054 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2055 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2056 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2057 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2058 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2059 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2063 for (i = 0, s = smd.sections;
2064 i < smd.num_sections;
2065 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2066 if (SUFFIX (is_data_section) (s, image_target)
2067 /* Explicitly initialize BSS
2068 when producing PE32 to avoid a bug in EFI implementations.
2069 Platforms other than EFI and U-boot shouldn't have .bss in
2070 their binaries as we build with -Wl,-Ttext.
2072 || (SUFFIX (is_bss_section) (s, image_target) && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2073 || SUFFIX (is_text_section) (s, image_target))
2075 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2076 memset (out_img + smd.addrs[i], 0,
2077 grub_host_to_target_addr (s->sh_size));
2079 memcpy (out_img + smd.addrs[i],
2080 kernel_img + grub_host_to_target_addr (s->sh_offset),
2081 grub_host_to_target_addr (s->sh_size));