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);
846 grub_uint32_t *t32 = (grub_uint32_t *) target;
847 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
849 - target_section_addr - offset
850 - image_target->vaddr_offset);
851 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
852 GRUB_HOST_PRIxLONG_LONG,
853 *t32, (unsigned long long) offset);
859 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
861 - target_section_addr - offset
862 - image_target->vaddr_offset);
863 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
864 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
865 GRUB_HOST_PRIxLONG_LONG,
866 (unsigned long long) *target,
867 (unsigned long long) offset);
874 grub_uint32_t *t32 = (grub_uint32_t *) target;
875 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
876 + addend + sym_addr);
877 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
878 GRUB_HOST_PRIxLONG_LONG,
879 *t32, (unsigned long long) offset);
884 grub_util_error (_("relocation 0x%x is not implemented yet"),
885 (unsigned int) ELF_R_TYPE (info));
890 switch (ELF_R_TYPE (info))
892 case R_IA64_PCREL21B:
895 grub_ia64_make_trampoline (tr, addend + sym_addr);
896 noff = ((char *) tr - (char *) pe_target
897 - target_section_addr - (offset & ~3)) >> 4;
900 grub_util_error ("trampoline offset too big (%"
901 GRUB_HOST_PRIxLONG_LONG ")",
902 (unsigned long long) noff);
903 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
907 case R_IA64_LTOFF22X:
912 sym = (Elf_Sym *) ((char *) e
913 + grub_target_to_host (symtab_section->sh_offset)
914 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
915 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
916 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
918 - image_target->vaddr_offset));
921 case R_IA64_LTOFF_FPTR22:
922 *gpptr = grub_host_to_target64 (addend + sym_addr);
923 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
924 (char *) gpptr - (char *) pe_target
925 + image_target->vaddr_offset);
930 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
933 case R_IA64_GPREL64I:
934 grub_ia64_set_immu64 ((grub_addr_t) target,
937 case R_IA64_PCREL64LSB:
938 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
940 - target_section_addr - offset
941 - image_target->vaddr_offset);
944 case R_IA64_SEGREL64LSB:
945 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
946 + addend + sym_addr - target_section_addr);
948 case R_IA64_DIR64LSB:
949 case R_IA64_FPTR64LSB:
950 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
951 + addend + sym_addr);
952 grub_util_info ("relocating a direct entry to 0x%"
953 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
954 GRUB_HOST_PRIxLONG_LONG,
956 grub_target_to_host64 (*target),
957 (unsigned long long) offset);
960 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
965 grub_util_error (_("relocation 0x%x is not implemented yet"),
966 (unsigned int) ELF_R_TYPE (info));
973 switch (ELF_R_TYPE (info))
975 case R_AARCH64_ABS64:
977 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
980 case R_AARCH64_PREL32:
982 grub_uint32_t *t32 = (grub_uint32_t *) target;
983 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
985 - target_section_addr - offset
986 - image_target->vaddr_offset);
987 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
988 GRUB_HOST_PRIxLONG_LONG,
989 *t32, (unsigned long long) offset);
992 case R_AARCH64_ADD_ABS_LO12_NC:
993 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
996 case R_AARCH64_LDST64_ABS_LO12_NC:
997 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
1000 case R_AARCH64_JUMP26:
1001 case R_AARCH64_CALL26:
1004 sym_addr -= target_section_addr + image_target->vaddr_offset;
1005 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1006 grub_util_error ("%s", "CALL26 Relocation out of range");
1008 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1012 case R_AARCH64_ADR_GOT_PAGE:
1015 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1016 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1018 *gpptr = grub_host_to_target64 (sym_addr);
1019 unmatched_adr_got_page++;
1020 if (!grub_arm64_check_hi21_signed (gpoffset))
1021 grub_util_error ("HI21 out of range");
1022 grub_arm64_set_hi21((grub_uint32_t *)target,
1024 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1026 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1027 if (ELF_R_SYM (rel2->r_info)
1028 == ELF_R_SYM (r->r_info)
1029 && r->r_addend == rel2->r_addend
1030 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1032 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1033 grub_target_to_host (rel2->r_offset), image_target),
1034 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1038 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1042 case R_AARCH64_LD64_GOT_LO12_NC:
1043 if (unmatched_adr_got_page == 0)
1044 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1045 unmatched_adr_got_page--;
1047 case R_AARCH64_ADR_PREL_PG_HI21:
1049 sym_addr &= ~0xfffULL;
1050 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1051 if (!grub_arm64_check_hi21_signed (sym_addr))
1052 grub_util_error ("%s", "CALL26 Relocation out of range");
1054 grub_arm64_set_hi21((grub_uint32_t *)target,
1059 grub_util_error (_("relocation 0x%x is not implemented yet"),
1060 (unsigned int) ELF_R_TYPE (info));
1066 #if defined(MKIMAGE_ELF32)
1070 sym_addr -= image_target->vaddr_offset;
1071 switch (ELF_R_TYPE (info))
1075 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1076 (int) sym_addr, (int) sym_addr);
1077 /* Data will be naturally aligned */
1078 if (image_target->id == IMAGE_EFI)
1080 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1083 /* Happens when compiled with -march=armv4.
1084 Since currently we need at least armv5, keep bx as-is.
1088 case R_ARM_THM_CALL:
1089 case R_ARM_THM_JUMP24:
1090 case R_ARM_THM_JUMP19:
1094 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1095 (unsigned long) ((char *) target
1098 sym = (Elf_Sym *) ((char *) e
1099 + grub_target_to_host (symtab_section->sh_offset)
1100 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
1101 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1103 if (!(sym_addr & 1))
1105 grub_uint32_t tr_addr;
1106 grub_int32_t new_offset;
1107 tr_addr = (char *) tr - (char *) pe_target
1108 - target_section_addr;
1109 new_offset = sym_addr - tr_addr - 12;
1111 if (!grub_arm_jump24_check_offset (new_offset))
1112 return grub_util_error ("jump24 relocation out of range");
1114 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1115 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1117 sym_addr = tr_addr | 1;
1120 /* Thumb instructions can be 16-bit aligned */
1121 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1122 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1124 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1127 grub_util_error ("%s", grub_errmsg);
1135 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1138 grub_uint32_t tr_addr;
1139 grub_int32_t new_offset;
1140 tr_addr = (char *) tr - (char *) pe_target
1141 - target_section_addr;
1142 new_offset = sym_addr - tr_addr - 12;
1144 /* There is no immediate version of bx, only register one... */
1145 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1146 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1147 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1148 tr[3] = grub_host_to_target32 (new_offset | 1);
1153 err = grub_arm_reloc_jump24 (target,
1156 grub_util_error ("%s", grub_errmsg);
1161 grub_util_error (_("relocation 0x%x is not implemented yet"),
1162 (unsigned int) ELF_R_TYPE (info));
1167 #endif /* MKIMAGE_ELF32 */
1169 grub_util_error ("unknown architecture type %d",
1170 image_target->elf_target);
1176 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1177 after having written to the file OUT. */
1179 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1180 Elf_Addr addr, int flush, Elf_Addr current_address,
1181 const struct grub_install_image_target_desc *image_target)
1183 struct grub_pe32_fixup_block *b;
1185 b = &((*cblock)->b);
1187 /* First, check if it is necessary to write out the current block. */
1188 if ((*cblock)->state)
1190 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
1196 /* Add as much padding as necessary to align the address
1197 with a section boundary. */
1198 Elf_Addr next_address;
1199 unsigned padding_size;
1202 next_address = current_address + b->block_size;
1203 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1206 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1207 grub_util_info ("adding %d padding fixup entries", padding_size);
1208 while (padding_size--)
1210 b->entries[cur_index++] = 0;
1214 else while (b->block_size & (8 - 1))
1216 /* If not aligned with a 32-bit boundary, add
1220 grub_util_info ("adding a padding fixup entry");
1221 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1222 b->entries[cur_index] = 0;
1227 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1228 b->block_size, b->page_rva);
1229 size = b->block_size;
1230 current_address += size;
1231 b->page_rva = grub_host_to_target32 (b->page_rva);
1232 b->block_size = grub_host_to_target32 (b->block_size);
1233 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1234 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1235 *cblock = (*cblock)->next;
1239 b = &((*cblock)->b);
1243 grub_uint16_t entry;
1246 /* If not allocated yet, allocate a block with enough entries. */
1247 if (! (*cblock)->state)
1249 (*cblock)->state = 1;
1251 /* The spec does not mention the requirement of a Page RVA.
1252 Here, align the address with a 4K boundary for safety. */
1253 b->page_rva = (addr & ~(0x1000 - 1));
1254 b->block_size = sizeof (*b);
1258 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1259 grub_util_error ("too many fixup entries");
1261 /* Add a new entry. */
1262 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1263 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
1264 b->entries[cur_index] = grub_host_to_target16 (entry);
1268 return current_address;
1273 struct raw_reloc *next;
1274 grub_uint32_t offset;
1275 enum raw_reloc_type {
1276 RAW_RELOC_NONE = -1,
1282 struct translate_context
1285 struct fixup_block_list *lst, *lst0;
1286 Elf_Addr current_address;
1289 struct raw_reloc *raw_relocs;
1293 translate_reloc_start (struct translate_context *ctx,
1294 const struct grub_install_image_target_desc *image_target)
1296 grub_memset (ctx, 0, sizeof (*ctx));
1297 if (image_target->id == IMAGE_EFI)
1299 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1300 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1301 ctx->current_address = 0;
1306 translate_relocation_pe (struct translate_context *ctx,
1309 const struct grub_install_image_target_desc *image_target)
1311 /* Necessary to relocate only absolute addresses. */
1312 switch (image_target->elf_target)
1315 if (ELF_R_TYPE (info) == R_386_32)
1317 grub_util_info ("adding a relocation entry for 0x%"
1318 GRUB_HOST_PRIxLONG_LONG,
1319 (unsigned long long) addr);
1320 ctx->current_address
1321 = add_fixup_entry (&ctx->lst,
1322 GRUB_PE32_REL_BASED_HIGHLOW,
1323 addr, 0, ctx->current_address,
1328 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1329 (ELF_R_TYPE (info) == R_X86_64_32S))
1331 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1333 else if (ELF_R_TYPE (info) == R_X86_64_64)
1335 grub_util_info ("adding a relocation entry for 0x%"
1336 GRUB_HOST_PRIxLONG_LONG,
1337 (unsigned long long) addr);
1338 ctx->current_address
1339 = add_fixup_entry (&ctx->lst,
1340 GRUB_PE32_REL_BASED_DIR64,
1342 0, ctx->current_address,
1347 switch (ELF_R_TYPE (info))
1349 case R_IA64_PCREL64LSB:
1351 case R_IA64_PCREL21B:
1352 case R_IA64_LTOFF_FPTR22:
1353 case R_IA64_LTOFF22X:
1354 case R_IA64_LTOFF22:
1355 case R_IA64_GPREL22:
1356 case R_IA64_GPREL64I:
1357 case R_IA64_SEGREL64LSB:
1360 case R_IA64_FPTR64LSB:
1361 case R_IA64_DIR64LSB:
1364 grub_util_info ("adding a relocation entry for 0x%"
1365 GRUB_HOST_PRIxLONG_LONG,
1366 (unsigned long long) addr);
1367 ctx->current_address
1368 = add_fixup_entry (&ctx->lst,
1369 GRUB_PE32_REL_BASED_DIR64,
1371 0, ctx->current_address,
1377 grub_util_error (_("relocation 0x%x is not implemented yet"),
1378 (unsigned int) ELF_R_TYPE (info));
1383 switch (ELF_R_TYPE (info))
1385 case R_AARCH64_ABS64:
1387 ctx->current_address
1388 = add_fixup_entry (&ctx->lst,
1389 GRUB_PE32_REL_BASED_DIR64,
1390 addr, 0, ctx->current_address,
1394 /* Relative relocations do not require fixup entries. */
1395 case R_AARCH64_CALL26:
1396 case R_AARCH64_JUMP26:
1397 case R_AARCH64_PREL32:
1399 /* Page-relative relocations do not require fixup entries. */
1400 case R_AARCH64_ADR_PREL_PG_HI21:
1401 /* We page-align the whole kernel, so no need
1404 case R_AARCH64_ADD_ABS_LO12_NC:
1405 case R_AARCH64_LDST64_ABS_LO12_NC:
1408 /* GOT is relocated separately. */
1409 case R_AARCH64_ADR_GOT_PAGE:
1410 case R_AARCH64_LD64_GOT_LO12_NC:
1414 grub_util_error (_("relocation 0x%x is not implemented yet"),
1415 (unsigned int) ELF_R_TYPE (info));
1420 #if defined(MKIMAGE_ELF32)
1422 switch (ELF_R_TYPE (info))
1425 /* Relative relocations do not require fixup entries. */
1427 case R_ARM_THM_CALL:
1428 case R_ARM_THM_JUMP19:
1429 case R_ARM_THM_JUMP24:
1432 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1435 /* Create fixup entry for PE/COFF loader */
1438 ctx->current_address
1439 = add_fixup_entry (&ctx->lst,
1440 GRUB_PE32_REL_BASED_HIGHLOW,
1441 addr, 0, ctx->current_address,
1446 grub_util_error (_("relocation 0x%x is not implemented yet"),
1447 (unsigned int) ELF_R_TYPE (info));
1451 #endif /* defined(MKIMAGE_ELF32) */
1453 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1457 static enum raw_reloc_type
1458 classify_raw_reloc (Elf_Addr info,
1459 const struct grub_install_image_target_desc *image_target)
1461 /* Necessary to relocate only absolute addresses. */
1462 switch (image_target->elf_target)
1465 switch (ELF_R_TYPE (info))
1469 case R_ARM_THM_CALL:
1470 case R_ARM_THM_JUMP19:
1471 case R_ARM_THM_JUMP24:
1473 return RAW_RELOC_NONE;
1475 return RAW_RELOC_32;
1477 grub_util_error (_("relocation 0x%x is not implemented yet"),
1478 (unsigned int) ELF_R_TYPE (info));
1483 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1488 translate_relocation_raw (struct translate_context *ctx,
1491 const struct grub_install_image_target_desc *image_target)
1493 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
1494 struct raw_reloc *rel;
1495 if (class == RAW_RELOC_NONE)
1497 rel = xmalloc (sizeof (*rel));
1498 rel->next = ctx->raw_relocs;
1501 ctx->raw_relocs = rel;
1505 translate_relocation (struct translate_context *ctx,
1508 const struct grub_install_image_target_desc *image_target)
1510 if (image_target->id == IMAGE_EFI)
1511 translate_relocation_pe (ctx, addr, info, image_target);
1513 translate_relocation_raw (ctx, addr, info, image_target);
1517 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1518 const struct grub_install_image_target_desc *image_target)
1520 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
1524 layout->reloc_section = ptr = xmalloc (ctx->current_address);
1525 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
1526 if (ctx->lst->state)
1528 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
1529 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
1531 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
1534 for (ctx->lst = ctx->lst0; ctx->lst; )
1536 struct fixup_block_list *next;
1537 next = ctx->lst->next;
1542 layout->reloc_size = ctx->current_address;
1543 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
1544 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
1545 "This breaks assembly assumptions. Please increase stack size",
1546 (int) layout->reloc_size,
1547 (int) GRUB_KERNEL_ARM_STACK_SIZE);
1552 <type 0 relocations>
1554 <type 1 relocations>
1557 <type n relocations>
1559 each relocation starts with 32-bit offset. Rest depends on relocation.
1560 mkimage stops when it sees first unknown type or end marker.
1561 This allows images to be created with mismatched mkimage and
1562 kernel as long as no relocations are present in kernel that mkimage
1563 isn't aware of (in which case mkimage aborts).
1564 This also allows simple assembly to do the relocs.
1567 #define RAW_SEPARATOR 0xfffffffe
1568 #define RAW_END_MARKER 0xffffffff
1571 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1572 const struct grub_install_image_target_desc *image_target)
1574 size_t count = 0, sz;
1575 enum raw_reloc_type highest = RAW_RELOC_NONE;
1576 enum raw_reloc_type curtype;
1577 struct raw_reloc *cur;
1579 if (!ctx->raw_relocs)
1581 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
1582 p[0] = RAW_END_MARKER;
1583 layout->reloc_size = sizeof (grub_uint32_t);
1586 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1589 if (cur->type > highest)
1590 highest = cur->type;
1592 /* highest separators, count relocations and one end marker. */
1593 sz = (highest + count + 1) * sizeof (grub_uint32_t);
1594 layout->reloc_section = p = xmalloc (sz);
1595 for (curtype = 0; curtype <= highest; curtype++)
1597 /* Support for special cases would go here. */
1598 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1599 if (cur->type == curtype)
1603 *p++ = RAW_SEPARATOR;
1605 *--p = RAW_END_MARKER;
1606 layout->reloc_size = sz;
1610 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1611 const struct grub_install_image_target_desc *image_target)
1613 if (image_target->id == IMAGE_EFI)
1614 finish_reloc_translation_pe (ctx, layout, image_target);
1616 finish_reloc_translation_raw (ctx, layout, image_target);
1621 create_u64_fixups (struct translate_context *ctx,
1622 Elf_Addr jumpers, grub_size_t njumpers,
1623 const struct grub_install_image_target_desc *image_target)
1626 assert (image_target->id == IMAGE_EFI);
1627 for (i = 0; i < njumpers; i++)
1628 ctx->current_address = add_fixup_entry (&ctx->lst,
1629 GRUB_PE32_REL_BASED_DIR64,
1631 0, ctx->current_address,
1635 /* Make a .reloc section. */
1637 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
1638 Elf_Addr *section_addresses, Elf_Shdr *sections,
1639 Elf_Half section_entsize, Elf_Half num_sections,
1641 const struct grub_install_image_target_desc *image_target)
1645 struct translate_context ctx;
1647 translate_reloc_start (&ctx, image_target);
1649 for (i = 0, s = sections; i < num_sections;
1650 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1651 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1652 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
1655 Elf_Word rtab_size, r_size, num_rs;
1656 Elf_Off rtab_offset;
1657 Elf_Addr section_address;
1660 grub_util_info ("translating the relocation section %s",
1661 strtab + grub_le_to_cpu32 (s->sh_name));
1663 rtab_size = grub_target_to_host (s->sh_size);
1664 r_size = grub_target_to_host (s->sh_entsize);
1665 rtab_offset = grub_target_to_host (s->sh_offset);
1666 num_rs = rtab_size / r_size;
1668 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
1670 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1672 j++, r = (Elf_Rel *) ((char *) r + r_size))
1678 offset = grub_target_to_host (r->r_offset);
1679 info = grub_target_to_host (r->r_info);
1681 addr = section_address + offset;
1683 translate_relocation (&ctx, addr, info, image_target);
1687 if (image_target->elf_target == EM_IA_64)
1688 create_u64_fixups (&ctx,
1690 + image_target->vaddr_offset,
1691 2 * layout->ia64jmpnum,
1693 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
1694 create_u64_fixups (&ctx,
1696 + image_target->vaddr_offset,
1697 (layout->got_size / 8),
1700 finish_reloc_translation (&ctx, layout, image_target);
1703 /* Determine if this section is a text section. Return false if this
1704 section is not allocated. */
1706 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1708 if (!is_relocatable (image_target)
1709 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1711 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1712 == (SHF_EXECINSTR | SHF_ALLOC));
1715 /* Determine if this section is a data section. */
1717 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1719 if (!is_relocatable (image_target)
1720 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1722 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1723 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1727 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
1729 if (!is_relocatable (image_target))
1731 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
1732 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
1735 /* Return if the ELF header is valid. */
1737 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
1739 if (size < sizeof (*e)
1740 || e->e_ident[EI_MAG0] != ELFMAG0
1741 || e->e_ident[EI_MAG1] != ELFMAG1
1742 || e->e_ident[EI_MAG2] != ELFMAG2
1743 || e->e_ident[EI_MAG3] != ELFMAG3
1744 || e->e_ident[EI_VERSION] != EV_CURRENT
1745 || e->e_ident[EI_CLASS] != ELFCLASSXX
1746 || e->e_version != grub_host_to_target32 (EV_CURRENT))
1753 SUFFIX (put_section) (Elf_Shdr *s, int i,
1754 Elf_Addr current_address,
1755 Elf_Addr *section_addresses,
1757 const struct grub_install_image_target_desc *image_target)
1759 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
1760 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1763 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1765 - image_target->vaddr_offset;
1767 grub_util_info ("locating the section %s at 0x%"
1768 GRUB_HOST_PRIxLONG_LONG,
1769 name, (unsigned long long) current_address);
1770 if (!is_relocatable (image_target))
1771 current_address = grub_host_to_target_addr (s->sh_addr)
1772 - image_target->link_addr;
1773 section_addresses[i] = current_address;
1774 current_address += grub_host_to_target_addr (s->sh_size);
1775 return current_address;
1778 /* Locate section addresses by merging code sections and data sections
1779 into .text and .data, respectively. Return the array of section
1782 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
1783 Elf_Shdr *sections, Elf_Half section_entsize,
1784 Elf_Half num_sections, const char *strtab,
1785 struct grub_mkimage_layout *layout,
1786 const struct grub_install_image_target_desc *image_target)
1789 Elf_Addr *section_addresses;
1793 /* Page-aligning simplifies relocation handling. */
1794 if (image_target->elf_target == EM_AARCH64)
1795 layout->align = 4096;
1797 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
1798 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
1800 layout->kernel_size = 0;
1802 for (i = 0, s = sections;
1804 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1805 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
1806 && grub_host_to_target32 (s->sh_addralign) > layout->align)
1807 layout->align = grub_host_to_target32 (s->sh_addralign);
1811 for (i = 0, s = sections;
1813 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1814 if (SUFFIX (is_text_section) (s, image_target))
1816 layout->kernel_size = SUFFIX (put_section) (s, i,
1817 layout->kernel_size,
1821 if (!is_relocatable (image_target) &&
1822 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
1825 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
1826 " instead of 0x%llx: ld.gold bug?"),
1828 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
1829 (unsigned long long) image_target->link_addr);
1830 grub_util_error ("%s", msg);
1834 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1835 image_target->section_align)
1836 - image_target->vaddr_offset;
1837 layout->exec_size = layout->kernel_size;
1840 for (i = 0, s = sections;
1842 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1843 if (SUFFIX (is_data_section) (s, image_target))
1844 layout->kernel_size = SUFFIX (put_section) (s, i,
1845 layout->kernel_size,
1850 #ifdef MKIMAGE_ELF32
1851 if (image_target->elf_target == EM_ARM)
1854 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
1855 image_target->section_align) - image_target->vaddr_offset;
1857 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
1859 tramp = arm_get_trampoline_size (e, sections, section_entsize,
1860 num_sections, image_target);
1862 layout->tramp_off = layout->kernel_size;
1863 layout->kernel_size += ALIGN_UP (tramp, 16);
1867 layout->bss_start = layout->kernel_size;
1868 layout->end = layout->kernel_size;
1871 for (i = 0, s = sections;
1873 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1874 if (SUFFIX (is_bss_section) (s, image_target))
1875 layout->end = SUFFIX (put_section) (s, i,
1881 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
1882 image_target->section_align) - image_target->vaddr_offset;
1883 /* Explicitly initialize BSS
1884 when producing PE32 to avoid a bug in EFI implementations.
1885 Platforms other than EFI and U-boot shouldn't have .bss in
1886 their binaries as we build with -Wl,-Ttext.
1888 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
1889 layout->kernel_size = layout->end;
1891 return section_addresses;
1895 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
1896 size_t total_module_size,
1897 struct grub_mkimage_layout *layout,
1898 const struct grub_install_image_target_desc *image_target)
1900 char *kernel_img, *out_img;
1904 Elf_Addr *section_addresses;
1905 Elf_Addr *section_vaddresses;
1908 Elf_Half num_sections;
1909 Elf_Off section_offset;
1910 Elf_Half section_entsize;
1911 grub_size_t kernel_size;
1912 Elf_Shdr *symtab_section = 0;
1914 grub_memset (layout, 0, sizeof (*layout));
1916 layout->start_address = 0;
1918 kernel_size = grub_util_get_image_size (kernel_path);
1919 kernel_img = xmalloc (kernel_size);
1920 grub_util_load_image (kernel_path, kernel_img);
1922 e = (Elf_Ehdr *) kernel_img;
1923 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
1924 grub_util_error ("invalid ELF header");
1926 section_offset = grub_target_to_host (e->e_shoff);
1927 section_entsize = grub_target_to_host16 (e->e_shentsize);
1928 num_sections = grub_target_to_host16 (e->e_shnum);
1930 if (kernel_size < section_offset + (grub_uint32_t) section_entsize * num_sections)
1931 grub_util_error (_("premature end of file %s"), kernel_path);
1933 sections = (Elf_Shdr *) (kernel_img + section_offset);
1935 /* Relocate sections then symbols in the virtual address space. */
1936 s = (Elf_Shdr *) ((char *) sections
1937 + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
1938 strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
1940 section_addresses = SUFFIX (locate_sections) (e, kernel_path,
1941 sections, section_entsize,
1942 num_sections, strtab,
1946 section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
1948 for (i = 0; i < num_sections; i++)
1949 section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
1951 if (!is_relocatable (image_target))
1953 Elf_Addr current_address = layout->kernel_size;
1955 for (i = 0, s = sections;
1957 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1958 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1960 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
1961 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1964 current_address = ALIGN_UP (current_address
1965 + image_target->vaddr_offset,
1967 - image_target->vaddr_offset;
1969 grub_util_info ("locating the section %s at 0x%"
1970 GRUB_HOST_PRIxLONG_LONG,
1971 name, (unsigned long long) current_address);
1972 if (!is_relocatable (image_target))
1973 current_address = grub_host_to_target_addr (s->sh_addr)
1974 - image_target->link_addr;
1976 section_vaddresses[i] = current_address
1977 + image_target->vaddr_offset;
1978 current_address += grub_host_to_target_addr (s->sh_size);
1980 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1981 image_target->section_align)
1982 - image_target->vaddr_offset;
1983 layout->bss_size = current_address - layout->kernel_size;
1986 layout->bss_size = 0;
1988 if (image_target->id == IMAGE_SPARC64_AOUT
1989 || image_target->id == IMAGE_SPARC64_RAW
1990 || image_target->id == IMAGE_UBOOT
1991 || image_target->id == IMAGE_COREBOOT
1992 || image_target->id == IMAGE_SPARC64_CDCORE)
1993 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
1995 if (is_relocatable (image_target))
1997 symtab_section = NULL;
1998 for (i = 0, s = sections;
2000 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2001 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2006 if (! symtab_section)
2007 grub_util_error ("%s", _("no symbol table"));
2008 #ifdef MKIMAGE_ELF64
2009 if (image_target->elf_target == EM_IA_64)
2013 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2015 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2017 layout->tramp_off = layout->kernel_size;
2018 layout->kernel_size += ALIGN_UP (tramp, 16);
2020 layout->ia64jmp_off = layout->kernel_size;
2021 layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
2023 layout->kernel_size += 16 * layout->ia64jmpnum;
2025 layout->got_off = layout->kernel_size;
2026 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2028 if (image_target->elf_target == EM_AARCH64)
2032 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2034 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2036 layout->got_off = layout->kernel_size;
2037 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2043 layout->reloc_size = 0;
2044 layout->reloc_section = NULL;
2047 out_img = xmalloc (layout->kernel_size + total_module_size);
2048 memset (out_img, 0, layout->kernel_size + total_module_size);
2050 if (is_relocatable (image_target))
2052 layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
2053 section_vaddresses, section_entsize,
2055 (char *) out_img + layout->ia64jmp_off,
2057 + image_target->vaddr_offset,
2061 if (layout->start_address == (Elf_Addr) -1)
2062 grub_util_error ("start symbol is not defined");
2064 /* Resolve addresses in the virtual address space. */
2065 SUFFIX (relocate_addresses) (e, sections, section_addresses,
2067 num_sections, strtab,
2068 out_img, layout->tramp_off,
2072 make_reloc_section (e, layout,
2073 section_vaddresses, sections,
2074 section_entsize, num_sections,
2077 if (image_target->id != IMAGE_EFI)
2079 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2080 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2081 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2082 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2083 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2084 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2088 for (i = 0, s = sections;
2090 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
2091 if (SUFFIX (is_data_section) (s, image_target)
2092 /* Explicitly initialize BSS
2093 when producing PE32 to avoid a bug in EFI implementations.
2094 Platforms other than EFI and U-boot shouldn't have .bss in
2095 their binaries as we build with -Wl,-Ttext.
2097 || (SUFFIX (is_bss_section) (s, image_target) && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2098 || SUFFIX (is_text_section) (s, image_target))
2100 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2101 memset (out_img + section_addresses[i], 0,
2102 grub_host_to_target_addr (s->sh_size));
2104 memcpy (out_img + section_addresses[i],
2105 kernel_img + grub_host_to_target_addr (s->sh_offset),
2106 grub_host_to_target_addr (s->sh_size));
2110 free (section_vaddresses);
2111 free (section_addresses);