tpm2_key_protector: Enable build for powerpc_ieee1275
[grub.git] / util / grub-mkimagexx.c
blob448862b2e12c0854952c38d7bd83f37700f23508
1 /* grub-mkimage.c - make a bootable image */
2 /*
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/>.
20 #include <config.h>
21 #include <grub/types.h>
22 #include <grub/elf.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>
33 #include <grub/dl.h>
34 #include <time.h>
35 #include <multiboot.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <assert.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/loongarch64/reloc.h>
48 #include <grub/osdep/hostfile.h>
49 #include <grub/util/install.h>
50 #include <grub/util/mkimage.h>
52 #include <xen/elfnote.h>
54 #pragma GCC diagnostic ignored "-Wcast-align"
56 #define GRUB_MKIMAGEXX
57 #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
58 #if __SIZEOF_POINTER__ == 8
59 #include "grub-mkimage64.c"
60 #else
61 #include "grub-mkimage32.c"
62 #endif
63 #endif
65 /* These structures are defined according to the CHRP binding to IEEE1275,
66 "Client Program Format" section. */
68 struct grub_ieee1275_note_desc
70 grub_uint32_t real_mode;
71 grub_uint32_t real_base;
72 grub_uint32_t real_size;
73 grub_uint32_t virt_base;
74 grub_uint32_t virt_size;
75 grub_uint32_t load_base;
78 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
79 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
81 struct grub_ieee1275_note
83 Elf32_Nhdr header;
84 char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
85 struct grub_ieee1275_note_desc descriptor;
88 #define GRUB_XEN_NOTE_NAME "Xen"
90 struct fixup_block_list
92 struct fixup_block_list *next;
93 int state;
94 struct grub_pe32_fixup_block b;
97 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
99 struct section_metadata
101 Elf_Half num_sections;
102 Elf_Shdr *sections;
103 Elf_Addr *addrs;
104 Elf_Addr *vaddrs;
105 Elf_Half section_entsize;
106 Elf_Shdr *symtab;
107 const char *strtab;
110 #define GRUB_SBAT_NOTE_NAME ".sbat"
111 #define GRUB_SBAT_NOTE_TYPE 0x53424154 /* "SBAT" */
113 struct grub_sbat_note {
114 Elf32_Nhdr header;
115 char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
118 static int
119 is_relocatable (const struct grub_install_image_target_desc *image_target)
121 return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
122 || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
125 #ifdef MKIMAGE_ELF32
128 * R_ARM_THM_CALL/THM_JUMP24
130 * Relocate Thumb (T32) instruction set relative branches:
131 * B.W, BL and BLX
133 static grub_err_t
134 grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
136 grub_int32_t offset;
138 offset = grub_arm_thm_call_get_offset (target);
140 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
142 offset += sym_addr;
144 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
145 target, sym_addr, offset);
147 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
148 is bigger than 2M (currently under 150K) then we probably have a problem
149 somewhere else. */
150 if (offset < -0x200000 || offset >= 0x200000)
151 return grub_error (GRUB_ERR_BAD_MODULE,
152 "THM_CALL Relocation out of range.");
154 grub_dprintf ("dl", " relative destination = %p",
155 (char *) target + offset);
157 return grub_arm_thm_call_set_offset (target, offset);
161 * R_ARM_THM_JUMP19
163 * Relocate conditional Thumb (T32) B<c>.W
165 static grub_err_t
166 grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
168 grub_int32_t offset;
170 if (!(sym_addr & 1))
171 return grub_error (GRUB_ERR_BAD_MODULE,
172 "Relocation targeting wrong execution state");
174 offset = grub_arm_thm_jump19_get_offset (target);
176 /* Adjust and re-truncate offset */
177 offset += sym_addr;
179 if (!grub_arm_thm_jump19_check_offset (offset))
180 return grub_error (GRUB_ERR_BAD_MODULE,
181 "THM_JUMP19 Relocation out of range.");
183 grub_arm_thm_jump19_set_offset (target, offset);
185 return GRUB_ERR_NONE;
189 * R_ARM_JUMP24
191 * Relocate ARM (A32) B
193 static grub_err_t
194 grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
196 grub_int32_t offset;
198 if (sym_addr & 1)
199 return grub_error (GRUB_ERR_BAD_MODULE,
200 "Relocation targeting wrong execution state");
202 offset = grub_arm_jump24_get_offset (target);
203 offset += sym_addr;
205 if (!grub_arm_jump24_check_offset (offset))
206 return grub_error (GRUB_ERR_BAD_MODULE,
207 "JUMP24 Relocation out of range.");
210 grub_arm_jump24_set_offset (target, offset);
212 return GRUB_ERR_NONE;
215 #endif
217 void
218 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
219 int note, char *sbat, char **core_img, size_t *core_size,
220 Elf_Addr target_addr,
221 struct grub_mkimage_layout *layout)
223 char *elf_img;
224 size_t program_size;
225 Elf_Ehdr *ehdr;
226 Elf_Phdr *phdr;
227 Elf_Shdr *shdr;
228 int header_size, footer_size = 0, footer_offset = 0;
229 int phnum = 1;
230 int shnum = 4;
231 int string_size = sizeof (".text") + sizeof ("mods") + 1;
232 char *footer;
234 if (sbat)
236 phnum++;
237 footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
240 if (image_target->id != IMAGE_LOONGSON_ELF)
241 phnum += 2;
243 if (note)
245 phnum++;
246 footer_size += sizeof (struct grub_ieee1275_note);
248 if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
250 phnum++;
251 shnum++;
252 string_size += sizeof (".xen");
253 footer_size += (image_target->id == IMAGE_XEN) ? XEN_NOTE_SIZE : XEN_PVH_NOTE_SIZE;
255 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
256 + shnum * sizeof (*shdr) + string_size, layout->align);
258 program_size = ALIGN_ADDR (*core_size);
260 elf_img = xmalloc (program_size + header_size + footer_size);
261 memset (elf_img, 0, program_size + header_size + footer_size);
262 memcpy (elf_img + header_size, *core_img, *core_size);
263 ehdr = (void *) elf_img;
264 phdr = (void *) (elf_img + sizeof (*ehdr));
265 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
266 footer = elf_img + program_size + header_size;
267 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
268 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
269 if (!image_target->bigendian)
270 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
271 else
272 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
273 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
274 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
275 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
276 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
277 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
279 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
280 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
281 ehdr->e_phnum = grub_host_to_target16 (phnum);
283 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
284 - (grub_uint8_t *) ehdr);
285 if (image_target->id == IMAGE_LOONGSON_ELF)
286 ehdr->e_shentsize = grub_host_to_target16 (0);
287 else
288 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
289 ehdr->e_shnum = grub_host_to_target16 (shnum);
290 ehdr->e_shstrndx = grub_host_to_target16 (1);
292 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
294 phdr->p_type = grub_host_to_target32 (PT_LOAD);
295 phdr->p_offset = grub_host_to_target32 (header_size);
296 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
298 ehdr->e_entry = grub_host_to_target32 (target_addr);
299 phdr->p_vaddr = grub_host_to_target32 (target_addr);
300 phdr->p_paddr = grub_host_to_target32 (target_addr);
301 phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
302 layout->align : image_target->link_align);
303 if (image_target->id == IMAGE_LOONGSON_ELF)
304 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
305 | EF_MIPS_PIC | EF_MIPS_CPIC);
306 else
307 ehdr->e_flags = 0;
308 if (image_target->id == IMAGE_LOONGSON_ELF)
310 phdr->p_filesz = grub_host_to_target32 (*core_size);
311 phdr->p_memsz = grub_host_to_target32 (*core_size);
313 else
315 grub_uint32_t target_addr_mods;
316 phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
317 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
318 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
319 else
320 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
322 phdr++;
323 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
324 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
325 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
326 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
327 phdr->p_align = grub_host_to_target32 (image_target->link_align);
329 phdr++;
330 phdr->p_type = grub_host_to_target32 (PT_LOAD);
331 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
332 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
333 phdr->p_filesz = phdr->p_memsz
334 = grub_host_to_target32 (*core_size - layout->kernel_size);
336 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
337 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
338 else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
339 target_addr_mods = ALIGN_UP (target_addr + layout->end
340 + image_target->mod_gap,
341 image_target->mod_align);
342 else
343 target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
344 + image_target->mod_gap,
345 image_target->mod_align);
346 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
347 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
348 phdr->p_align = grub_host_to_target32 (image_target->link_align);
351 if (image_target->id == IMAGE_XEN)
353 char *note_start = (elf_img + program_size + header_size);
354 Elf_Nhdr *note_ptr;
355 char *ptr = (char *) note_start;
357 grub_util_info ("adding XEN NOTE segment");
359 /* Guest OS. */
360 note_ptr = (Elf_Nhdr *) ptr;
361 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
362 note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
363 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_GUEST_OS);
364 ptr += sizeof (Elf_Nhdr);
365 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
366 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
367 memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
368 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
370 /* Loader. */
371 note_ptr = (Elf_Nhdr *) ptr;
372 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
373 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
374 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_LOADER);
375 ptr += sizeof (Elf_Nhdr);
376 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
377 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
378 memcpy (ptr, "generic", sizeof ("generic"));
379 ptr += ALIGN_UP (sizeof ("generic"), 4);
381 /* Version. */
382 note_ptr = (Elf_Nhdr *) ptr;
383 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
384 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
385 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_XEN_VERSION);
386 ptr += sizeof (Elf_Nhdr);
387 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
388 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
389 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
390 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
392 /* Entry. */
393 note_ptr = (Elf_Nhdr *) ptr;
394 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
395 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
396 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_ENTRY);
397 ptr += sizeof (Elf_Nhdr);
398 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
399 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
400 memset (ptr, 0, image_target->voidp_sizeof);
401 ptr += image_target->voidp_sizeof;
403 /* Virt base. */
404 note_ptr = (Elf_Nhdr *) ptr;
405 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
406 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
407 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_VIRT_BASE);
408 ptr += sizeof (Elf_Nhdr);
409 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
410 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
411 memset (ptr, 0, image_target->voidp_sizeof);
412 ptr += image_target->voidp_sizeof;
414 /* PAE. */
415 if (image_target->elf_target == EM_386)
417 note_ptr = (Elf_Nhdr *) ptr;
418 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
419 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
420 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PAE_MODE);
421 ptr += sizeof (Elf_Nhdr);
422 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
423 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
424 memcpy (ptr, "yes", sizeof ("yes"));
425 ptr += ALIGN_UP (sizeof ("yes"), 4);
428 assert (XEN_NOTE_SIZE == (ptr - note_start));
430 phdr++;
431 phdr->p_type = grub_host_to_target32 (PT_NOTE);
432 phdr->p_flags = grub_host_to_target32 (PF_R);
433 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
434 phdr->p_vaddr = 0;
435 phdr->p_paddr = 0;
436 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
437 phdr->p_memsz = 0;
438 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
439 footer = ptr;
440 footer_offset = XEN_NOTE_SIZE;
443 if (image_target->id == IMAGE_XEN_PVH)
445 char *note_start = (elf_img + program_size + header_size);
446 Elf_Nhdr *note_ptr;
447 char *ptr = (char *) note_start;
449 grub_util_info ("adding XEN NOTE segment");
451 /* Phys32 Entry. */
452 note_ptr = (Elf_Nhdr *) ptr;
453 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
454 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
455 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PHYS32_ENTRY);
456 ptr += sizeof (Elf_Nhdr);
457 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
458 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
459 memset (ptr, 0, image_target->voidp_sizeof);
460 *(grub_uint32_t *) ptr = GRUB_KERNEL_I386_XEN_PVH_LINK_ADDR;
461 ptr += image_target->voidp_sizeof;
463 assert (XEN_PVH_NOTE_SIZE == (ptr - note_start));
465 phdr++;
466 phdr->p_type = grub_host_to_target32 (PT_NOTE);
467 phdr->p_flags = grub_host_to_target32 (PF_R);
468 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
469 phdr->p_vaddr = 0;
470 phdr->p_paddr = 0;
471 phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
472 phdr->p_memsz = 0;
473 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
474 footer = ptr;
475 footer_offset = XEN_PVH_NOTE_SIZE;
478 if (note)
480 int note_size = sizeof (struct grub_ieee1275_note);
481 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
482 (elf_img + program_size + header_size);
484 grub_util_info ("adding CHRP NOTE segment");
486 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
487 note_ptr->header.n_descsz = grub_host_to_target32 (sizeof (struct grub_ieee1275_note_desc));
488 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
489 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
490 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
491 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
492 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
493 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
494 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
495 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
497 phdr++;
498 phdr->p_type = grub_host_to_target32 (PT_NOTE);
499 phdr->p_flags = grub_host_to_target32 (PF_R);
500 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
501 phdr->p_vaddr = 0;
502 phdr->p_paddr = 0;
503 phdr->p_filesz = grub_host_to_target32 (note_size);
504 phdr->p_memsz = 0;
505 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
506 footer = (elf_img + program_size + header_size + note_size);
507 footer_offset += note_size;
510 if (sbat)
512 int note_size = ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
513 struct grub_sbat_note *note_ptr = (struct grub_sbat_note *) footer;
515 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_SBAT_NOTE_NAME));
516 note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(layout->sbat_size, 4));
517 note_ptr->header.n_type = grub_host_to_target32 (GRUB_SBAT_NOTE_TYPE);
518 memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME));
519 memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size);
521 phdr++;
522 phdr->p_type = grub_host_to_target32 (PT_NOTE);
523 phdr->p_flags = grub_host_to_target32 (PF_R);
524 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
525 phdr->p_vaddr = 0;
526 phdr->p_paddr = 0;
527 phdr->p_filesz = grub_host_to_target32 (note_size);
528 phdr->p_memsz = 0;
529 phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
533 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
534 + shnum * sizeof (*shdr));
535 char *ptr = str_start + 1;
537 shdr++;
539 shdr->sh_name = grub_host_to_target32 (0);
540 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
541 shdr->sh_addr = grub_host_to_target_addr (0);
542 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
543 shdr->sh_size = grub_host_to_target32 (string_size);
544 shdr->sh_link = grub_host_to_target32 (0);
545 shdr->sh_info = grub_host_to_target32 (0);
546 shdr->sh_addralign = grub_host_to_target32 (layout->align);
547 shdr->sh_entsize = grub_host_to_target32 (0);
548 shdr++;
550 memcpy (ptr, ".text", sizeof (".text"));
552 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
553 ptr += sizeof (".text");
554 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
555 shdr->sh_addr = grub_host_to_target_addr (target_addr);
556 shdr->sh_offset = grub_host_to_target_addr (header_size);
557 shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
558 shdr->sh_link = grub_host_to_target32 (0);
559 shdr->sh_info = grub_host_to_target32 (0);
560 shdr->sh_addralign = grub_host_to_target32 (layout->align);
561 shdr->sh_entsize = grub_host_to_target32 (0);
562 shdr++;
564 memcpy (ptr, "mods", sizeof ("mods"));
565 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
566 ptr += sizeof ("mods");
567 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
568 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
569 shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
570 shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
571 shdr->sh_link = grub_host_to_target32 (0);
572 shdr->sh_info = grub_host_to_target32 (0);
573 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
574 shdr->sh_entsize = grub_host_to_target32 (0);
575 shdr++;
577 if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
579 memcpy (ptr, ".xen", sizeof (".xen"));
580 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
581 ptr += sizeof (".xen");
582 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
583 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
584 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
585 if (image_target->id == IMAGE_XEN)
586 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
587 else
588 shdr->sh_size = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
589 shdr->sh_link = grub_host_to_target32 (0);
590 shdr->sh_info = grub_host_to_target32 (0);
591 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
592 shdr->sh_entsize = grub_host_to_target32 (0);
593 shdr++;
597 free (*core_img);
598 *core_img = elf_img;
599 *core_size = program_size + header_size + footer_size;
602 /* Relocate symbols; note that this function overwrites the symbol table.
603 Return the address of a start symbol. */
604 static Elf_Addr
605 SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
606 void *jumpers, Elf_Addr jumpers_addr,
607 Elf_Addr bss_start, Elf_Addr end,
608 const struct grub_install_image_target_desc *image_target)
610 Elf_Word symtab_size, sym_size, num_syms;
611 Elf_Off symtab_offset;
612 Elf_Addr start_address = (Elf_Addr) -1;
613 Elf_Sym *sym;
614 Elf_Word i;
615 Elf_Shdr *symtab_section;
616 const char *symtab;
617 grub_uint64_t *jptr = jumpers;
619 symtab_section = (Elf_Shdr *) ((char *) smd->sections
620 + grub_target_to_host32 (smd->symtab->sh_link)
621 * smd->section_entsize);
622 symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
624 symtab_size = grub_target_to_host (smd->symtab->sh_size);
625 sym_size = grub_target_to_host (smd->symtab->sh_entsize);
626 symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
627 num_syms = symtab_size / sym_size;
629 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
630 i < num_syms;
631 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
633 Elf_Section cur_index;
634 const char *name;
636 name = symtab + grub_target_to_host32 (sym->st_name);
638 cur_index = grub_target_to_host16 (sym->st_shndx);
639 if (cur_index == STN_ABS)
641 continue;
643 else if (cur_index == STN_UNDEF)
645 if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
646 sym->st_value = bss_start;
647 else if (sym->st_name && grub_strcmp (name, "_end") == 0)
648 sym->st_value = end;
649 else if (sym->st_name)
650 grub_util_error ("undefined symbol %s", name);
651 else
652 continue;
654 else if (cur_index >= smd->num_sections)
655 grub_util_error ("section %d does not exist", cur_index);
656 else
658 sym->st_value = (grub_target_to_host (sym->st_value)
659 + smd->vaddrs[cur_index]);
662 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
663 == STT_FUNC)
665 *jptr = grub_host_to_target64 (sym->st_value);
666 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
667 jptr++;
668 *jptr = 0;
669 jptr++;
671 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
672 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
673 (unsigned long long) sym->st_value,
674 (unsigned long long) smd->vaddrs[cur_index]);
676 if (start_address == (Elf_Addr)-1)
677 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
678 start_address = sym->st_value;
681 return start_address;
684 /* Return the address of a symbol at the index I in the section S. */
685 static Elf_Addr
686 SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
687 const struct grub_install_image_target_desc *image_target)
689 Elf_Sym *sym;
691 sym = (Elf_Sym *) ((char *) e
692 + grub_target_to_host (s->sh_offset)
693 + i * grub_target_to_host (s->sh_entsize));
694 return sym->st_value;
697 /* Return the address of a modified value. */
698 static Elf_Addr *
699 SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
700 const struct grub_install_image_target_desc *image_target)
702 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
705 #ifdef MKIMAGE_ELF64
706 static Elf_Addr
707 SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
708 const struct grub_install_image_target_desc *image_target)
710 Elf_Word symtab_size, sym_size, num_syms;
711 Elf_Off symtab_offset;
712 Elf_Sym *sym;
713 Elf_Word i;
714 int ret = 0;
716 symtab_size = grub_target_to_host (symtab_section->sh_size);
717 sym_size = grub_target_to_host (symtab_section->sh_entsize);
718 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
719 num_syms = symtab_size / sym_size;
721 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
722 i < num_syms;
723 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
724 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
725 ret++;
727 return ret;
729 #endif
731 #ifdef MKIMAGE_ELF32
732 /* Deal with relocation information. This function relocates addresses
733 within the virtual address space starting from 0. So only relative
734 addresses can be fully resolved. Absolute addresses must be relocated
735 again by a PE32 relocator when loaded. */
736 static grub_size_t
737 arm_get_trampoline_size (Elf_Ehdr *e,
738 Elf_Shdr *sections,
739 Elf_Half section_entsize,
740 Elf_Half num_sections,
741 const struct grub_install_image_target_desc *image_target)
743 Elf_Half i;
744 Elf_Shdr *s;
745 grub_size_t ret = 0;
747 for (i = 0, s = sections;
748 i < num_sections;
749 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
750 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
751 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
753 Elf_Rela *r;
754 Elf_Word rtab_size, r_size, num_rs;
755 Elf_Off rtab_offset;
756 Elf_Shdr *symtab_section;
757 Elf_Word j;
759 symtab_section = (Elf_Shdr *) ((char *) sections
760 + (grub_target_to_host32 (s->sh_link)
761 * section_entsize));
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);
769 j < num_rs;
770 j++, r = (Elf_Rela *) ((char *) r + r_size))
772 Elf_Addr info;
773 Elf_Addr sym_addr;
775 info = grub_target_to_host (r->r_info);
776 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
777 ELF_R_SYM (info), image_target);
779 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
780 grub_target_to_host (r->r_addend) : 0;
782 switch (ELF_R_TYPE (info))
784 case R_ARM_ABS32:
785 case R_ARM_V4BX:
786 break;
787 case R_ARM_THM_CALL:
788 case R_ARM_THM_JUMP24:
789 case R_ARM_THM_JUMP19:
790 if (!(sym_addr & 1))
791 ret += 8;
792 break;
794 case R_ARM_CALL:
795 case R_ARM_JUMP24:
796 if (sym_addr & 1)
797 ret += 16;
798 break;
800 default:
801 grub_util_error (_("relocation 0x%x is not implemented yet"),
802 (unsigned int) ELF_R_TYPE (info));
803 break;
807 return ret;
809 #endif
811 static int
812 SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target);
813 static int
814 SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
815 struct section_metadata *smd);
817 /* Deal with relocation information. This function relocates addresses
818 within the virtual address space starting from 0. So only relative
819 addresses can be fully resolved. Absolute addresses must be relocated
820 again by a PE32 relocator when loaded. */
821 static void
822 SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
823 char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
824 const struct grub_install_image_target_desc *image_target)
826 Elf_Half i;
827 Elf_Shdr *s;
828 #ifdef MKIMAGE_ELF64
829 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
830 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
831 unsigned unmatched_adr_got_page = 0;
832 struct grub_loongarch64_stack stack;
833 grub_loongarch64_stack_init (&stack);
834 #define MASK19 ((1 << 19) - 1)
835 #else
836 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
837 #endif
839 for (i = 0, s = smd->sections;
840 i < smd->num_sections;
841 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
842 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
843 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
845 Elf_Rela *r;
846 Elf_Word rtab_size, r_size, num_rs;
847 Elf_Off rtab_offset;
848 Elf_Word target_section_index;
849 Elf_Addr target_section_addr;
850 Elf_Shdr *target_section;
851 Elf_Word j;
853 if (!SUFFIX (is_kept_section) (s, image_target) &&
854 !SUFFIX (is_kept_reloc_section) (s, image_target, smd))
856 grub_util_info ("not translating relocations for omitted section %s",
857 smd->strtab + grub_le_to_cpu32 (s->sh_name));
858 continue;
861 target_section_index = grub_target_to_host32 (s->sh_info);
862 target_section_addr = smd->addrs[target_section_index];
863 target_section = (Elf_Shdr *) ((char *) smd->sections
864 + (target_section_index
865 * smd->section_entsize));
867 grub_util_info ("dealing with the relocation section %s for %s",
868 smd->strtab + grub_target_to_host32 (s->sh_name),
869 smd->strtab + grub_target_to_host32 (target_section->sh_name));
871 rtab_size = grub_target_to_host (s->sh_size);
872 r_size = grub_target_to_host (s->sh_entsize);
873 rtab_offset = grub_target_to_host (s->sh_offset);
874 num_rs = rtab_size / r_size;
876 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
877 j < num_rs;
878 j++, r = (Elf_Rela *) ((char *) r + r_size))
880 Elf_Addr info;
881 Elf_Addr offset;
882 Elf_Addr sym_addr;
883 Elf_Addr *target;
884 Elf_Addr addend;
886 offset = grub_target_to_host (r->r_offset);
887 target = SUFFIX (get_target_address) (e, target_section,
888 offset, image_target);
889 info = grub_target_to_host (r->r_info);
890 sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
891 ELF_R_SYM (info), image_target);
893 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
894 grub_target_to_host (r->r_addend) : 0;
896 switch (image_target->elf_target)
898 case EM_386:
899 switch (ELF_R_TYPE (info))
901 case R_386_NONE:
902 break;
904 case R_386_32:
905 /* This is absolute. */
906 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
907 + addend + sym_addr);
908 grub_util_info ("relocating an R_386_32 entry to 0x%"
909 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
910 GRUB_HOST_PRIxLONG_LONG,
911 (unsigned long long) *target,
912 (unsigned long long) offset);
913 break;
915 case R_386_PC32:
916 /* This is relative. */
917 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
918 + addend + sym_addr
919 - target_section_addr - offset
920 - image_target->vaddr_offset);
921 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
922 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
923 GRUB_HOST_PRIxLONG_LONG,
924 (unsigned long long) *target,
925 (unsigned long long) offset);
926 break;
927 default:
928 grub_util_error (_("relocation 0x%x is not implemented yet"),
929 (unsigned int) ELF_R_TYPE (info));
930 break;
932 break;
933 #ifdef MKIMAGE_ELF64
934 case EM_X86_64:
935 switch (ELF_R_TYPE (info))
938 case R_X86_64_NONE:
939 break;
941 case R_X86_64_64:
942 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
943 + addend + sym_addr);
944 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
945 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
946 GRUB_HOST_PRIxLONG_LONG,
947 (unsigned long long) *target,
948 (unsigned long long) offset);
949 break;
951 case R_X86_64_PC32:
952 case R_X86_64_PLT32:
954 grub_uint32_t *t32 = (grub_uint32_t *) target;
955 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
956 + addend + sym_addr
957 - target_section_addr - offset
958 - image_target->vaddr_offset);
959 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
960 GRUB_HOST_PRIxLONG_LONG,
961 *t32, (unsigned long long) offset);
962 break;
965 case R_X86_64_PC64:
967 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
968 + addend + sym_addr
969 - target_section_addr - offset
970 - image_target->vaddr_offset);
971 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
972 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
973 GRUB_HOST_PRIxLONG_LONG,
974 (unsigned long long) *target,
975 (unsigned long long) offset);
976 break;
979 case R_X86_64_32:
980 case R_X86_64_32S:
982 grub_uint32_t *t32 = (grub_uint32_t *) target;
983 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
984 + addend + sym_addr);
985 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
986 GRUB_HOST_PRIxLONG_LONG,
987 *t32, (unsigned long long) offset);
988 break;
991 default:
992 grub_util_error (_("relocation 0x%x is not implemented yet"),
993 (unsigned int) ELF_R_TYPE (info));
994 break;
996 break;
997 case EM_IA_64:
998 switch (ELF_R_TYPE (info))
1000 case R_IA64_PCREL21B:
1002 grub_uint64_t noff;
1003 grub_ia64_make_trampoline (tr, addend + sym_addr);
1004 noff = ((char *) tr - (char *) pe_target
1005 - target_section_addr - (offset & ~3)) >> 4;
1006 tr++;
1007 if (noff & ~MASK19)
1008 grub_util_error ("trampoline offset too big (%"
1009 GRUB_HOST_PRIxLONG_LONG ")",
1010 (unsigned long long) noff);
1011 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
1013 break;
1015 case R_IA64_LTOFF22X:
1016 case R_IA64_LTOFF22:
1018 Elf_Sym *sym;
1020 sym = (Elf_Sym *) ((char *) e
1021 + grub_target_to_host (smd->symtab->sh_offset)
1022 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
1023 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
1024 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
1025 + sym->st_value
1026 - image_target->vaddr_offset));
1028 /* FALLTHROUGH */
1029 case R_IA64_LTOFF_FPTR22:
1030 *gpptr = grub_host_to_target64 (addend + sym_addr);
1031 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
1032 (char *) gpptr - (char *) pe_target
1033 + image_target->vaddr_offset);
1034 gpptr++;
1035 break;
1037 case R_IA64_GPREL22:
1038 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
1039 addend + sym_addr);
1040 break;
1041 case R_IA64_GPREL64I:
1042 grub_ia64_set_immu64 ((grub_addr_t) target,
1043 addend + sym_addr);
1044 break;
1045 case R_IA64_PCREL64LSB:
1046 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1047 + addend + sym_addr
1048 - target_section_addr - offset
1049 - image_target->vaddr_offset);
1050 break;
1052 case R_IA64_SEGREL64LSB:
1053 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1054 + addend + sym_addr - target_section_addr);
1055 break;
1056 case R_IA64_DIR64LSB:
1057 case R_IA64_FPTR64LSB:
1058 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1059 + addend + sym_addr);
1060 grub_util_info ("relocating a direct entry to 0x%"
1061 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
1062 GRUB_HOST_PRIxLONG_LONG,
1063 (unsigned long long)
1064 grub_target_to_host64 (*target),
1065 (unsigned long long) offset);
1066 break;
1068 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
1069 case R_IA64_LDXMOV:
1070 break;
1072 default:
1073 grub_util_error (_("relocation 0x%x is not implemented yet"),
1074 (unsigned int) ELF_R_TYPE (info));
1075 break;
1077 break;
1078 case EM_AARCH64:
1080 sym_addr += addend;
1081 switch (ELF_R_TYPE (info))
1083 case R_AARCH64_ABS64:
1085 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
1087 break;
1088 case R_AARCH64_PREL32:
1090 grub_uint32_t *t32 = (grub_uint32_t *) target;
1091 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
1092 + sym_addr
1093 - target_section_addr - offset
1094 - image_target->vaddr_offset);
1095 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
1096 GRUB_HOST_PRIxLONG_LONG,
1097 *t32, (unsigned long long) offset);
1098 break;
1100 case R_AARCH64_ADD_ABS_LO12_NC:
1101 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
1102 sym_addr);
1103 break;
1104 case R_AARCH64_LDST64_ABS_LO12_NC:
1105 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
1106 sym_addr);
1107 break;
1108 case R_AARCH64_JUMP26:
1109 case R_AARCH64_CALL26:
1111 sym_addr -= offset;
1112 sym_addr -= target_section_addr + image_target->vaddr_offset;
1113 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1114 grub_util_error ("%s", "CALL26 Relocation out of range");
1116 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1117 sym_addr);
1119 break;
1120 case R_AARCH64_ADR_GOT_PAGE:
1122 Elf64_Rela *rel2;
1123 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1124 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1125 unsigned k;
1126 *gpptr = grub_host_to_target64 (sym_addr);
1127 unmatched_adr_got_page++;
1128 if (!grub_arm64_check_hi21_signed (gpoffset))
1129 grub_util_error ("HI21 out of range");
1130 grub_arm64_set_hi21((grub_uint32_t *)target,
1131 gpoffset);
1132 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1133 k < num_rs;
1134 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1135 if (ELF_R_SYM (rel2->r_info)
1136 == ELF_R_SYM (r->r_info)
1137 && r->r_addend == rel2->r_addend
1138 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1140 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1141 grub_target_to_host (rel2->r_offset), image_target),
1142 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1143 break;
1145 if (k >= num_rs)
1146 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1147 gpptr++;
1149 break;
1150 case R_AARCH64_LD64_GOT_LO12_NC:
1151 if (unmatched_adr_got_page == 0)
1152 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1153 unmatched_adr_got_page--;
1154 break;
1155 case R_AARCH64_ADR_PREL_PG_HI21:
1157 sym_addr &= ~0xfffULL;
1158 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1159 if (!grub_arm64_check_hi21_signed (sym_addr))
1160 grub_util_error ("%s", "CALL26 Relocation out of range");
1162 grub_arm64_set_hi21((grub_uint32_t *)target,
1163 sym_addr);
1165 break;
1166 default:
1167 grub_util_error (_("relocation 0x%x is not implemented yet"),
1168 (unsigned int) ELF_R_TYPE (info));
1169 break;
1171 break;
1173 case EM_LOONGARCH:
1175 grub_int64_t pc;
1177 grub_uint32_t *t32 = (grub_uint32_t *) target;
1178 sym_addr += addend;
1180 pc = offset + target_section_addr + image_target->vaddr_offset;
1182 switch (ELF_R_TYPE (info))
1184 case R_LARCH_64:
1186 grub_uint64_t *t64 = (grub_uint64_t *) target;
1187 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
1189 break;
1190 case R_LARCH_MARK_LA:
1191 break;
1192 case R_LARCH_SOP_PUSH_PCREL:
1193 case R_LARCH_SOP_PUSH_PLT_PCREL:
1194 grub_loongarch64_sop_push (&stack, sym_addr
1195 -(target_section_addr
1196 +offset
1197 +image_target->vaddr_offset));
1198 break;
1199 case R_LARCH_B26:
1201 grub_int64_t off;
1203 off = sym_addr - pc;
1205 grub_loongarch64_b26 (t32, off);
1207 break;
1208 case R_LARCH_ABS_HI20:
1209 grub_loongarch64_xxx_hi20 (t32, sym_addr);
1210 break;
1211 case R_LARCH_ABS64_LO20:
1212 grub_loongarch64_abs64_lo20 (t32, sym_addr);
1213 break;
1214 case R_LARCH_ABS64_HI12:
1215 grub_loongarch64_abs64_hi12 (t32, sym_addr);
1216 break;
1217 case R_LARCH_PCALA_HI20:
1219 grub_int32_t hi20;
1221 hi20 = (((sym_addr + 0x800) & ~0xfffULL) - (pc & ~0xfffULL));
1223 grub_loongarch64_xxx_hi20 (t32, hi20);
1225 break;
1226 case R_LARCH_ABS_LO12:
1227 case R_LARCH_PCALA_LO12:
1228 grub_loongarch64_xxx_lo12 (t32, sym_addr);
1229 break;
1230 GRUB_LOONGARCH64_RELOCATION (&stack, target, sym_addr)
1231 default:
1232 grub_util_error (_("relocation 0x%x is not implemented yet"),
1233 (unsigned int) ELF_R_TYPE (info));
1234 break;
1236 break;
1238 #endif
1239 #if defined(MKIMAGE_ELF32)
1240 case EM_ARM:
1242 sym_addr += addend;
1243 sym_addr -= image_target->vaddr_offset;
1244 switch (ELF_R_TYPE (info))
1246 case R_ARM_ABS32:
1248 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1249 (int) sym_addr, (int) sym_addr);
1250 /* Data will be naturally aligned */
1251 if (image_target->id == IMAGE_EFI)
1252 sym_addr += GRUB_PE32_SECTION_ALIGNMENT;
1253 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1255 break;
1256 /* Happens when compiled with -march=armv4.
1257 Since currently we need at least armv5, keep bx as-is.
1259 case R_ARM_V4BX:
1260 break;
1261 case R_ARM_THM_CALL:
1262 case R_ARM_THM_JUMP24:
1263 case R_ARM_THM_JUMP19:
1265 grub_err_t err;
1266 Elf_Sym *sym;
1267 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1268 (unsigned long) ((char *) target
1269 - (char *) e),
1270 sym_addr);
1271 sym = (Elf_Sym *) ((char *) e
1272 + grub_target_to_host (smd->symtab->sh_offset)
1273 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
1274 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1275 sym_addr |= 1;
1276 if (!(sym_addr & 1))
1278 grub_uint32_t tr_addr;
1279 grub_int32_t new_offset;
1280 tr_addr = (char *) tr - (char *) pe_target
1281 - target_section_addr;
1282 new_offset = sym_addr - tr_addr - 12;
1284 if (!grub_arm_jump24_check_offset (new_offset))
1285 return grub_util_error ("jump24 relocation out of range");
1287 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1288 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1289 tr += 2;
1290 sym_addr = tr_addr | 1;
1292 sym_addr -= offset;
1293 /* Thumb instructions can be 16-bit aligned */
1294 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1295 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1296 else
1297 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1298 sym_addr);
1299 if (err)
1300 grub_util_error ("%s", grub_errmsg);
1302 break;
1304 case R_ARM_CALL:
1305 case R_ARM_JUMP24:
1307 grub_err_t err;
1308 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1309 if (sym_addr & 1)
1311 grub_uint32_t tr_addr;
1312 grub_int32_t new_offset;
1313 tr_addr = (char *) tr - (char *) pe_target
1314 - target_section_addr;
1315 new_offset = sym_addr - tr_addr - 12;
1317 /* There is no immediate version of bx, only register one... */
1318 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1319 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1320 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1321 tr[3] = grub_host_to_target32 (new_offset | 1);
1322 tr += 4;
1323 sym_addr = tr_addr;
1325 sym_addr -= offset;
1326 err = grub_arm_reloc_jump24 (target,
1327 sym_addr);
1328 if (err)
1329 grub_util_error ("%s", grub_errmsg);
1331 break;
1333 default:
1334 grub_util_error (_("relocation 0x%x is not implemented yet"),
1335 (unsigned int) ELF_R_TYPE (info));
1336 break;
1338 break;
1340 #endif /* MKIMAGE_ELF32 */
1341 case EM_RISCV:
1343 grub_uint64_t *t64 = (grub_uint64_t *) target;
1344 grub_uint32_t *t32 = (grub_uint32_t *) target;
1345 grub_uint16_t *t16 = (grub_uint16_t *) target;
1346 grub_uint8_t *t8 = (grub_uint8_t *) target;
1347 grub_int64_t off;
1350 * Instructions and instruction encoding are documented in the RISC-V
1351 * specification. This file is based on version 2.2:
1353 * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
1356 sym_addr += addend;
1357 off = sym_addr - target_section_addr - offset - image_target->vaddr_offset;
1359 switch (ELF_R_TYPE (info))
1361 case R_RISCV_ADD8:
1362 *t8 = *t8 + sym_addr;
1363 break;
1364 case R_RISCV_ADD16:
1365 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) + sym_addr);
1366 break;
1367 case R_RISCV_32:
1368 case R_RISCV_ADD32:
1369 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
1370 break;
1371 case R_RISCV_64:
1372 case R_RISCV_ADD64:
1373 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
1374 break;
1376 case R_RISCV_SUB8:
1377 *t8 = sym_addr - *t8;
1378 break;
1379 case R_RISCV_SUB16:
1380 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) - sym_addr);
1381 break;
1382 case R_RISCV_SUB32:
1383 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) - sym_addr);
1384 break;
1385 case R_RISCV_SUB64:
1386 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) - sym_addr);
1387 break;
1388 case R_RISCV_BRANCH:
1390 grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
1391 grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
1392 grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
1393 grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
1394 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
1395 | imm12 | imm11 | imm10_5 | imm4_1);
1397 break;
1398 case R_RISCV_JAL:
1400 grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
1401 grub_uint32_t imm19_12 = (off & 0xff000);
1402 grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
1403 grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
1404 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
1405 | imm20 | imm19_12 | imm11 | imm10_1);
1407 break;
1408 case R_RISCV_CALL:
1409 case R_RISCV_CALL_PLT:
1411 grub_uint32_t hi20, lo12;
1413 if (off != (grub_int32_t)off)
1414 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
1416 hi20 = (off + 0x800) & 0xfffff000;
1417 lo12 = (off - hi20) & 0xfff;
1418 t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
1419 t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
1421 break;
1422 case R_RISCV_RVC_BRANCH:
1424 grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
1425 grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
1426 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1427 grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
1428 grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
1429 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
1430 | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
1432 break;
1433 case R_RISCV_RVC_JUMP:
1435 grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
1436 grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
1437 grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
1438 grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
1439 grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
1440 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1441 grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
1442 grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
1443 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
1444 | imm11 | imm10 | imm9_8 | imm7 | imm6
1445 | imm5 | imm4 | imm3_1);
1447 break;
1448 case R_RISCV_PCREL_HI20:
1450 grub_int32_t hi20;
1452 if (off != (grub_int32_t)off)
1453 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
1455 hi20 = (off + 0x800) & 0xfffff000;
1456 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
1458 break;
1459 case R_RISCV_PCREL_LO12_I:
1460 case R_RISCV_PCREL_LO12_S:
1462 Elf_Rela *rel2;
1463 Elf_Word k;
1464 /* Search backwards for matching HI20 reloc. */
1465 for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
1466 k > 0;
1467 k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
1469 Elf_Addr rel2_info;
1470 Elf_Addr rel2_offset;
1471 Elf_Addr rel2_sym_addr;
1472 Elf_Addr rel2_addend;
1473 Elf_Addr rel2_loc;
1474 grub_int64_t rel2_off;
1476 rel2_offset = grub_target_to_host (rel2->r_offset);
1477 rel2_info = grub_target_to_host (rel2->r_info);
1478 rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
1480 if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
1481 && rel2_loc == sym_addr)
1483 rel2_sym_addr = SUFFIX (get_symbol_address)
1484 (e, smd->symtab, ELF_R_SYM (rel2_info),
1485 image_target);
1486 rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
1487 grub_target_to_host (rel2->r_addend) : 0;
1488 rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
1489 off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
1491 if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
1492 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
1493 else
1495 grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
1496 grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
1497 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1499 break;
1502 if (k == 0)
1503 grub_util_error ("cannot find matching HI20 relocation");
1505 break;
1506 case R_RISCV_HI20:
1507 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
1508 break;
1509 case R_RISCV_LO12_I:
1511 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1512 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
1514 break;
1515 case R_RISCV_LO12_S:
1517 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1518 grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
1519 grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
1520 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1522 break;
1523 case R_RISCV_RELAX:
1524 break;
1525 default:
1526 grub_util_error (_("relocation 0x%x is not implemented yet"),
1527 (unsigned int) ELF_R_TYPE (info));
1528 break;
1530 break;
1532 default:
1533 grub_util_error ("unknown architecture type %d",
1534 image_target->elf_target);
1540 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1541 after having written to the file OUT. */
1542 static Elf_Addr
1543 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1544 Elf_Addr addr, int flush, Elf_Addr current_address,
1545 const struct grub_install_image_target_desc *image_target)
1547 struct grub_pe32_fixup_block *b;
1549 b = &((*cblock)->b);
1551 /* First, check if it is necessary to write out the current block. */
1552 if ((*cblock)->state)
1554 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
1556 grub_uint32_t size;
1558 if (flush)
1560 /* Add as much padding as necessary to align the address
1561 with a section boundary. */
1562 Elf_Addr next_address;
1563 unsigned padding_size;
1564 size_t cur_index;
1566 next_address = current_address + b->block_size;
1567 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1568 - next_address)
1569 >> 1);
1570 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1571 grub_util_info ("adding %d padding fixup entries", padding_size);
1572 while (padding_size--)
1574 b->entries[cur_index++] = 0;
1575 b->block_size += 2;
1578 else while (b->block_size & (8 - 1))
1580 /* If not aligned with a 32-bit boundary, add
1581 a padding entry. */
1582 size_t cur_index;
1584 grub_util_info ("adding a padding fixup entry");
1585 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1586 b->entries[cur_index] = 0;
1587 b->block_size += 2;
1590 /* Flush it. */
1591 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1592 b->block_size, b->page_rva);
1593 size = b->block_size;
1594 current_address += size;
1595 b->page_rva = grub_host_to_target32 (b->page_rva);
1596 b->block_size = grub_host_to_target32 (b->block_size);
1597 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1598 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1599 *cblock = (*cblock)->next;
1603 b = &((*cblock)->b);
1605 if (! flush)
1607 grub_uint16_t entry;
1608 size_t cur_index;
1610 /* If not allocated yet, allocate a block with enough entries. */
1611 if (! (*cblock)->state)
1613 (*cblock)->state = 1;
1615 /* The spec does not mention the requirement of a Page RVA.
1616 Here, align the address with a 4K boundary for safety. */
1617 b->page_rva = (addr & ~(0x1000 - 1));
1618 b->block_size = sizeof (*b);
1621 /* Sanity check. */
1622 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1623 grub_util_error ("too many fixup entries");
1625 /* Add a new entry. */
1626 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1627 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
1628 b->entries[cur_index] = grub_host_to_target16 (entry);
1629 b->block_size += 2;
1632 return current_address;
1635 struct raw_reloc
1637 struct raw_reloc *next;
1638 grub_uint32_t offset;
1639 enum raw_reloc_type {
1640 RAW_RELOC_NONE = -1,
1641 RAW_RELOC_32 = 0,
1642 RAW_RELOC_MAX = 1,
1643 } type;
1646 struct translate_context
1648 /* PE */
1649 struct fixup_block_list *lst, *lst0;
1650 Elf_Addr current_address;
1652 /* Raw */
1653 struct raw_reloc *raw_relocs;
1656 static void
1657 translate_reloc_start (struct translate_context *ctx,
1658 const struct grub_install_image_target_desc *image_target)
1660 grub_memset (ctx, 0, sizeof (*ctx));
1661 if (image_target->id == IMAGE_EFI)
1663 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1664 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1665 ctx->current_address = 0;
1669 static void
1670 translate_relocation_pe (struct translate_context *ctx,
1671 Elf_Addr addr,
1672 Elf_Addr info,
1673 const struct grub_install_image_target_desc *image_target)
1675 /* Necessary to relocate only absolute addresses. */
1676 switch (image_target->elf_target)
1678 case EM_386:
1679 if (ELF_R_TYPE (info) == R_386_32)
1681 grub_util_info ("adding a relocation entry for 0x%"
1682 GRUB_HOST_PRIxLONG_LONG,
1683 (unsigned long long) addr);
1684 ctx->current_address
1685 = add_fixup_entry (&ctx->lst,
1686 GRUB_PE32_REL_BASED_HIGHLOW,
1687 addr, 0, ctx->current_address,
1688 image_target);
1690 break;
1691 case EM_X86_64:
1692 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1693 (ELF_R_TYPE (info) == R_X86_64_32S))
1695 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1697 else if (ELF_R_TYPE (info) == R_X86_64_64)
1699 grub_util_info ("adding a relocation entry for 0x%"
1700 GRUB_HOST_PRIxLONG_LONG,
1701 (unsigned long long) addr);
1702 ctx->current_address
1703 = add_fixup_entry (&ctx->lst,
1704 GRUB_PE32_REL_BASED_DIR64,
1705 addr,
1706 0, ctx->current_address,
1707 image_target);
1709 break;
1710 case EM_IA_64:
1711 switch (ELF_R_TYPE (info))
1713 case R_IA64_PCREL64LSB:
1714 case R_IA64_LDXMOV:
1715 case R_IA64_PCREL21B:
1716 case R_IA64_LTOFF_FPTR22:
1717 case R_IA64_LTOFF22X:
1718 case R_IA64_LTOFF22:
1719 case R_IA64_GPREL22:
1720 case R_IA64_GPREL64I:
1721 case R_IA64_SEGREL64LSB:
1722 break;
1724 case R_IA64_FPTR64LSB:
1725 case R_IA64_DIR64LSB:
1726 #if 1
1728 grub_util_info ("adding a relocation entry for 0x%"
1729 GRUB_HOST_PRIxLONG_LONG,
1730 (unsigned long long) addr);
1731 ctx->current_address
1732 = add_fixup_entry (&ctx->lst,
1733 GRUB_PE32_REL_BASED_DIR64,
1734 addr,
1735 0, ctx->current_address,
1736 image_target);
1738 #endif
1739 break;
1740 default:
1741 grub_util_error (_("relocation 0x%x is not implemented yet"),
1742 (unsigned int) ELF_R_TYPE (info));
1743 break;
1745 break;
1746 case EM_AARCH64:
1747 #if defined(MKIMAGE_ELF64)
1748 switch (ELF_R_TYPE (info))
1750 case R_AARCH64_ABS64:
1752 ctx->current_address
1753 = add_fixup_entry (&ctx->lst,
1754 GRUB_PE32_REL_BASED_DIR64,
1755 addr, 0, ctx->current_address,
1756 image_target);
1758 break;
1759 /* Relative relocations do not require fixup entries. */
1760 case R_AARCH64_CALL26:
1761 case R_AARCH64_JUMP26:
1762 case R_AARCH64_PREL32:
1763 break;
1764 /* Page-relative relocations do not require fixup entries. */
1765 case R_AARCH64_ADR_PREL_PG_HI21:
1766 /* We page-align the whole kernel, so no need
1767 for fixup entries.
1769 case R_AARCH64_ADD_ABS_LO12_NC:
1770 case R_AARCH64_LDST64_ABS_LO12_NC:
1771 break;
1773 /* GOT is relocated separately. */
1774 case R_AARCH64_ADR_GOT_PAGE:
1775 case R_AARCH64_LD64_GOT_LO12_NC:
1776 break;
1778 default:
1779 grub_util_error (_("relocation 0x%x is not implemented yet"),
1780 (unsigned int) ELF_R_TYPE (info));
1781 break;
1783 #endif /* defined(MKIMAGE_ELF64) */
1784 break;
1785 case EM_LOONGARCH:
1786 #if defined(MKIMAGE_ELF64)
1787 switch (ELF_R_TYPE (info))
1789 case R_LARCH_64:
1791 ctx->current_address = add_fixup_entry (&ctx->lst,
1792 GRUB_PE32_REL_BASED_DIR64,
1793 addr, 0, ctx->current_address,
1794 image_target);
1796 break;
1797 case R_LARCH_MARK_LA:
1799 ctx->current_address = add_fixup_entry (&ctx->lst,
1800 GRUB_PE32_REL_BASED_LOONGARCH64_MARK_LA,
1801 addr, 0, ctx->current_address,
1802 image_target);
1804 break;
1805 /* Relative relocations do not require fixup entries. */
1806 case R_LARCH_NONE:
1807 case R_LARCH_SOP_PUSH_PCREL:
1808 case R_LARCH_SOP_PUSH_ABSOLUTE:
1809 case R_LARCH_SOP_PUSH_PLT_PCREL:
1810 case R_LARCH_SOP_SUB:
1811 case R_LARCH_SOP_SL:
1812 case R_LARCH_SOP_SR:
1813 case R_LARCH_SOP_ADD:
1814 case R_LARCH_SOP_AND:
1815 case R_LARCH_SOP_IF_ELSE:
1816 case R_LARCH_SOP_POP_32_S_10_5:
1817 case R_LARCH_SOP_POP_32_U_10_12:
1818 case R_LARCH_SOP_POP_32_S_10_12:
1819 case R_LARCH_SOP_POP_32_S_10_16:
1820 case R_LARCH_SOP_POP_32_S_10_16_S2:
1821 case R_LARCH_SOP_POP_32_S_5_20:
1822 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
1823 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
1824 case R_LARCH_B26:
1825 case R_LARCH_ABS_HI20:
1826 case R_LARCH_ABS_LO12:
1827 case R_LARCH_ABS64_LO20:
1828 case R_LARCH_ABS64_HI12:
1829 case R_LARCH_PCALA_HI20:
1830 case R_LARCH_PCALA_LO12:
1831 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x",
1832 __FUNCTION__,
1833 (unsigned int) addr,
1834 (unsigned int) ctx->current_address);
1835 break;
1836 default:
1837 grub_util_error (_("relocation 0x%x is not implemented yet"),
1838 (unsigned int) ELF_R_TYPE (info));
1839 break;
1841 #endif /* defined(MKIMAGE_ELF64) */
1842 break;
1843 #if defined(MKIMAGE_ELF32)
1844 case EM_ARM:
1845 switch (ELF_R_TYPE (info))
1847 case R_ARM_V4BX:
1848 /* Relative relocations do not require fixup entries. */
1849 case R_ARM_JUMP24:
1850 case R_ARM_THM_CALL:
1851 case R_ARM_THM_JUMP19:
1852 case R_ARM_THM_JUMP24:
1853 case R_ARM_CALL:
1855 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1857 break;
1858 /* Create fixup entry for PE/COFF loader */
1859 case R_ARM_ABS32:
1861 ctx->current_address
1862 = add_fixup_entry (&ctx->lst,
1863 GRUB_PE32_REL_BASED_HIGHLOW,
1864 addr, 0, ctx->current_address,
1865 image_target);
1867 break;
1868 default:
1869 grub_util_error (_("relocation 0x%x is not implemented yet"),
1870 (unsigned int) ELF_R_TYPE (info));
1871 break;
1873 break;
1874 #endif /* defined(MKIMAGE_ELF32) */
1875 case EM_RISCV:
1876 switch (ELF_R_TYPE (info))
1878 case R_RISCV_32:
1880 ctx->current_address
1881 = add_fixup_entry (&ctx->lst,
1882 GRUB_PE32_REL_BASED_HIGHLOW,
1883 addr, 0, ctx->current_address,
1884 image_target);
1886 break;
1887 case R_RISCV_64:
1889 ctx->current_address
1890 = add_fixup_entry (&ctx->lst,
1891 GRUB_PE32_REL_BASED_DIR64,
1892 addr, 0, ctx->current_address,
1893 image_target);
1895 break;
1896 /* Relative relocations do not require fixup entries. */
1897 case R_RISCV_BRANCH:
1898 case R_RISCV_JAL:
1899 case R_RISCV_CALL:
1900 case R_RISCV_CALL_PLT:
1901 case R_RISCV_PCREL_HI20:
1902 case R_RISCV_PCREL_LO12_I:
1903 case R_RISCV_PCREL_LO12_S:
1904 case R_RISCV_RVC_BRANCH:
1905 case R_RISCV_RVC_JUMP:
1906 case R_RISCV_ADD32:
1907 case R_RISCV_SUB32:
1908 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1909 break;
1910 case R_RISCV_HI20:
1912 ctx->current_address
1913 = add_fixup_entry (&ctx->lst,
1914 GRUB_PE32_REL_BASED_RISCV_HI20,
1915 addr, 0, ctx->current_address,
1916 image_target);
1918 break;
1919 case R_RISCV_LO12_I:
1921 ctx->current_address
1922 = add_fixup_entry (&ctx->lst,
1923 GRUB_PE32_REL_BASED_RISCV_LOW12I,
1924 addr, 0, ctx->current_address,
1925 image_target);
1927 break;
1928 case R_RISCV_LO12_S:
1930 ctx->current_address
1931 = add_fixup_entry (&ctx->lst,
1932 GRUB_PE32_REL_BASED_RISCV_LOW12S,
1933 addr, 0, ctx->current_address,
1934 image_target);
1936 break;
1937 case R_RISCV_RELAX:
1938 break;
1939 default:
1940 grub_util_error (_("relocation 0x%x is not implemented yet"),
1941 (unsigned int) ELF_R_TYPE (info));
1942 break;
1944 break;
1945 default:
1946 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1950 static enum raw_reloc_type
1951 classify_raw_reloc (Elf_Addr info,
1952 const struct grub_install_image_target_desc *image_target)
1954 /* Necessary to relocate only absolute addresses. */
1955 switch (image_target->elf_target)
1957 case EM_ARM:
1958 switch (ELF_R_TYPE (info))
1960 case R_ARM_V4BX:
1961 case R_ARM_JUMP24:
1962 case R_ARM_THM_CALL:
1963 case R_ARM_THM_JUMP19:
1964 case R_ARM_THM_JUMP24:
1965 case R_ARM_CALL:
1966 return RAW_RELOC_NONE;
1967 case R_ARM_ABS32:
1968 return RAW_RELOC_32;
1969 default:
1970 grub_util_error (_("relocation 0x%x is not implemented yet"),
1971 (unsigned int) ELF_R_TYPE (info));
1972 break;
1974 break;
1975 default:
1976 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1980 static void
1981 translate_relocation_raw (struct translate_context *ctx,
1982 Elf_Addr addr,
1983 Elf_Addr info,
1984 const struct grub_install_image_target_desc *image_target)
1986 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
1987 struct raw_reloc *rel;
1988 if (class == RAW_RELOC_NONE)
1989 return;
1990 rel = xmalloc (sizeof (*rel));
1991 rel->next = ctx->raw_relocs;
1992 rel->type = class;
1993 rel->offset = addr;
1994 ctx->raw_relocs = rel;
1997 static void
1998 translate_relocation (struct translate_context *ctx,
1999 Elf_Addr addr,
2000 Elf_Addr info,
2001 const struct grub_install_image_target_desc *image_target)
2003 if (image_target->id == IMAGE_EFI)
2004 translate_relocation_pe (ctx, addr, info, image_target);
2005 else
2006 translate_relocation_raw (ctx, addr, info, image_target);
2009 static void
2010 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2011 const struct grub_install_image_target_desc *image_target)
2013 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
2016 grub_uint8_t *ptr;
2017 layout->reloc_section = ptr = xmalloc (ctx->current_address);
2018 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
2019 if (ctx->lst->state)
2021 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
2022 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
2024 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
2027 for (ctx->lst = ctx->lst0; ctx->lst; )
2029 struct fixup_block_list *next;
2030 next = ctx->lst->next;
2031 free (ctx->lst);
2032 ctx->lst = next;
2035 layout->reloc_size = ctx->current_address;
2036 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
2037 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
2038 "This breaks assembly assumptions. Please increase stack size",
2039 (int) layout->reloc_size,
2040 (int) GRUB_KERNEL_ARM_STACK_SIZE);
2044 Layout:
2045 <type 0 relocations>
2046 <fffffffe>
2047 <type 1 relocations>
2048 <fffffffe>
2050 <type n relocations>
2051 <ffffffff>
2052 each relocation starts with 32-bit offset. Rest depends on relocation.
2053 mkimage stops when it sees first unknown type or end marker.
2054 This allows images to be created with mismatched mkimage and
2055 kernel as long as no relocations are present in kernel that mkimage
2056 isn't aware of (in which case mkimage aborts).
2057 This also allows simple assembly to do the relocs.
2060 #define RAW_SEPARATOR 0xfffffffe
2061 #define RAW_END_MARKER 0xffffffff
2063 static void
2064 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2065 const struct grub_install_image_target_desc *image_target)
2067 size_t count = 0, sz;
2068 enum raw_reloc_type highest = RAW_RELOC_NONE;
2069 enum raw_reloc_type curtype;
2070 struct raw_reloc *cur;
2071 grub_uint32_t *p;
2072 if (!ctx->raw_relocs)
2074 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
2075 p[0] = RAW_END_MARKER;
2076 layout->reloc_size = sizeof (grub_uint32_t);
2077 return;
2079 for (cur = ctx->raw_relocs; cur; cur = cur->next)
2081 count++;
2082 if (cur->type > highest)
2083 highest = cur->type;
2085 /* highest separators, count relocations and one end marker. */
2086 sz = (highest + count + 1) * sizeof (grub_uint32_t);
2087 layout->reloc_section = p = xmalloc (sz);
2088 for (curtype = 0; curtype <= highest; curtype++)
2090 /* Support for special cases would go here. */
2091 for (cur = ctx->raw_relocs; cur; cur = cur->next)
2092 if (cur->type == curtype)
2094 *p++ = cur->offset;
2096 *p++ = RAW_SEPARATOR;
2098 *--p = RAW_END_MARKER;
2099 layout->reloc_size = sz;
2102 static void
2103 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2104 const struct grub_install_image_target_desc *image_target)
2106 if (image_target->id == IMAGE_EFI)
2107 finish_reloc_translation_pe (ctx, layout, image_target);
2108 else
2109 finish_reloc_translation_raw (ctx, layout, image_target);
2113 static void
2114 create_u64_fixups (struct translate_context *ctx,
2115 Elf_Addr jumpers, grub_size_t njumpers,
2116 const struct grub_install_image_target_desc *image_target)
2118 unsigned i;
2119 assert (image_target->id == IMAGE_EFI);
2120 for (i = 0; i < njumpers; i++)
2121 ctx->current_address = add_fixup_entry (&ctx->lst,
2122 GRUB_PE32_REL_BASED_DIR64,
2123 jumpers + 8 * i,
2124 0, ctx->current_address,
2125 image_target);
2128 /* Make a .reloc section. */
2129 static void
2130 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
2131 struct section_metadata *smd,
2132 const struct grub_install_image_target_desc *image_target)
2134 unsigned i;
2135 Elf_Shdr *s;
2136 struct translate_context ctx;
2138 translate_reloc_start (&ctx, image_target);
2140 for (i = 0, s = smd->sections; i < smd->num_sections;
2141 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2142 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
2143 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
2145 Elf_Rel *r;
2146 Elf_Word rtab_size, r_size, num_rs;
2147 Elf_Off rtab_offset;
2148 Elf_Addr section_address;
2149 Elf_Word j;
2151 if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
2153 grub_util_info ("not translating the skipped relocation section %s",
2154 smd->strtab + grub_le_to_cpu32 (s->sh_name));
2155 continue;
2158 grub_util_info ("translating the relocation section %s",
2159 smd->strtab + grub_le_to_cpu32 (s->sh_name));
2161 rtab_size = grub_target_to_host (s->sh_size);
2162 r_size = grub_target_to_host (s->sh_entsize);
2163 rtab_offset = grub_target_to_host (s->sh_offset);
2164 num_rs = rtab_size / r_size;
2166 section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
2168 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
2169 j < num_rs;
2170 j++, r = (Elf_Rel *) ((char *) r + r_size))
2172 Elf_Addr info;
2173 Elf_Addr offset;
2174 Elf_Addr addr;
2176 offset = grub_target_to_host (r->r_offset);
2177 info = grub_target_to_host (r->r_info);
2179 addr = section_address + offset;
2181 translate_relocation (&ctx, addr, info, image_target);
2185 if (image_target->elf_target == EM_IA_64)
2186 create_u64_fixups (&ctx,
2187 layout->ia64jmp_off
2188 + image_target->vaddr_offset,
2189 2 * layout->ia64jmpnum,
2190 image_target);
2191 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
2192 create_u64_fixups (&ctx,
2193 layout->got_off
2194 + image_target->vaddr_offset,
2195 (layout->got_size / 8),
2196 image_target);
2198 finish_reloc_translation (&ctx, layout, image_target);
2201 /* Determine if this section is a text section. Return false if this
2202 section is not allocated. */
2203 static int
2204 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2206 if (!is_relocatable (image_target)
2207 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2208 return 0;
2209 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2210 == (SHF_EXECINSTR | SHF_ALLOC));
2213 /* Determine if this section is a data section. */
2214 static int
2215 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2217 if (!is_relocatable (image_target)
2218 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2219 return 0;
2220 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2221 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2224 static int
2225 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2227 if (!is_relocatable (image_target))
2228 return 0;
2229 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2230 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2233 /* Determine if a section is going to be in the final output */
2234 static int
2235 SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2237 /* We keep .text and .data */
2238 if (SUFFIX (is_text_section) (s, image_target)
2239 || SUFFIX (is_data_section) (s, image_target))
2240 return 1;
2243 * And we keep .bss if we're producing PE binaries or the target doesn't
2244 * have a relocating loader. Platforms other than EFI and U-boot shouldn't
2245 * have .bss in their binaries as we build with -Wl,-Ttext.
2247 if (SUFFIX (is_bss_section) (s, image_target)
2248 && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2249 return 1;
2251 /* Otherwise this is not a section we're keeping in the final output. */
2252 return 0;
2255 static int
2256 SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
2257 struct section_metadata *smd)
2259 int i;
2260 int r = 0;
2261 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2263 if (!strncmp (name, ".rela.", 6))
2264 name += 5;
2265 else if (!strncmp (name, ".rel.", 5))
2266 name += 4;
2267 else
2268 return 1;
2270 for (i = 0, s = smd->sections; i < smd->num_sections;
2271 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2273 const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
2274 if (strcmp (sname, name))
2275 continue;
2277 return SUFFIX (is_kept_section) (s, image_target);
2280 return r;
2283 /* Return if the ELF header is valid. */
2284 static int
2285 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
2287 if (size < sizeof (*e)
2288 || e->e_ident[EI_MAG0] != ELFMAG0
2289 || e->e_ident[EI_MAG1] != ELFMAG1
2290 || e->e_ident[EI_MAG2] != ELFMAG2
2291 || e->e_ident[EI_MAG3] != ELFMAG3
2292 || e->e_ident[EI_VERSION] != EV_CURRENT
2293 || e->e_ident[EI_CLASS] != ELFCLASSXX
2294 || e->e_version != grub_host_to_target32 (EV_CURRENT))
2295 return 0;
2297 return 1;
2300 static Elf_Addr
2301 SUFFIX (put_section) (Elf_Shdr *s, int i,
2302 Elf_Addr current_address,
2303 struct section_metadata *smd,
2304 const struct grub_install_image_target_desc *image_target)
2306 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
2307 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2309 if (align)
2310 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2311 align)
2312 - image_target->vaddr_offset;
2314 grub_util_info ("locating the section %s at 0x%"
2315 GRUB_HOST_PRIxLONG_LONG,
2316 name, (unsigned long long) current_address);
2317 if (!is_relocatable (image_target))
2318 current_address = grub_host_to_target_addr (s->sh_addr)
2319 - image_target->link_addr;
2320 smd->addrs[i] = current_address;
2321 current_address += grub_host_to_target_addr (s->sh_size);
2322 return current_address;
2326 * Locate section addresses by merging code sections and data sections
2327 * into .text and .data, respectively.
2329 static void
2330 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
2331 struct section_metadata *smd,
2332 struct grub_mkimage_layout *layout,
2333 const struct grub_install_image_target_desc *image_target)
2335 int i;
2336 Elf_Shdr *s;
2338 layout->align = 1;
2339 /* Page-aligning simplifies relocation handling. */
2340 if (image_target->elf_target == EM_AARCH64)
2341 layout->align = 4096;
2343 layout->kernel_size = 0;
2345 for (i = 0, s = smd->sections;
2346 i < smd->num_sections;
2347 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2348 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
2349 && grub_host_to_target32 (s->sh_addralign) > layout->align)
2350 layout->align = grub_host_to_target32 (s->sh_addralign);
2352 /* .text */
2353 for (i = 0, s = smd->sections;
2354 i < smd->num_sections;
2355 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2356 if (SUFFIX (is_text_section) (s, image_target))
2358 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
2359 smd, image_target);
2360 if (!is_relocatable (image_target) &&
2361 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
2363 char *msg
2364 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
2365 " instead of 0x%llx: ld.gold bug?"),
2366 kernel_path,
2367 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
2368 (unsigned long long) image_target->link_addr);
2369 grub_util_error ("%s", msg);
2373 #ifdef MKIMAGE_ELF32
2374 if (image_target->elf_target == EM_ARM)
2376 grub_size_t tramp;
2378 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2380 tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
2381 smd->num_sections, image_target);
2383 layout->tramp_off = layout->kernel_size;
2384 layout->kernel_size += ALIGN_UP (tramp, 16);
2386 #endif
2388 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
2389 image_target->section_align)
2390 - image_target->vaddr_offset;
2391 layout->exec_size = layout->kernel_size;
2393 /* .data */
2394 for (i = 0, s = smd->sections;
2395 i < smd->num_sections;
2396 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2397 if (SUFFIX (is_data_section) (s, image_target))
2398 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
2399 image_target);
2401 layout->bss_start = layout->kernel_size;
2402 layout->end = layout->kernel_size;
2404 /* .bss */
2405 for (i = 0, s = smd->sections;
2406 i < smd->num_sections;
2407 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2409 if (SUFFIX (is_bss_section) (s, image_target))
2410 layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
2413 * This must to be in the last time this function passes through the loop.
2415 smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
2418 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
2419 image_target->section_align) - image_target->vaddr_offset;
2420 /* Explicitly initialize BSS
2421 when producing PE32 to avoid a bug in EFI implementations.
2422 Platforms other than EFI and U-boot shouldn't have .bss in
2423 their binaries as we build with -Wl,-Ttext.
2425 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
2426 layout->kernel_size = layout->end;
2429 char *
2430 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
2431 size_t total_module_size,
2432 struct grub_mkimage_layout *layout,
2433 const struct grub_install_image_target_desc *image_target)
2435 char *kernel_img, *out_img;
2436 struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
2437 Elf_Ehdr *e;
2438 int i;
2439 Elf_Shdr *s;
2440 Elf_Off section_offset;
2441 grub_size_t kernel_size;
2443 grub_memset (layout, 0, sizeof (*layout));
2445 layout->start_address = 0;
2447 kernel_size = grub_util_get_image_size (kernel_path);
2448 kernel_img = xmalloc (kernel_size);
2449 grub_util_load_image (kernel_path, kernel_img);
2451 e = (Elf_Ehdr *) kernel_img;
2452 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
2453 grub_util_error ("invalid ELF header");
2455 section_offset = grub_target_to_host (e->e_shoff);
2456 smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
2457 smd.num_sections = grub_target_to_host16 (e->e_shnum);
2459 if (kernel_size < section_offset
2460 + (grub_uint32_t) smd.section_entsize * smd.num_sections)
2461 grub_util_error (_("premature end of file %s"), kernel_path);
2463 smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
2465 /* Relocate sections then symbols in the virtual address space. */
2466 s = (Elf_Shdr *) ((char *) smd.sections
2467 + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
2468 smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
2470 smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs));
2471 smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs));
2473 SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
2475 if (!is_relocatable (image_target))
2477 Elf_Addr current_address = layout->kernel_size;
2478 Elf_Addr bss_start = layout->kernel_size;
2479 bool is_first = true;
2481 for (i = 0, s = smd.sections;
2482 i < smd.num_sections;
2483 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2484 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2486 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
2487 const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
2489 if (sec_align)
2490 current_address = ALIGN_UP (current_address
2491 + image_target->vaddr_offset,
2492 sec_align)
2493 - image_target->vaddr_offset;
2495 grub_util_info ("locating the section %s at 0x%"
2496 GRUB_HOST_PRIxLONG_LONG,
2497 name, (unsigned long long) current_address);
2498 if (!is_relocatable (image_target))
2499 current_address = grub_host_to_target_addr (s->sh_addr)
2500 - image_target->link_addr;
2502 if (is_first == true)
2504 bss_start = current_address;
2505 is_first = false;
2508 smd.vaddrs[i] = current_address
2509 + image_target->vaddr_offset;
2510 current_address += grub_host_to_target_addr (s->sh_size);
2512 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2513 image_target->section_align)
2514 - image_target->vaddr_offset;
2516 if (image_target->id == IMAGE_YEELOONG_FLASH
2517 || image_target->id == IMAGE_FULOONG2F_FLASH
2518 || image_target->id == IMAGE_LOONGSON_ELF
2519 || image_target->id == IMAGE_QEMU_MIPS_FLASH
2520 || image_target->id == IMAGE_MIPS_ARC)
2522 layout->kernel_size = bss_start;
2525 layout->bss_size = current_address - layout->kernel_size;
2527 else
2528 layout->bss_size = 0;
2530 if (image_target->id == IMAGE_SPARC64_AOUT
2531 || image_target->id == IMAGE_SPARC64_RAW
2532 || image_target->id == IMAGE_UBOOT
2533 || image_target->id == IMAGE_COREBOOT
2534 || image_target->id == IMAGE_SPARC64_CDCORE)
2535 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
2537 if (is_relocatable (image_target))
2539 smd.symtab = NULL;
2540 for (i = 0, s = smd.sections;
2541 i < smd.num_sections;
2542 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2543 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2545 smd.symtab = s;
2546 break;
2548 if (! smd.symtab)
2549 grub_util_error ("%s", _("no symbol table"));
2550 #ifdef MKIMAGE_ELF64
2551 if (image_target->elf_target == EM_IA_64)
2553 grub_size_t tramp;
2555 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2557 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2559 layout->tramp_off = layout->kernel_size;
2560 layout->kernel_size += ALIGN_UP (tramp, 16);
2562 layout->ia64jmp_off = layout->kernel_size;
2563 layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
2564 image_target);
2565 layout->kernel_size += 16 * layout->ia64jmpnum;
2567 layout->got_off = layout->kernel_size;
2568 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2570 if (image_target->elf_target == EM_AARCH64)
2572 grub_size_t tramp;
2574 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2576 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2578 layout->got_off = layout->kernel_size;
2579 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2581 #endif
2583 if (image_target->id == IMAGE_EFI)
2584 layout->kernel_size = ALIGN_UP (layout->kernel_size,
2585 GRUB_PE32_FILE_ALIGNMENT);
2587 else
2589 layout->reloc_size = 0;
2590 layout->reloc_section = NULL;
2593 out_img = xmalloc (layout->kernel_size + total_module_size);
2594 memset (out_img, 0, layout->kernel_size + total_module_size);
2596 if (is_relocatable (image_target))
2598 layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
2599 (char *) out_img + layout->ia64jmp_off,
2600 layout->ia64jmp_off + image_target->vaddr_offset,
2601 layout->bss_start, layout->end, image_target);
2603 if (layout->start_address == (Elf_Addr) -1)
2604 grub_util_error ("start symbol is not defined");
2606 /* Resolve addrs in the virtual address space. */
2607 SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
2608 layout->got_off, image_target);
2610 make_reloc_section (e, layout, &smd, image_target);
2611 if (image_target->id != IMAGE_EFI)
2613 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2614 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2615 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2616 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2617 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2618 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2622 for (i = 0, s = smd.sections;
2623 i < smd.num_sections;
2624 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2625 if (SUFFIX (is_kept_section) (s, image_target))
2627 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2628 memset (out_img + smd.addrs[i], 0,
2629 grub_host_to_target_addr (s->sh_size));
2630 else
2631 memcpy (out_img + smd.addrs[i],
2632 kernel_img + grub_host_to_target_addr (s->sh_offset),
2633 grub_host_to_target_addr (s->sh_size));
2635 free (kernel_img);
2637 free (smd.vaddrs);
2638 smd.vaddrs = NULL;
2639 free (smd.addrs);
2640 smd.addrs = NULL;
2642 return out_img;