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 /* These structures are defined according to the CHRP binding to IEEE1275,
54 "Client Program Format" section. */
56 struct grub_ieee1275_note_desc
58 grub_uint32_t real_mode;
59 grub_uint32_t real_base;
60 grub_uint32_t real_size;
61 grub_uint32_t virt_base;
62 grub_uint32_t virt_size;
63 grub_uint32_t load_base;
66 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
67 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
69 struct grub_ieee1275_note
72 char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
73 struct grub_ieee1275_note_desc descriptor;
76 #define GRUB_XEN_NOTE_NAME "Xen"
78 struct fixup_block_list
80 struct fixup_block_list *next;
82 struct grub_pe32_fixup_block b;
85 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
88 is_relocatable (const struct grub_install_image_target_desc *image_target)
90 return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
91 || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
97 * R_ARM_THM_CALL/THM_JUMP24
99 * Relocate Thumb (T32) instruction set relative branches:
103 grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
107 offset = grub_arm_thm_call_get_offset (target);
109 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
113 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
114 target, sym_addr, offset);
116 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
117 is bigger than 2M (currently under 150K) then we probably have a problem
119 if (offset < -0x200000 || offset >= 0x200000)
120 return grub_error (GRUB_ERR_BAD_MODULE,
121 "THM_CALL Relocation out of range.");
123 grub_dprintf ("dl", " relative destination = %p",
124 (char *) target + offset);
126 return grub_arm_thm_call_set_offset (target, offset);
132 * Relocate conditional Thumb (T32) B<c>.W
135 grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
140 return grub_error (GRUB_ERR_BAD_MODULE,
141 "Relocation targeting wrong execution state");
143 offset = grub_arm_thm_jump19_get_offset (target);
145 /* Adjust and re-truncate offset */
148 if (!grub_arm_thm_jump19_check_offset (offset))
149 return grub_error (GRUB_ERR_BAD_MODULE,
150 "THM_JUMP19 Relocation out of range.");
152 grub_arm_thm_jump19_set_offset (target, offset);
154 return GRUB_ERR_NONE;
160 * Relocate ARM (A32) B
163 grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
168 return grub_error (GRUB_ERR_BAD_MODULE,
169 "Relocation targeting wrong execution state");
171 offset = grub_arm_jump24_get_offset (target);
174 if (!grub_arm_jump24_check_offset (offset))
175 return grub_error (GRUB_ERR_BAD_MODULE,
176 "JUMP24 Relocation out of range.");
179 grub_arm_jump24_set_offset (target, offset);
181 return GRUB_ERR_NONE;
187 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
188 int note, char **core_img, size_t *core_size,
189 Elf_Addr target_addr,
190 struct grub_mkimage_layout *layout)
197 int header_size, footer_size = 0;
200 int string_size = sizeof (".text") + sizeof ("mods") + 1;
202 if (image_target->id != IMAGE_LOONGSON_ELF)
208 footer_size += sizeof (struct grub_ieee1275_note);
210 if (image_target->id == IMAGE_XEN)
214 string_size += sizeof (".xen");
215 footer_size += XEN_NOTE_SIZE;
217 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
218 + shnum * sizeof (*shdr) + string_size, layout->align);
220 program_size = ALIGN_ADDR (*core_size);
222 elf_img = xmalloc (program_size + header_size + footer_size);
223 memset (elf_img, 0, program_size + header_size + footer_size);
224 memcpy (elf_img + header_size, *core_img, *core_size);
225 ehdr = (void *) elf_img;
226 phdr = (void *) (elf_img + sizeof (*ehdr));
227 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
228 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
229 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
230 if (!image_target->bigendian)
231 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
233 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
234 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
235 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
236 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
237 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
238 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
240 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
241 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
242 ehdr->e_phnum = grub_host_to_target16 (phnum);
244 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
245 - (grub_uint8_t *) ehdr);
246 if (image_target->id == IMAGE_LOONGSON_ELF)
247 ehdr->e_shentsize = grub_host_to_target16 (0);
249 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
250 ehdr->e_shnum = grub_host_to_target16 (shnum);
251 ehdr->e_shstrndx = grub_host_to_target16 (1);
253 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
255 phdr->p_type = grub_host_to_target32 (PT_LOAD);
256 phdr->p_offset = grub_host_to_target32 (header_size);
257 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
259 ehdr->e_entry = grub_host_to_target32 (target_addr);
260 phdr->p_vaddr = grub_host_to_target32 (target_addr);
261 phdr->p_paddr = grub_host_to_target32 (target_addr);
262 phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
263 layout->align : image_target->link_align);
264 if (image_target->id == IMAGE_LOONGSON_ELF)
265 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
266 | EF_MIPS_PIC | EF_MIPS_CPIC);
269 if (image_target->id == IMAGE_LOONGSON_ELF)
271 phdr->p_filesz = grub_host_to_target32 (*core_size);
272 phdr->p_memsz = grub_host_to_target32 (*core_size);
276 grub_uint32_t target_addr_mods;
277 phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
278 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
279 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
281 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
284 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
285 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
286 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
287 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
288 phdr->p_align = grub_host_to_target32 (image_target->link_align);
291 phdr->p_type = grub_host_to_target32 (PT_LOAD);
292 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
293 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
294 phdr->p_filesz = phdr->p_memsz
295 = grub_host_to_target32 (*core_size - layout->kernel_size);
297 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
298 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
299 else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
300 target_addr_mods = ALIGN_UP (target_addr + layout->end
301 + image_target->mod_gap,
302 image_target->mod_align);
304 target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
305 + image_target->mod_gap,
306 image_target->mod_align);
307 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
308 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
309 phdr->p_align = grub_host_to_target32 (image_target->link_align);
312 if (image_target->id == IMAGE_XEN)
314 char *note_start = (elf_img + program_size + header_size);
316 char *ptr = (char *) note_start;
318 grub_util_info ("adding XEN NOTE segment");
321 note_ptr = (Elf_Nhdr *) ptr;
322 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
323 note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
324 note_ptr->n_type = grub_host_to_target32 (6);
325 ptr += sizeof (Elf_Nhdr);
326 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
327 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
328 memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
329 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
332 note_ptr = (Elf_Nhdr *) ptr;
333 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
334 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
335 note_ptr->n_type = grub_host_to_target32 (8);
336 ptr += sizeof (Elf_Nhdr);
337 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
338 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
339 memcpy (ptr, "generic", sizeof ("generic"));
340 ptr += ALIGN_UP (sizeof ("generic"), 4);
343 note_ptr = (Elf_Nhdr *) ptr;
344 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
345 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
346 note_ptr->n_type = grub_host_to_target32 (5);
347 ptr += sizeof (Elf_Nhdr);
348 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
349 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
350 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
351 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
354 note_ptr = (Elf_Nhdr *) ptr;
355 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
356 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
357 note_ptr->n_type = grub_host_to_target32 (1);
358 ptr += sizeof (Elf_Nhdr);
359 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
360 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
361 memset (ptr, 0, image_target->voidp_sizeof);
362 ptr += image_target->voidp_sizeof;
365 note_ptr = (Elf_Nhdr *) ptr;
366 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
367 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
368 note_ptr->n_type = grub_host_to_target32 (3);
369 ptr += sizeof (Elf_Nhdr);
370 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
371 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
372 memset (ptr, 0, image_target->voidp_sizeof);
373 ptr += image_target->voidp_sizeof;
376 if (image_target->elf_target == EM_386)
378 note_ptr = (Elf_Nhdr *) ptr;
379 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
380 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
381 note_ptr->n_type = grub_host_to_target32 (9);
382 ptr += sizeof (Elf_Nhdr);
383 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
384 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
385 memcpy (ptr, "yes", sizeof ("yes"));
386 ptr += ALIGN_UP (sizeof ("yes"), 4);
389 assert (XEN_NOTE_SIZE == (ptr - note_start));
392 phdr->p_type = grub_host_to_target32 (PT_NOTE);
393 phdr->p_flags = grub_host_to_target32 (PF_R);
394 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
397 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
399 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
404 int note_size = sizeof (struct grub_ieee1275_note);
405 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
406 (elf_img + program_size + header_size);
408 grub_util_info ("adding CHRP NOTE segment");
410 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
411 note_ptr->header.n_descsz = grub_host_to_target32 (note_size);
412 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
413 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
414 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
415 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
416 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
417 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
418 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
419 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
422 phdr->p_type = grub_host_to_target32 (PT_NOTE);
423 phdr->p_flags = grub_host_to_target32 (PF_R);
424 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
427 phdr->p_filesz = grub_host_to_target32 (note_size);
429 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
433 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
434 + shnum * sizeof (*shdr));
435 char *ptr = str_start + 1;
439 shdr->sh_name = grub_host_to_target32 (0);
440 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
441 shdr->sh_addr = grub_host_to_target_addr (0);
442 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
443 shdr->sh_size = grub_host_to_target32 (string_size);
444 shdr->sh_link = grub_host_to_target32 (0);
445 shdr->sh_info = grub_host_to_target32 (0);
446 shdr->sh_addralign = grub_host_to_target32 (layout->align);
447 shdr->sh_entsize = grub_host_to_target32 (0);
450 memcpy (ptr, ".text", sizeof (".text"));
452 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
453 ptr += sizeof (".text");
454 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
455 shdr->sh_addr = grub_host_to_target_addr (target_addr);
456 shdr->sh_offset = grub_host_to_target_addr (header_size);
457 shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
458 shdr->sh_link = grub_host_to_target32 (0);
459 shdr->sh_info = grub_host_to_target32 (0);
460 shdr->sh_addralign = grub_host_to_target32 (layout->align);
461 shdr->sh_entsize = grub_host_to_target32 (0);
464 memcpy (ptr, "mods", sizeof ("mods"));
465 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
466 ptr += sizeof ("mods");
467 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
468 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
469 shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
470 shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
471 shdr->sh_link = grub_host_to_target32 (0);
472 shdr->sh_info = grub_host_to_target32 (0);
473 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
474 shdr->sh_entsize = grub_host_to_target32 (0);
477 if (image_target->id == IMAGE_XEN)
479 memcpy (ptr, ".xen", sizeof (".xen"));
480 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
481 ptr += sizeof (".xen");
482 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
483 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
484 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
485 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
486 shdr->sh_link = grub_host_to_target32 (0);
487 shdr->sh_info = grub_host_to_target32 (0);
488 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
489 shdr->sh_entsize = grub_host_to_target32 (0);
496 *core_size = program_size + header_size + footer_size;
499 /* Relocate symbols; note that this function overwrites the symbol table.
500 Return the address of a start symbol. */
502 SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
503 Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
504 Elf_Half section_entsize, Elf_Half num_sections,
505 void *jumpers, Elf_Addr jumpers_addr,
506 Elf_Addr bss_start, Elf_Addr end,
507 const struct grub_install_image_target_desc *image_target)
509 Elf_Word symtab_size, sym_size, num_syms;
510 Elf_Off symtab_offset;
511 Elf_Addr start_address = (Elf_Addr) -1;
514 Elf_Shdr *strtab_section;
516 grub_uint64_t *jptr = jumpers;
519 = (Elf_Shdr *) ((char *) sections
520 + (grub_target_to_host32 (symtab_section->sh_link)
522 strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);
524 symtab_size = grub_target_to_host (symtab_section->sh_size);
525 sym_size = grub_target_to_host (symtab_section->sh_entsize);
526 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
527 num_syms = symtab_size / sym_size;
529 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
531 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
533 Elf_Section cur_index;
536 name = strtab + grub_target_to_host32 (sym->st_name);
538 cur_index = grub_target_to_host16 (sym->st_shndx);
539 if (cur_index == STN_ABS)
543 else if (cur_index == STN_UNDEF)
545 if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
546 sym->st_value = bss_start;
547 else if (sym->st_name && grub_strcmp (name, "_end") == 0)
549 else if (sym->st_name)
550 grub_util_error ("undefined symbol %s", name);
554 else if (cur_index >= num_sections)
555 grub_util_error ("section %d does not exist", cur_index);
558 sym->st_value = (grub_target_to_host (sym->st_value)
559 + section_addresses[cur_index]);
562 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
565 *jptr = grub_host_to_target64 (sym->st_value);
566 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
571 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
572 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
573 (unsigned long long) sym->st_value,
574 (unsigned long long) section_addresses[cur_index]);
576 if (start_address == (Elf_Addr)-1)
577 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
578 start_address = sym->st_value;
581 return start_address;
584 /* Return the address of a symbol at the index I in the section S. */
586 SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
587 const struct grub_install_image_target_desc *image_target)
591 sym = (Elf_Sym *) ((char *) e
592 + grub_target_to_host (s->sh_offset)
593 + i * grub_target_to_host (s->sh_entsize));
594 return sym->st_value;
597 /* Return the address of a modified value. */
599 SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
600 const struct grub_install_image_target_desc *image_target)
602 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
607 SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
608 const struct grub_install_image_target_desc *image_target)
610 Elf_Word symtab_size, sym_size, num_syms;
611 Elf_Off symtab_offset;
616 symtab_size = grub_target_to_host (symtab_section->sh_size);
617 sym_size = grub_target_to_host (symtab_section->sh_entsize);
618 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
619 num_syms = symtab_size / sym_size;
621 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
623 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
624 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
632 /* Deal with relocation information. This function relocates addresses
633 within the virtual address space starting from 0. So only relative
634 addresses can be fully resolved. Absolute addresses must be relocated
635 again by a PE32 relocator when loaded. */
637 arm_get_trampoline_size (Elf_Ehdr *e,
639 Elf_Half section_entsize,
640 Elf_Half num_sections,
641 const struct grub_install_image_target_desc *image_target)
647 for (i = 0, s = sections;
649 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
650 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
651 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
654 Elf_Word rtab_size, r_size, num_rs;
656 Elf_Shdr *symtab_section;
659 symtab_section = (Elf_Shdr *) ((char *) sections
660 + (grub_target_to_host32 (s->sh_link)
663 rtab_size = grub_target_to_host (s->sh_size);
664 r_size = grub_target_to_host (s->sh_entsize);
665 rtab_offset = grub_target_to_host (s->sh_offset);
666 num_rs = rtab_size / r_size;
668 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
670 j++, r = (Elf_Rela *) ((char *) r + r_size))
675 info = grub_target_to_host (r->r_info);
676 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
677 ELF_R_SYM (info), image_target);
679 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
680 grub_target_to_host (r->r_addend) : 0;
682 switch (ELF_R_TYPE (info))
688 case R_ARM_THM_JUMP24:
689 case R_ARM_THM_JUMP19:
701 grub_util_error (_("relocation 0x%x is not implemented yet"),
702 (unsigned int) ELF_R_TYPE (info));
711 /* Deal with relocation information. This function relocates addresses
712 within the virtual address space starting from 0. So only relative
713 addresses can be fully resolved. Absolute addresses must be relocated
714 again by a PE32 relocator when loaded. */
716 SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
717 Elf_Addr *section_addresses,
718 Elf_Half section_entsize, Elf_Half num_sections,
720 char *pe_target, Elf_Addr tramp_off,
722 const struct grub_install_image_target_desc *image_target)
727 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
728 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
729 unsigned unmatched_adr_got_page = 0;
730 #define MASK19 ((1 << 19) - 1)
732 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
735 for (i = 0, s = sections;
737 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
738 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
739 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
742 Elf_Word rtab_size, r_size, num_rs;
744 Elf_Shdr *symtab_section;
745 Elf_Word target_section_index;
746 Elf_Addr target_section_addr;
747 Elf_Shdr *target_section;
750 symtab_section = (Elf_Shdr *) ((char *) sections
751 + (grub_target_to_host32 (s->sh_link)
753 target_section_index = grub_target_to_host32 (s->sh_info);
754 target_section_addr = section_addresses[target_section_index];
755 target_section = (Elf_Shdr *) ((char *) sections
756 + (target_section_index
759 grub_util_info ("dealing with the relocation section %s for %s",
760 strtab + grub_target_to_host32 (s->sh_name),
761 strtab + grub_target_to_host32 (target_section->sh_name));
763 rtab_size = grub_target_to_host (s->sh_size);
764 r_size = grub_target_to_host (s->sh_entsize);
765 rtab_offset = grub_target_to_host (s->sh_offset);
766 num_rs = rtab_size / r_size;
768 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
770 j++, r = (Elf_Rela *) ((char *) r + r_size))
778 offset = grub_target_to_host (r->r_offset);
779 target = SUFFIX (get_target_address) (e, target_section,
780 offset, image_target);
781 info = grub_target_to_host (r->r_info);
782 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
783 ELF_R_SYM (info), image_target);
785 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
786 grub_target_to_host (r->r_addend) : 0;
788 switch (image_target->elf_target)
791 switch (ELF_R_TYPE (info))
797 /* This is absolute. */
798 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
799 + addend + sym_addr);
800 grub_util_info ("relocating an R_386_32 entry to 0x%"
801 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
802 GRUB_HOST_PRIxLONG_LONG,
803 (unsigned long long) *target,
804 (unsigned long long) offset);
808 /* This is relative. */
809 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
811 - target_section_addr - offset
812 - image_target->vaddr_offset);
813 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
814 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
815 GRUB_HOST_PRIxLONG_LONG,
816 (unsigned long long) *target,
817 (unsigned long long) offset);
820 grub_util_error (_("relocation 0x%x is not implemented yet"),
821 (unsigned int) ELF_R_TYPE (info));
827 switch (ELF_R_TYPE (info))
834 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
835 + addend + sym_addr);
836 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
837 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
838 GRUB_HOST_PRIxLONG_LONG,
839 (unsigned long long) *target,
840 (unsigned long long) offset);
845 grub_uint32_t *t32 = (grub_uint32_t *) target;
846 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
848 - target_section_addr - offset
849 - image_target->vaddr_offset);
850 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
851 GRUB_HOST_PRIxLONG_LONG,
852 *t32, (unsigned long long) offset);
858 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
860 - target_section_addr - offset
861 - image_target->vaddr_offset);
862 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
863 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
864 GRUB_HOST_PRIxLONG_LONG,
865 (unsigned long long) *target,
866 (unsigned long long) offset);
873 grub_uint32_t *t32 = (grub_uint32_t *) target;
874 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
875 + addend + sym_addr);
876 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
877 GRUB_HOST_PRIxLONG_LONG,
878 *t32, (unsigned long long) offset);
883 grub_util_error (_("relocation 0x%x is not implemented yet"),
884 (unsigned int) ELF_R_TYPE (info));
889 switch (ELF_R_TYPE (info))
891 case R_IA64_PCREL21B:
894 grub_ia64_make_trampoline (tr, addend + sym_addr);
895 noff = ((char *) tr - (char *) pe_target
896 - target_section_addr - (offset & ~3)) >> 4;
899 grub_util_error ("trampoline offset too big (%"
900 GRUB_HOST_PRIxLONG_LONG ")",
901 (unsigned long long) noff);
902 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
906 case R_IA64_LTOFF22X:
911 sym = (Elf_Sym *) ((char *) e
912 + grub_target_to_host (symtab_section->sh_offset)
913 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
914 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
915 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
917 - image_target->vaddr_offset));
920 case R_IA64_LTOFF_FPTR22:
921 *gpptr = grub_host_to_target64 (addend + sym_addr);
922 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
923 (char *) gpptr - (char *) pe_target
924 + image_target->vaddr_offset);
929 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
932 case R_IA64_GPREL64I:
933 grub_ia64_set_immu64 ((grub_addr_t) target,
936 case R_IA64_PCREL64LSB:
937 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
939 - target_section_addr - offset
940 - image_target->vaddr_offset);
943 case R_IA64_SEGREL64LSB:
944 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
945 + addend + sym_addr - target_section_addr);
947 case R_IA64_DIR64LSB:
948 case R_IA64_FPTR64LSB:
949 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
950 + addend + sym_addr);
951 grub_util_info ("relocating a direct entry to 0x%"
952 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
953 GRUB_HOST_PRIxLONG_LONG,
955 grub_target_to_host64 (*target),
956 (unsigned long long) offset);
959 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
964 grub_util_error (_("relocation 0x%x is not implemented yet"),
965 (unsigned int) ELF_R_TYPE (info));
972 switch (ELF_R_TYPE (info))
974 case R_AARCH64_ABS64:
976 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
979 case R_AARCH64_PREL32:
981 grub_uint32_t *t32 = (grub_uint32_t *) target;
982 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
984 - target_section_addr - offset
985 - image_target->vaddr_offset);
986 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
987 GRUB_HOST_PRIxLONG_LONG,
988 *t32, (unsigned long long) offset);
991 case R_AARCH64_ADD_ABS_LO12_NC:
992 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
995 case R_AARCH64_LDST64_ABS_LO12_NC:
996 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
999 case R_AARCH64_JUMP26:
1000 case R_AARCH64_CALL26:
1003 sym_addr -= target_section_addr + image_target->vaddr_offset;
1004 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1005 grub_util_error ("%s", "CALL26 Relocation out of range");
1007 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1011 case R_AARCH64_ADR_GOT_PAGE:
1014 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1015 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1017 *gpptr = grub_host_to_target64 (sym_addr);
1018 unmatched_adr_got_page++;
1019 if (!grub_arm64_check_hi21_signed (gpoffset))
1020 grub_util_error ("HI21 out of range");
1021 grub_arm64_set_hi21((grub_uint32_t *)target,
1023 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1025 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1026 if (ELF_R_SYM (rel2->r_info)
1027 == ELF_R_SYM (r->r_info)
1028 && r->r_addend == rel2->r_addend
1029 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1031 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1032 grub_target_to_host (rel2->r_offset), image_target),
1033 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1037 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1041 case R_AARCH64_LD64_GOT_LO12_NC:
1042 if (unmatched_adr_got_page == 0)
1043 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1044 unmatched_adr_got_page--;
1046 case R_AARCH64_ADR_PREL_PG_HI21:
1048 sym_addr &= ~0xfffULL;
1049 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1050 if (!grub_arm64_check_hi21_signed (sym_addr))
1051 grub_util_error ("%s", "CALL26 Relocation out of range");
1053 grub_arm64_set_hi21((grub_uint32_t *)target,
1058 grub_util_error (_("relocation 0x%x is not implemented yet"),
1059 (unsigned int) ELF_R_TYPE (info));
1065 #if defined(MKIMAGE_ELF32)
1069 sym_addr -= image_target->vaddr_offset;
1070 switch (ELF_R_TYPE (info))
1074 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1075 (int) sym_addr, (int) sym_addr);
1076 /* Data will be naturally aligned */
1077 if (image_target->id == IMAGE_EFI)
1079 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1082 /* Happens when compiled with -march=armv4.
1083 Since currently we need at least armv5, keep bx as-is.
1087 case R_ARM_THM_CALL:
1088 case R_ARM_THM_JUMP24:
1089 case R_ARM_THM_JUMP19:
1093 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1094 (unsigned long) ((char *) target
1097 sym = (Elf_Sym *) ((char *) e
1098 + grub_target_to_host (symtab_section->sh_offset)
1099 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
1100 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1102 if (!(sym_addr & 1))
1104 grub_uint32_t tr_addr;
1105 grub_int32_t new_offset;
1106 tr_addr = (char *) tr - (char *) pe_target
1107 - target_section_addr;
1108 new_offset = sym_addr - tr_addr - 12;
1110 if (!grub_arm_jump24_check_offset (new_offset))
1111 return grub_util_error ("jump24 relocation out of range");
1113 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1114 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1116 sym_addr = tr_addr | 1;
1119 /* Thumb instructions can be 16-bit aligned */
1120 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1121 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1123 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1126 grub_util_error ("%s", grub_errmsg);
1134 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1137 grub_uint32_t tr_addr;
1138 grub_int32_t new_offset;
1139 tr_addr = (char *) tr - (char *) pe_target
1140 - target_section_addr;
1141 new_offset = sym_addr - tr_addr - 12;
1143 /* There is no immediate version of bx, only register one... */
1144 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1145 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1146 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1147 tr[3] = grub_host_to_target32 (new_offset | 1);
1152 err = grub_arm_reloc_jump24 (target,
1155 grub_util_error ("%s", grub_errmsg);
1160 grub_util_error (_("relocation 0x%x is not implemented yet"),
1161 (unsigned int) ELF_R_TYPE (info));
1166 #endif /* MKIMAGE_ELF32 */
1168 grub_util_error ("unknown architecture type %d",
1169 image_target->elf_target);
1175 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1176 after having written to the file OUT. */
1178 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1179 Elf_Addr addr, int flush, Elf_Addr current_address,
1180 const struct grub_install_image_target_desc *image_target)
1182 struct grub_pe32_fixup_block *b;
1184 b = &((*cblock)->b);
1186 /* First, check if it is necessary to write out the current block. */
1187 if ((*cblock)->state)
1189 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
1195 /* Add as much padding as necessary to align the address
1196 with a section boundary. */
1197 Elf_Addr next_address;
1198 unsigned padding_size;
1201 next_address = current_address + b->block_size;
1202 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1205 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1206 grub_util_info ("adding %d padding fixup entries", padding_size);
1207 while (padding_size--)
1209 b->entries[cur_index++] = 0;
1213 else while (b->block_size & (8 - 1))
1215 /* If not aligned with a 32-bit boundary, add
1219 grub_util_info ("adding a padding fixup entry");
1220 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1221 b->entries[cur_index] = 0;
1226 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1227 b->block_size, b->page_rva);
1228 size = b->block_size;
1229 current_address += size;
1230 b->page_rva = grub_host_to_target32 (b->page_rva);
1231 b->block_size = grub_host_to_target32 (b->block_size);
1232 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1233 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1234 *cblock = (*cblock)->next;
1238 b = &((*cblock)->b);
1242 grub_uint16_t entry;
1245 /* If not allocated yet, allocate a block with enough entries. */
1246 if (! (*cblock)->state)
1248 (*cblock)->state = 1;
1250 /* The spec does not mention the requirement of a Page RVA.
1251 Here, align the address with a 4K boundary for safety. */
1252 b->page_rva = (addr & ~(0x1000 - 1));
1253 b->block_size = sizeof (*b);
1257 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1258 grub_util_error ("too many fixup entries");
1260 /* Add a new entry. */
1261 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1262 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
1263 b->entries[cur_index] = grub_host_to_target16 (entry);
1267 return current_address;
1272 struct raw_reloc *next;
1273 grub_uint32_t offset;
1274 enum raw_reloc_type {
1275 RAW_RELOC_NONE = -1,
1281 struct translate_context
1284 struct fixup_block_list *lst, *lst0;
1285 Elf_Addr current_address;
1288 struct raw_reloc *raw_relocs;
1292 translate_reloc_start (struct translate_context *ctx,
1293 const struct grub_install_image_target_desc *image_target)
1295 grub_memset (ctx, 0, sizeof (*ctx));
1296 if (image_target->id == IMAGE_EFI)
1298 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1299 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1300 ctx->current_address = 0;
1305 translate_relocation_pe (struct translate_context *ctx,
1308 const struct grub_install_image_target_desc *image_target)
1310 /* Necessary to relocate only absolute addresses. */
1311 switch (image_target->elf_target)
1314 if (ELF_R_TYPE (info) == R_386_32)
1316 grub_util_info ("adding a relocation entry for 0x%"
1317 GRUB_HOST_PRIxLONG_LONG,
1318 (unsigned long long) addr);
1319 ctx->current_address
1320 = add_fixup_entry (&ctx->lst,
1321 GRUB_PE32_REL_BASED_HIGHLOW,
1322 addr, 0, ctx->current_address,
1327 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1328 (ELF_R_TYPE (info) == R_X86_64_32S))
1330 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1332 else if (ELF_R_TYPE (info) == R_X86_64_64)
1334 grub_util_info ("adding a relocation entry for 0x%"
1335 GRUB_HOST_PRIxLONG_LONG,
1336 (unsigned long long) addr);
1337 ctx->current_address
1338 = add_fixup_entry (&ctx->lst,
1339 GRUB_PE32_REL_BASED_DIR64,
1341 0, ctx->current_address,
1346 switch (ELF_R_TYPE (info))
1348 case R_IA64_PCREL64LSB:
1350 case R_IA64_PCREL21B:
1351 case R_IA64_LTOFF_FPTR22:
1352 case R_IA64_LTOFF22X:
1353 case R_IA64_LTOFF22:
1354 case R_IA64_GPREL22:
1355 case R_IA64_GPREL64I:
1356 case R_IA64_SEGREL64LSB:
1359 case R_IA64_FPTR64LSB:
1360 case R_IA64_DIR64LSB:
1363 grub_util_info ("adding a relocation entry for 0x%"
1364 GRUB_HOST_PRIxLONG_LONG,
1365 (unsigned long long) addr);
1366 ctx->current_address
1367 = add_fixup_entry (&ctx->lst,
1368 GRUB_PE32_REL_BASED_DIR64,
1370 0, ctx->current_address,
1376 grub_util_error (_("relocation 0x%x is not implemented yet"),
1377 (unsigned int) ELF_R_TYPE (info));
1382 switch (ELF_R_TYPE (info))
1384 case R_AARCH64_ABS64:
1386 ctx->current_address
1387 = add_fixup_entry (&ctx->lst,
1388 GRUB_PE32_REL_BASED_DIR64,
1389 addr, 0, ctx->current_address,
1393 /* Relative relocations do not require fixup entries. */
1394 case R_AARCH64_CALL26:
1395 case R_AARCH64_JUMP26:
1396 case R_AARCH64_PREL32:
1398 /* Page-relative relocations do not require fixup entries. */
1399 case R_AARCH64_ADR_PREL_PG_HI21:
1400 /* We page-align the whole kernel, so no need
1403 case R_AARCH64_ADD_ABS_LO12_NC:
1404 case R_AARCH64_LDST64_ABS_LO12_NC:
1407 /* GOT is relocated separately. */
1408 case R_AARCH64_ADR_GOT_PAGE:
1409 case R_AARCH64_LD64_GOT_LO12_NC:
1413 grub_util_error (_("relocation 0x%x is not implemented yet"),
1414 (unsigned int) ELF_R_TYPE (info));
1419 #if defined(MKIMAGE_ELF32)
1421 switch (ELF_R_TYPE (info))
1424 /* Relative relocations do not require fixup entries. */
1426 case R_ARM_THM_CALL:
1427 case R_ARM_THM_JUMP19:
1428 case R_ARM_THM_JUMP24:
1431 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1434 /* Create fixup entry for PE/COFF loader */
1437 ctx->current_address
1438 = add_fixup_entry (&ctx->lst,
1439 GRUB_PE32_REL_BASED_HIGHLOW,
1440 addr, 0, ctx->current_address,
1445 grub_util_error (_("relocation 0x%x is not implemented yet"),
1446 (unsigned int) ELF_R_TYPE (info));
1450 #endif /* defined(MKIMAGE_ELF32) */
1452 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1456 static enum raw_reloc_type
1457 classify_raw_reloc (Elf_Addr info,
1458 const struct grub_install_image_target_desc *image_target)
1460 /* Necessary to relocate only absolute addresses. */
1461 switch (image_target->elf_target)
1464 switch (ELF_R_TYPE (info))
1468 case R_ARM_THM_CALL:
1469 case R_ARM_THM_JUMP19:
1470 case R_ARM_THM_JUMP24:
1472 return RAW_RELOC_NONE;
1474 return RAW_RELOC_32;
1476 grub_util_error (_("relocation 0x%x is not implemented yet"),
1477 (unsigned int) ELF_R_TYPE (info));
1482 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1487 translate_relocation_raw (struct translate_context *ctx,
1490 const struct grub_install_image_target_desc *image_target)
1492 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
1493 struct raw_reloc *rel;
1494 if (class == RAW_RELOC_NONE)
1496 rel = xmalloc (sizeof (*rel));
1497 rel->next = ctx->raw_relocs;
1500 ctx->raw_relocs = rel;
1504 translate_relocation (struct translate_context *ctx,
1507 const struct grub_install_image_target_desc *image_target)
1509 if (image_target->id == IMAGE_EFI)
1510 translate_relocation_pe (ctx, addr, info, image_target);
1512 translate_relocation_raw (ctx, addr, info, image_target);
1516 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1517 const struct grub_install_image_target_desc *image_target)
1519 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
1523 layout->reloc_section = ptr = xmalloc (ctx->current_address);
1524 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
1525 if (ctx->lst->state)
1527 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
1528 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
1530 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
1533 for (ctx->lst = ctx->lst0; ctx->lst; )
1535 struct fixup_block_list *next;
1536 next = ctx->lst->next;
1541 layout->reloc_size = ctx->current_address;
1542 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
1543 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
1544 "This breaks assembly assumptions. Please increase stack size",
1545 (int) layout->reloc_size,
1546 (int) GRUB_KERNEL_ARM_STACK_SIZE);
1551 <type 0 relocations>
1553 <type 1 relocations>
1556 <type n relocations>
1558 each relocation starts with 32-bit offset. Rest depends on relocation.
1559 mkimage stops when it sees first unknown type or end marker.
1560 This allows images to be created with mismatched mkimage and
1561 kernel as long as no relocations are present in kernel that mkimage
1562 isn't aware of (in which case mkimage aborts).
1563 This also allows simple assembly to do the relocs.
1566 #define RAW_SEPARATOR 0xfffffffe
1567 #define RAW_END_MARKER 0xffffffff
1570 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1571 const struct grub_install_image_target_desc *image_target)
1573 size_t count = 0, sz;
1574 enum raw_reloc_type highest = RAW_RELOC_NONE;
1575 enum raw_reloc_type curtype;
1576 struct raw_reloc *cur;
1578 if (!ctx->raw_relocs)
1580 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
1581 p[0] = RAW_END_MARKER;
1582 layout->reloc_size = sizeof (grub_uint32_t);
1585 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1588 if (cur->type > highest)
1589 highest = cur->type;
1591 /* highest separators, count relocations and one end marker. */
1592 sz = (highest + count + 1) * sizeof (grub_uint32_t);
1593 layout->reloc_section = p = xmalloc (sz);
1594 for (curtype = 0; curtype <= highest; curtype++)
1596 /* Support for special cases would go here. */
1597 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1598 if (cur->type == curtype)
1602 *p++ = RAW_SEPARATOR;
1604 *--p = RAW_END_MARKER;
1605 layout->reloc_size = sz;
1609 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1610 const struct grub_install_image_target_desc *image_target)
1612 if (image_target->id == IMAGE_EFI)
1613 finish_reloc_translation_pe (ctx, layout, image_target);
1615 finish_reloc_translation_raw (ctx, layout, image_target);
1620 create_u64_fixups (struct translate_context *ctx,
1621 Elf_Addr jumpers, grub_size_t njumpers,
1622 const struct grub_install_image_target_desc *image_target)
1625 assert (image_target->id == IMAGE_EFI);
1626 for (i = 0; i < njumpers; i++)
1627 ctx->current_address = add_fixup_entry (&ctx->lst,
1628 GRUB_PE32_REL_BASED_DIR64,
1630 0, ctx->current_address,
1634 /* Make a .reloc section. */
1636 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
1637 Elf_Addr *section_addresses, Elf_Shdr *sections,
1638 Elf_Half section_entsize, Elf_Half num_sections,
1640 const struct grub_install_image_target_desc *image_target)
1644 struct translate_context ctx;
1646 translate_reloc_start (&ctx, image_target);
1648 for (i = 0, s = sections; i < num_sections;
1649 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1650 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1651 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
1654 Elf_Word rtab_size, r_size, num_rs;
1655 Elf_Off rtab_offset;
1656 Elf_Addr section_address;
1659 grub_util_info ("translating the relocation section %s",
1660 strtab + grub_le_to_cpu32 (s->sh_name));
1662 rtab_size = grub_target_to_host (s->sh_size);
1663 r_size = grub_target_to_host (s->sh_entsize);
1664 rtab_offset = grub_target_to_host (s->sh_offset);
1665 num_rs = rtab_size / r_size;
1667 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
1669 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1671 j++, r = (Elf_Rel *) ((char *) r + r_size))
1677 offset = grub_target_to_host (r->r_offset);
1678 info = grub_target_to_host (r->r_info);
1680 addr = section_address + offset;
1682 translate_relocation (&ctx, addr, info, image_target);
1686 if (image_target->elf_target == EM_IA_64)
1687 create_u64_fixups (&ctx,
1689 + image_target->vaddr_offset,
1690 2 * layout->ia64jmpnum,
1692 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
1693 create_u64_fixups (&ctx,
1695 + image_target->vaddr_offset,
1696 (layout->got_size / 8),
1699 finish_reloc_translation (&ctx, layout, image_target);
1702 /* Determine if this section is a text section. Return false if this
1703 section is not allocated. */
1705 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1707 if (!is_relocatable (image_target)
1708 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1710 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1711 == (SHF_EXECINSTR | SHF_ALLOC));
1714 /* Determine if this section is a data section. */
1716 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1718 if (!is_relocatable (image_target)
1719 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1721 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1722 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1726 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1728 if (!is_relocatable (image_target))
1730 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1731 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1734 /* Return if the ELF header is valid. */
1736 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
1738 if (size < sizeof (*e)
1739 || e->e_ident[EI_MAG0] != ELFMAG0
1740 || e->e_ident[EI_MAG1] != ELFMAG1
1741 || e->e_ident[EI_MAG2] != ELFMAG2
1742 || e->e_ident[EI_MAG3] != ELFMAG3
1743 || e->e_ident[EI_VERSION] != EV_CURRENT
1744 || e->e_ident[EI_CLASS] != ELFCLASSXX
1745 || e->e_version != grub_host_to_target32 (EV_CURRENT))
1752 SUFFIX (put_section) (Elf_Shdr *s, int i,
1753 Elf_Addr current_address,
1754 Elf_Addr *section_addresses,
1756 const struct grub_install_image_target_desc *image_target)
1758 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
1759 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1762 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1764 - image_target->vaddr_offset;
1766 grub_util_info ("locating the section %s at 0x%"
1767 GRUB_HOST_PRIxLONG_LONG,
1768 name, (unsigned long long) current_address);
1769 if (!is_relocatable (image_target))
1770 current_address = grub_host_to_target_addr (s->sh_addr)
1771 - image_target->link_addr;
1772 section_addresses[i] = current_address;
1773 current_address += grub_host_to_target_addr (s->sh_size);
1774 return current_address;
1777 /* Locate section addresses by merging code sections and data sections
1778 into .text and .data, respectively. Return the array of section
1781 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
1782 Elf_Shdr *sections, Elf_Half section_entsize,
1783 Elf_Half num_sections, const char *strtab,
1784 struct grub_mkimage_layout *layout,
1785 const struct grub_install_image_target_desc *image_target)
1788 Elf_Addr *section_addresses;
1792 /* Page-aligning simplifies relocation handling. */
1793 if (image_target->elf_target == EM_AARCH64)
1794 layout->align = 4096;
1796 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
1797 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
1799 layout->kernel_size = 0;
1801 for (i = 0, s = sections;
1803 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1804 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
1805 && grub_host_to_target32 (s->sh_addralign) > layout->align)
1806 layout->align = grub_host_to_target32 (s->sh_addralign);
1810 for (i = 0, s = sections;
1812 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1813 if (SUFFIX (is_text_section) (s, image_target))
1815 layout->kernel_size = SUFFIX (put_section) (s, i,
1816 layout->kernel_size,
1820 if (!is_relocatable (image_target) &&
1821 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
1824 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
1825 " instead of 0x%llx: ld.gold bug?"),
1827 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
1828 (unsigned long long) image_target->link_addr);
1829 grub_util_error ("%s", msg);
1833 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1834 image_target->section_align)
1835 - image_target->vaddr_offset;
1836 layout->exec_size = layout->kernel_size;
1839 for (i = 0, s = sections;
1841 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1842 if (SUFFIX (is_data_section) (s, image_target))
1843 layout->kernel_size = SUFFIX (put_section) (s, i,
1844 layout->kernel_size,
1849 #ifdef MKIMAGE_ELF32
1850 if (image_target->elf_target == EM_ARM)
1853 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1854 image_target->section_align) - image_target->vaddr_offset;
1856 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
1858 tramp = arm_get_trampoline_size (e, sections, section_entsize,
1859 num_sections, image_target);
1861 layout->tramp_off = layout->kernel_size;
1862 layout->kernel_size += ALIGN_UP (tramp, 16);
1866 layout->bss_start = layout->kernel_size;
1867 layout->end = layout->kernel_size;
1870 for (i = 0, s = sections;
1872 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1873 if (SUFFIX (is_bss_section) (s, image_target))
1874 layout->end = SUFFIX (put_section) (s, i,
1880 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
1881 image_target->section_align) - image_target->vaddr_offset;
1882 /* Explicitly initialize BSS
1883 when producing PE32 to avoid a bug in EFI implementations.
1884 Platforms other than EFI and U-boot shouldn't have .bss in
1885 their binaries as we build with -Wl,-Ttext.
1887 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
1888 layout->kernel_size = layout->end;
1890 return section_addresses;
1894 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
1895 size_t total_module_size,
1896 struct grub_mkimage_layout *layout,
1897 const struct grub_install_image_target_desc *image_target)
1899 char *kernel_img, *out_img;
1903 Elf_Addr *section_addresses;
1904 Elf_Addr *section_vaddresses;
1907 Elf_Half num_sections;
1908 Elf_Off section_offset;
1909 Elf_Half section_entsize;
1910 grub_size_t kernel_size;
1911 Elf_Shdr *symtab_section = 0;
1913 grub_memset (layout, 0, sizeof (*layout));
1915 layout->start_address = 0;
1917 kernel_size = grub_util_get_image_size (kernel_path);
1918 kernel_img = xmalloc (kernel_size);
1919 grub_util_load_image (kernel_path, kernel_img);
1921 e = (Elf_Ehdr *) kernel_img;
1922 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
1923 grub_util_error ("invalid ELF header");
1925 section_offset = grub_target_to_host (e->e_shoff);
1926 section_entsize = grub_target_to_host16 (e->e_shentsize);
1927 num_sections = grub_target_to_host16 (e->e_shnum);
1929 if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections)
1930 grub_util_error (_("premature end of file %s"), kernel_path);
1932 sections = (Elf_Shdr *) (kernel_img + section_offset);
1934 /* Relocate sections then symbols in the virtual address space. */
1935 s = (Elf_Shdr *) ((char *) sections
1936 + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
1937 strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
1939 section_addresses = SUFFIX (locate_sections) (e, kernel_path,
1940 sections, section_entsize,
1941 num_sections, strtab,
1945 section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
1947 for (i = 0; i < num_sections; i++)
1948 section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
1950 if (!is_relocatable (image_target))
1952 Elf_Addr current_address = layout->kernel_size;
1954 for (i = 0, s = sections;
1956 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1957 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1959 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
1960 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1963 current_address = ALIGN_UP (current_address
1964 + image_target->vaddr_offset,
1966 - image_target->vaddr_offset;
1968 grub_util_info ("locating the section %s at 0x%"
1969 GRUB_HOST_PRIxLONG_LONG,
1970 name, (unsigned long long) current_address);
1971 if (!is_relocatable (image_target))
1972 current_address = grub_host_to_target_addr (s->sh_addr)
1973 - image_target->link_addr;
1975 section_vaddresses[i] = current_address
1976 + image_target->vaddr_offset;
1977 current_address += grub_host_to_target_addr (s->sh_size);
1979 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1980 image_target->section_align)
1981 - image_target->vaddr_offset;
1982 layout->bss_size = current_address - layout->kernel_size;
1985 layout->bss_size = 0;
1987 if (image_target->id == IMAGE_SPARC64_AOUT
1988 || image_target->id == IMAGE_SPARC64_RAW
1989 || image_target->id == IMAGE_UBOOT
1990 || image_target->id == IMAGE_COREBOOT
1991 || image_target->id == IMAGE_SPARC64_CDCORE)
1992 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
1994 if (is_relocatable (image_target))
1996 symtab_section = NULL;
1997 for (i = 0, s = sections;
1999 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2000 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2005 if (! symtab_section)
2006 grub_util_error ("%s", _("no symbol table"));
2007 #ifdef MKIMAGE_ELF64
2008 if (image_target->elf_target == EM_IA_64)
2012 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2014 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2016 layout->tramp_off = layout->kernel_size;
2017 layout->kernel_size += ALIGN_UP (tramp, 16);
2019 layout->ia64jmp_off = layout->kernel_size;
2020 layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
2022 layout->kernel_size += 16 * layout->ia64jmpnum;
2024 layout->got_off = layout->kernel_size;
2025 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2027 if (image_target->elf_target == EM_AARCH64)
2031 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2033 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2035 layout->got_off = layout->kernel_size;
2036 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2042 layout->reloc_size = 0;
2043 layout->reloc_section = NULL;
2046 out_img = xmalloc (layout->kernel_size + total_module_size);
2047 memset (out_img, 0, layout->kernel_size + total_module_size);
2049 if (is_relocatable (image_target))
2051 layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
2052 section_vaddresses, section_entsize,
2054 (char *) out_img + layout->ia64jmp_off,
2056 + image_target->vaddr_offset,
2060 if (layout->start_address == (Elf_Addr) -1)
2061 grub_util_error ("start symbol is not defined");
2063 /* Resolve addresses in the virtual address space. */
2064 SUFFIX (relocate_addresses) (e, sections, section_addresses,
2066 num_sections, strtab,
2067 out_img, layout->tramp_off,
2071 make_reloc_section (e, layout,
2072 section_vaddresses, sections,
2073 section_entsize, num_sections,
2076 if (image_target->id != IMAGE_EFI)
2078 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2079 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2080 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2081 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2082 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2083 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2087 for (i = 0, s = sections;
2089 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2090 if (SUFFIX (is_data_section) (s, image_target)
2091 /* Explicitly initialize BSS
2092 when producing PE32 to avoid a bug in EFI implementations.
2093 Platforms other than EFI and U-boot shouldn't have .bss in
2094 their binaries as we build with -Wl,-Ttext.
2096 || (SUFFIX (is_bss_section) (s, image_target) && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2097 || SUFFIX (is_text_section) (s, image_target))
2099 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2100 memset (out_img + section_addresses[i], 0,
2101 grub_host_to_target_addr (s->sh_size));
2103 memcpy (out_img + section_addresses[i],
2104 kernel_img + grub_host_to_target_addr (s->sh_offset),
2105 grub_host_to_target_addr (s->sh_size));
2109 free (section_vaddresses);
2110 free (section_addresses);