]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/util/grub-mkimagexx.c
Fix the syntax error in F4 localboot
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / util / grub-mkimagexx.c
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.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
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>
36
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/osdep/hostfile.h>
48 #include <grub/util/install.h>
49 #include <grub/util/mkimage.h>
50
51 #include <xen/elfnote.h>
52
53 #pragma GCC diagnostic ignored "-Wcast-align"
54
55 #define GRUB_MKIMAGEXX
56 #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
57 #if __SIZEOF_POINTER__ == 8
58 #include "grub-mkimage64.c"
59 #else
60 #include "grub-mkimage32.c"
61 #endif
62 #endif
63
64 /* These structures are defined according to the CHRP binding to IEEE1275,
65 "Client Program Format" section. */
66
67 struct grub_ieee1275_note_desc
68 {
69 grub_uint32_t real_mode;
70 grub_uint32_t real_base;
71 grub_uint32_t real_size;
72 grub_uint32_t virt_base;
73 grub_uint32_t virt_size;
74 grub_uint32_t load_base;
75 };
76
77 #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
78 #define GRUB_IEEE1275_NOTE_TYPE 0x1275
79
80 struct grub_ieee1275_note
81 {
82 Elf32_Nhdr header;
83 char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
84 struct grub_ieee1275_note_desc descriptor;
85 };
86
87 #define GRUB_XEN_NOTE_NAME "Xen"
88
89 struct fixup_block_list
90 {
91 struct fixup_block_list *next;
92 int state;
93 struct grub_pe32_fixup_block b;
94 };
95
96 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
97
98 struct section_metadata
99 {
100 Elf_Half num_sections;
101 Elf_Shdr *sections;
102 Elf_Addr *addrs;
103 Elf_Addr *vaddrs;
104 Elf_Half section_entsize;
105 Elf_Shdr *symtab;
106 const char *strtab;
107 };
108
109 static int
110 is_relocatable (const struct grub_install_image_target_desc *image_target)
111 {
112 return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
113 || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
114 }
115
116 #ifdef MKIMAGE_ELF32
117
118 /*
119 * R_ARM_THM_CALL/THM_JUMP24
120 *
121 * Relocate Thumb (T32) instruction set relative branches:
122 * B.W, BL and BLX
123 */
124 static grub_err_t
125 grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
126 {
127 grub_int32_t offset;
128
129 offset = grub_arm_thm_call_get_offset (target);
130
131 grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
132
133 offset += sym_addr;
134
135 grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
136 target, sym_addr, offset);
137
138 /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
139 is bigger than 2M (currently under 150K) then we probably have a problem
140 somewhere else. */
141 if (offset < -0x200000 || offset >= 0x200000)
142 return grub_error (GRUB_ERR_BAD_MODULE,
143 "THM_CALL Relocation out of range.");
144
145 grub_dprintf ("dl", " relative destination = %p",
146 (char *) target + offset);
147
148 return grub_arm_thm_call_set_offset (target, offset);
149 }
150
151 /*
152 * R_ARM_THM_JUMP19
153 *
154 * Relocate conditional Thumb (T32) B<c>.W
155 */
156 static grub_err_t
157 grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
158 {
159 grub_int32_t offset;
160
161 if (!(sym_addr & 1))
162 return grub_error (GRUB_ERR_BAD_MODULE,
163 "Relocation targeting wrong execution state");
164
165 offset = grub_arm_thm_jump19_get_offset (target);
166
167 /* Adjust and re-truncate offset */
168 offset += sym_addr;
169
170 if (!grub_arm_thm_jump19_check_offset (offset))
171 return grub_error (GRUB_ERR_BAD_MODULE,
172 "THM_JUMP19 Relocation out of range.");
173
174 grub_arm_thm_jump19_set_offset (target, offset);
175
176 return GRUB_ERR_NONE;
177 }
178
179 /*
180 * R_ARM_JUMP24
181 *
182 * Relocate ARM (A32) B
183 */
184 static grub_err_t
185 grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
186 {
187 grub_int32_t offset;
188
189 if (sym_addr & 1)
190 return grub_error (GRUB_ERR_BAD_MODULE,
191 "Relocation targeting wrong execution state");
192
193 offset = grub_arm_jump24_get_offset (target);
194 offset += sym_addr;
195
196 if (!grub_arm_jump24_check_offset (offset))
197 return grub_error (GRUB_ERR_BAD_MODULE,
198 "JUMP24 Relocation out of range.");
199
200
201 grub_arm_jump24_set_offset (target, offset);
202
203 return GRUB_ERR_NONE;
204 }
205
206 #endif
207
208 void
209 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
210 int note, char **core_img, size_t *core_size,
211 Elf_Addr target_addr,
212 struct grub_mkimage_layout *layout)
213 {
214 char *elf_img;
215 size_t program_size;
216 Elf_Ehdr *ehdr;
217 Elf_Phdr *phdr;
218 Elf_Shdr *shdr;
219 int header_size, footer_size = 0;
220 int phnum = 1;
221 int shnum = 4;
222 int string_size = sizeof (".text") + sizeof ("mods") + 1;
223
224 if (image_target->id != IMAGE_LOONGSON_ELF)
225 phnum += 2;
226
227 if (note)
228 {
229 phnum++;
230 footer_size += sizeof (struct grub_ieee1275_note);
231 }
232 if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
233 {
234 phnum++;
235 shnum++;
236 string_size += sizeof (".xen");
237 footer_size += (image_target->id == IMAGE_XEN) ? XEN_NOTE_SIZE : XEN_PVH_NOTE_SIZE;
238 }
239 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
240 + shnum * sizeof (*shdr) + string_size, layout->align);
241
242 program_size = ALIGN_ADDR (*core_size);
243
244 elf_img = xmalloc (program_size + header_size + footer_size);
245 memset (elf_img, 0, program_size + header_size + footer_size);
246 memcpy (elf_img + header_size, *core_img, *core_size);
247 ehdr = (void *) elf_img;
248 phdr = (void *) (elf_img + sizeof (*ehdr));
249 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
250 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
251 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
252 if (!image_target->bigendian)
253 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
254 else
255 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
256 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
257 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
258 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
259 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
260 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
261
262 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
263 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
264 ehdr->e_phnum = grub_host_to_target16 (phnum);
265
266 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
267 - (grub_uint8_t *) ehdr);
268 if (image_target->id == IMAGE_LOONGSON_ELF)
269 ehdr->e_shentsize = grub_host_to_target16 (0);
270 else
271 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
272 ehdr->e_shnum = grub_host_to_target16 (shnum);
273 ehdr->e_shstrndx = grub_host_to_target16 (1);
274
275 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
276
277 phdr->p_type = grub_host_to_target32 (PT_LOAD);
278 phdr->p_offset = grub_host_to_target32 (header_size);
279 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
280
281 ehdr->e_entry = grub_host_to_target32 (target_addr);
282 phdr->p_vaddr = grub_host_to_target32 (target_addr);
283 phdr->p_paddr = grub_host_to_target32 (target_addr);
284 phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
285 layout->align : image_target->link_align);
286 if (image_target->id == IMAGE_LOONGSON_ELF)
287 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
288 | EF_MIPS_PIC | EF_MIPS_CPIC);
289 else
290 ehdr->e_flags = 0;
291 if (image_target->id == IMAGE_LOONGSON_ELF)
292 {
293 phdr->p_filesz = grub_host_to_target32 (*core_size);
294 phdr->p_memsz = grub_host_to_target32 (*core_size);
295 }
296 else
297 {
298 grub_uint32_t target_addr_mods;
299 phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
300 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
301 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
302 else
303 phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
304
305 phdr++;
306 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
307 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
308 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
309 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
310 phdr->p_align = grub_host_to_target32 (image_target->link_align);
311
312 phdr++;
313 phdr->p_type = grub_host_to_target32 (PT_LOAD);
314 phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
315 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
316 phdr->p_filesz = phdr->p_memsz
317 = grub_host_to_target32 (*core_size - layout->kernel_size);
318
319 if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
320 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
321 else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
322 target_addr_mods = ALIGN_UP (target_addr + layout->end
323 + image_target->mod_gap,
324 image_target->mod_align);
325 else
326 target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
327 + image_target->mod_gap,
328 image_target->mod_align);
329 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
330 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
331 phdr->p_align = grub_host_to_target32 (image_target->link_align);
332 }
333
334 if (image_target->id == IMAGE_XEN)
335 {
336 char *note_start = (elf_img + program_size + header_size);
337 Elf_Nhdr *note_ptr;
338 char *ptr = (char *) note_start;
339
340 grub_util_info ("adding XEN NOTE segment");
341
342 /* Guest OS. */
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 (PACKAGE_NAME));
346 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_GUEST_OS);
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, PACKAGE_NAME, sizeof (PACKAGE_NAME));
351 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
352
353 /* Loader. */
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 (sizeof ("generic"));
357 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_LOADER);
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 memcpy (ptr, "generic", sizeof ("generic"));
362 ptr += ALIGN_UP (sizeof ("generic"), 4);
363
364 /* Version. */
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 (sizeof ("xen-3.0"));
368 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_XEN_VERSION);
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 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
373 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
374
375 /* Entry. */
376 note_ptr = (Elf_Nhdr *) ptr;
377 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
378 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
379 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_ENTRY);
380 ptr += sizeof (Elf_Nhdr);
381 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
382 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
383 memset (ptr, 0, image_target->voidp_sizeof);
384 ptr += image_target->voidp_sizeof;
385
386 /* Virt base. */
387 note_ptr = (Elf_Nhdr *) ptr;
388 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
389 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
390 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_VIRT_BASE);
391 ptr += sizeof (Elf_Nhdr);
392 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
393 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
394 memset (ptr, 0, image_target->voidp_sizeof);
395 ptr += image_target->voidp_sizeof;
396
397 /* PAE. */
398 if (image_target->elf_target == EM_386)
399 {
400 note_ptr = (Elf_Nhdr *) ptr;
401 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
402 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
403 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PAE_MODE);
404 ptr += sizeof (Elf_Nhdr);
405 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
406 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
407 memcpy (ptr, "yes", sizeof ("yes"));
408 ptr += ALIGN_UP (sizeof ("yes"), 4);
409 }
410
411 assert (XEN_NOTE_SIZE == (ptr - note_start));
412
413 phdr++;
414 phdr->p_type = grub_host_to_target32 (PT_NOTE);
415 phdr->p_flags = grub_host_to_target32 (PF_R);
416 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
417 phdr->p_vaddr = 0;
418 phdr->p_paddr = 0;
419 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
420 phdr->p_memsz = 0;
421 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
422 }
423
424 if (image_target->id == IMAGE_XEN_PVH)
425 {
426 char *note_start = (elf_img + program_size + header_size);
427 Elf_Nhdr *note_ptr;
428 char *ptr = (char *) note_start;
429
430 grub_util_info ("adding XEN NOTE segment");
431
432 /* Phys32 Entry. */
433 note_ptr = (Elf_Nhdr *) ptr;
434 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
435 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
436 note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PHYS32_ENTRY);
437 ptr += sizeof (Elf_Nhdr);
438 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
439 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
440 memset (ptr, 0, image_target->voidp_sizeof);
441 *(grub_uint32_t *) ptr = GRUB_KERNEL_I386_XEN_PVH_LINK_ADDR;
442 ptr += image_target->voidp_sizeof;
443
444 assert (XEN_PVH_NOTE_SIZE == (ptr - note_start));
445
446 phdr++;
447 phdr->p_type = grub_host_to_target32 (PT_NOTE);
448 phdr->p_flags = grub_host_to_target32 (PF_R);
449 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
450 phdr->p_vaddr = 0;
451 phdr->p_paddr = 0;
452 phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
453 phdr->p_memsz = 0;
454 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
455 }
456
457 if (note)
458 {
459 int note_size = sizeof (struct grub_ieee1275_note);
460 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
461 (elf_img + program_size + header_size);
462
463 grub_util_info ("adding CHRP NOTE segment");
464
465 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
466 note_ptr->header.n_descsz = grub_host_to_target32 (note_size);
467 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
468 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
469 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
470 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
471 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
472 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
473 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
474 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
475
476 phdr++;
477 phdr->p_type = grub_host_to_target32 (PT_NOTE);
478 phdr->p_flags = grub_host_to_target32 (PF_R);
479 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
480 phdr->p_vaddr = 0;
481 phdr->p_paddr = 0;
482 phdr->p_filesz = grub_host_to_target32 (note_size);
483 phdr->p_memsz = 0;
484 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
485 }
486
487 {
488 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
489 + shnum * sizeof (*shdr));
490 char *ptr = str_start + 1;
491
492 shdr++;
493
494 shdr->sh_name = grub_host_to_target32 (0);
495 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
496 shdr->sh_addr = grub_host_to_target_addr (0);
497 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
498 shdr->sh_size = grub_host_to_target32 (string_size);
499 shdr->sh_link = grub_host_to_target32 (0);
500 shdr->sh_info = grub_host_to_target32 (0);
501 shdr->sh_addralign = grub_host_to_target32 (layout->align);
502 shdr->sh_entsize = grub_host_to_target32 (0);
503 shdr++;
504
505 memcpy (ptr, ".text", sizeof (".text"));
506
507 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
508 ptr += sizeof (".text");
509 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
510 shdr->sh_addr = grub_host_to_target_addr (target_addr);
511 shdr->sh_offset = grub_host_to_target_addr (header_size);
512 shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
513 shdr->sh_link = grub_host_to_target32 (0);
514 shdr->sh_info = grub_host_to_target32 (0);
515 shdr->sh_addralign = grub_host_to_target32 (layout->align);
516 shdr->sh_entsize = grub_host_to_target32 (0);
517 shdr++;
518
519 memcpy (ptr, "mods", sizeof ("mods"));
520 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
521 ptr += sizeof ("mods");
522 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
523 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
524 shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
525 shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
526 shdr->sh_link = grub_host_to_target32 (0);
527 shdr->sh_info = grub_host_to_target32 (0);
528 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
529 shdr->sh_entsize = grub_host_to_target32 (0);
530 shdr++;
531
532 if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
533 {
534 memcpy (ptr, ".xen", sizeof (".xen"));
535 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
536 ptr += sizeof (".xen");
537 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
538 shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
539 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
540 if (image_target->id == IMAGE_XEN)
541 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
542 else
543 shdr->sh_size = grub_host_to_target32 (XEN_PVH_NOTE_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 (image_target->voidp_sizeof);
547 shdr->sh_entsize = grub_host_to_target32 (0);
548 shdr++;
549 }
550 }
551
552 free (*core_img);
553 *core_img = elf_img;
554 *core_size = program_size + header_size + footer_size;
555 }
556
557 /* Relocate symbols; note that this function overwrites the symbol table.
558 Return the address of a start symbol. */
559 static Elf_Addr
560 SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
561 void *jumpers, Elf_Addr jumpers_addr,
562 Elf_Addr bss_start, Elf_Addr end,
563 const struct grub_install_image_target_desc *image_target)
564 {
565 Elf_Word symtab_size, sym_size, num_syms;
566 Elf_Off symtab_offset;
567 Elf_Addr start_address = (Elf_Addr) -1;
568 Elf_Sym *sym;
569 Elf_Word i;
570 Elf_Shdr *symtab_section;
571 const char *symtab;
572 grub_uint64_t *jptr = jumpers;
573
574 symtab_section = (Elf_Shdr *) ((char *) smd->sections
575 + grub_target_to_host32 (smd->symtab->sh_link)
576 * smd->section_entsize);
577 symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
578
579 symtab_size = grub_target_to_host (smd->symtab->sh_size);
580 sym_size = grub_target_to_host (smd->symtab->sh_entsize);
581 symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
582 num_syms = symtab_size / sym_size;
583
584 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
585 i < num_syms;
586 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
587 {
588 Elf_Section cur_index;
589 const char *name;
590
591 name = symtab + grub_target_to_host32 (sym->st_name);
592
593 cur_index = grub_target_to_host16 (sym->st_shndx);
594 if (cur_index == STN_ABS)
595 {
596 continue;
597 }
598 else if (cur_index == STN_UNDEF)
599 {
600 if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
601 sym->st_value = bss_start;
602 else if (sym->st_name && grub_strcmp (name, "_end") == 0)
603 sym->st_value = end;
604 else if (sym->st_name)
605 grub_util_error ("undefined symbol %s", name);
606 else
607 continue;
608 }
609 else if (cur_index >= smd->num_sections)
610 grub_util_error ("section %d does not exist", cur_index);
611 else
612 {
613 sym->st_value = (grub_target_to_host (sym->st_value)
614 + smd->vaddrs[cur_index]);
615 }
616
617 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
618 == STT_FUNC)
619 {
620 *jptr = grub_host_to_target64 (sym->st_value);
621 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
622 jptr++;
623 *jptr = 0;
624 jptr++;
625 }
626 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
627 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
628 (unsigned long long) sym->st_value,
629 (unsigned long long) smd->vaddrs[cur_index]);
630
631 if (start_address == (Elf_Addr)-1)
632 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
633 start_address = sym->st_value;
634 }
635
636 return start_address;
637 }
638
639 /* Return the address of a symbol at the index I in the section S. */
640 static Elf_Addr
641 SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
642 const struct grub_install_image_target_desc *image_target)
643 {
644 Elf_Sym *sym;
645
646 sym = (Elf_Sym *) ((char *) e
647 + grub_target_to_host (s->sh_offset)
648 + i * grub_target_to_host (s->sh_entsize));
649 return sym->st_value;
650 }
651
652 /* Return the address of a modified value. */
653 static Elf_Addr *
654 SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
655 const struct grub_install_image_target_desc *image_target)
656 {
657 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
658 }
659
660 #ifdef MKIMAGE_ELF64
661 static Elf_Addr
662 SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
663 const struct grub_install_image_target_desc *image_target)
664 {
665 Elf_Word symtab_size, sym_size, num_syms;
666 Elf_Off symtab_offset;
667 Elf_Sym *sym;
668 Elf_Word i;
669 int ret = 0;
670
671 symtab_size = grub_target_to_host (symtab_section->sh_size);
672 sym_size = grub_target_to_host (symtab_section->sh_entsize);
673 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
674 num_syms = symtab_size / sym_size;
675
676 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
677 i < num_syms;
678 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
679 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
680 ret++;
681
682 return ret;
683 }
684 #endif
685
686 #ifdef MKIMAGE_ELF32
687 /* Deal with relocation information. This function relocates addresses
688 within the virtual address space starting from 0. So only relative
689 addresses can be fully resolved. Absolute addresses must be relocated
690 again by a PE32 relocator when loaded. */
691 static grub_size_t
692 arm_get_trampoline_size (Elf_Ehdr *e,
693 Elf_Shdr *sections,
694 Elf_Half section_entsize,
695 Elf_Half num_sections,
696 const struct grub_install_image_target_desc *image_target)
697 {
698 Elf_Half i;
699 Elf_Shdr *s;
700 grub_size_t ret = 0;
701
702 for (i = 0, s = sections;
703 i < num_sections;
704 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
705 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
706 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
707 {
708 Elf_Rela *r;
709 Elf_Word rtab_size, r_size, num_rs;
710 Elf_Off rtab_offset;
711 Elf_Shdr *symtab_section;
712 Elf_Word j;
713
714 symtab_section = (Elf_Shdr *) ((char *) sections
715 + (grub_target_to_host32 (s->sh_link)
716 * section_entsize));
717
718 rtab_size = grub_target_to_host (s->sh_size);
719 r_size = grub_target_to_host (s->sh_entsize);
720 rtab_offset = grub_target_to_host (s->sh_offset);
721 num_rs = rtab_size / r_size;
722
723 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
724 j < num_rs;
725 j++, r = (Elf_Rela *) ((char *) r + r_size))
726 {
727 Elf_Addr info;
728 Elf_Addr sym_addr;
729
730 info = grub_target_to_host (r->r_info);
731 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
732 ELF_R_SYM (info), image_target);
733
734 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
735 grub_target_to_host (r->r_addend) : 0;
736
737 switch (ELF_R_TYPE (info))
738 {
739 case R_ARM_ABS32:
740 case R_ARM_V4BX:
741 break;
742 case R_ARM_THM_CALL:
743 case R_ARM_THM_JUMP24:
744 case R_ARM_THM_JUMP19:
745 if (!(sym_addr & 1))
746 ret += 8;
747 break;
748
749 case R_ARM_CALL:
750 case R_ARM_JUMP24:
751 if (sym_addr & 1)
752 ret += 16;
753 break;
754
755 default:
756 grub_util_error (_("relocation 0x%x is not implemented yet"),
757 (unsigned int) ELF_R_TYPE (info));
758 break;
759 }
760 }
761 }
762 return ret;
763 }
764 #endif
765
766 static int
767 SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target);
768 static int
769 SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
770 struct section_metadata *smd);
771
772 /* Deal with relocation information. This function relocates addresses
773 within the virtual address space starting from 0. So only relative
774 addresses can be fully resolved. Absolute addresses must be relocated
775 again by a PE32 relocator when loaded. */
776 static void
777 SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
778 char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
779 const struct grub_install_image_target_desc *image_target)
780 {
781 Elf_Half i;
782 Elf_Shdr *s;
783 #ifdef MKIMAGE_ELF64
784 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
785 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
786 unsigned unmatched_adr_got_page = 0;
787 #define MASK19 ((1 << 19) - 1)
788 #else
789 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
790 #endif
791
792 for (i = 0, s = smd->sections;
793 i < smd->num_sections;
794 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
795 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
796 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
797 {
798 Elf_Rela *r;
799 Elf_Word rtab_size, r_size, num_rs;
800 Elf_Off rtab_offset;
801 Elf_Word target_section_index;
802 Elf_Addr target_section_addr;
803 Elf_Shdr *target_section;
804 Elf_Word j;
805
806 if (!SUFFIX (is_kept_section) (s, image_target) &&
807 !SUFFIX (is_kept_reloc_section) (s, image_target, smd))
808 {
809 grub_util_info ("not translating relocations for omitted section %s",
810 smd->strtab + grub_le_to_cpu32 (s->sh_name));
811 continue;
812 }
813
814 target_section_index = grub_target_to_host32 (s->sh_info);
815 target_section_addr = smd->addrs[target_section_index];
816 target_section = (Elf_Shdr *) ((char *) smd->sections
817 + (target_section_index
818 * smd->section_entsize));
819
820 grub_util_info ("dealing with the relocation section %s for %s",
821 smd->strtab + grub_target_to_host32 (s->sh_name),
822 smd->strtab + grub_target_to_host32 (target_section->sh_name));
823
824 rtab_size = grub_target_to_host (s->sh_size);
825 r_size = grub_target_to_host (s->sh_entsize);
826 rtab_offset = grub_target_to_host (s->sh_offset);
827 num_rs = rtab_size / r_size;
828
829 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
830 j < num_rs;
831 j++, r = (Elf_Rela *) ((char *) r + r_size))
832 {
833 Elf_Addr info;
834 Elf_Addr offset;
835 Elf_Addr sym_addr;
836 Elf_Addr *target;
837 Elf_Addr addend;
838
839 offset = grub_target_to_host (r->r_offset);
840 target = SUFFIX (get_target_address) (e, target_section,
841 offset, image_target);
842 if (image_target->elf_target == EM_MIPS && image_target->voidp_sizeof == 8)
843 info = ((grub_uint64_t) r->r_info << 32) |
844 (grub_uint32_t) grub_be_to_cpu64 (r->r_info);
845 else
846 info = grub_target_to_host (r->r_info);
847 sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
848 ELF_R_SYM (info), image_target);
849
850 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
851 grub_target_to_host (r->r_addend) : 0;
852
853 switch (image_target->elf_target)
854 {
855 case EM_386:
856 switch (ELF_R_TYPE (info))
857 {
858 case R_386_NONE:
859 break;
860
861 case R_386_32:
862 /* This is absolute. */
863 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
864 + addend + sym_addr);
865 grub_util_info ("relocating an R_386_32 entry to 0x%"
866 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
867 GRUB_HOST_PRIxLONG_LONG,
868 (unsigned long long) *target,
869 (unsigned long long) offset);
870 break;
871
872 case R_386_PC32:
873 /* This is relative. */
874 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
875 + addend + sym_addr
876 - target_section_addr - offset
877 - image_target->vaddr_offset);
878 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
879 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
880 GRUB_HOST_PRIxLONG_LONG,
881 (unsigned long long) *target,
882 (unsigned long long) offset);
883 break;
884 default:
885 grub_util_error (_("relocation 0x%x is not implemented yet"),
886 (unsigned int) ELF_R_TYPE (info));
887 break;
888 }
889 break;
890 #ifdef MKIMAGE_ELF64
891 case EM_X86_64:
892 switch (ELF_R_TYPE (info))
893 {
894
895 case R_X86_64_NONE:
896 break;
897
898 case R_X86_64_64:
899 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
900 + addend + sym_addr);
901 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
902 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
903 GRUB_HOST_PRIxLONG_LONG,
904 (unsigned long long) *target,
905 (unsigned long long) offset);
906 break;
907
908 case R_X86_64_PC32:
909 case R_X86_64_PLT32:
910 {
911 grub_uint32_t *t32 = (grub_uint32_t *) target;
912 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
913 + addend + sym_addr
914 - target_section_addr - offset
915 - image_target->vaddr_offset);
916 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
917 GRUB_HOST_PRIxLONG_LONG,
918 *t32, (unsigned long long) offset);
919 break;
920 }
921
922 case R_X86_64_PC64:
923 {
924 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
925 + addend + sym_addr
926 - target_section_addr - offset
927 - image_target->vaddr_offset);
928 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
929 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
930 GRUB_HOST_PRIxLONG_LONG,
931 (unsigned long long) *target,
932 (unsigned long long) offset);
933 break;
934 }
935
936 case R_X86_64_32:
937 case R_X86_64_32S:
938 {
939 grub_uint32_t *t32 = (grub_uint32_t *) target;
940 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
941 + addend + sym_addr);
942 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
943 GRUB_HOST_PRIxLONG_LONG,
944 *t32, (unsigned long long) offset);
945 break;
946 }
947
948 default:
949 grub_util_error (_("relocation 0x%x is not implemented yet"),
950 (unsigned int) ELF_R_TYPE (info));
951 break;
952 }
953 break;
954 case EM_IA_64:
955 switch (ELF_R_TYPE (info))
956 {
957 case R_IA64_PCREL21B:
958 {
959 grub_uint64_t noff;
960 grub_ia64_make_trampoline (tr, addend + sym_addr);
961 noff = ((char *) tr - (char *) pe_target
962 - target_section_addr - (offset & ~3)) >> 4;
963 tr++;
964 if (noff & ~MASK19)
965 grub_util_error ("trampoline offset too big (%"
966 GRUB_HOST_PRIxLONG_LONG ")",
967 (unsigned long long) noff);
968 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
969 }
970 break;
971
972 case R_IA64_LTOFF22X:
973 case R_IA64_LTOFF22:
974 {
975 Elf_Sym *sym;
976
977 sym = (Elf_Sym *) ((char *) e
978 + grub_target_to_host (smd->symtab->sh_offset)
979 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
980 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
981 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
982 + sym->st_value
983 - image_target->vaddr_offset));
984 }
985 /* FALLTHROUGH */
986 case R_IA64_LTOFF_FPTR22:
987 *gpptr = grub_host_to_target64 (addend + sym_addr);
988 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
989 (char *) gpptr - (char *) pe_target
990 + image_target->vaddr_offset);
991 gpptr++;
992 break;
993
994 case R_IA64_GPREL22:
995 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
996 addend + sym_addr);
997 break;
998 case R_IA64_GPREL64I:
999 grub_ia64_set_immu64 ((grub_addr_t) target,
1000 addend + sym_addr);
1001 break;
1002 case R_IA64_PCREL64LSB:
1003 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1004 + addend + sym_addr
1005 - target_section_addr - offset
1006 - image_target->vaddr_offset);
1007 break;
1008
1009 case R_IA64_SEGREL64LSB:
1010 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1011 + addend + sym_addr - target_section_addr);
1012 break;
1013 case R_IA64_DIR64LSB:
1014 case R_IA64_FPTR64LSB:
1015 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1016 + addend + sym_addr);
1017 grub_util_info ("relocating a direct entry to 0x%"
1018 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
1019 GRUB_HOST_PRIxLONG_LONG,
1020 (unsigned long long)
1021 grub_target_to_host64 (*target),
1022 (unsigned long long) offset);
1023 break;
1024
1025 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
1026 case R_IA64_LDXMOV:
1027 break;
1028
1029 default:
1030 grub_util_error (_("relocation 0x%x is not implemented yet"),
1031 (unsigned int) ELF_R_TYPE (info));
1032 break;
1033 }
1034 break;
1035 case EM_AARCH64:
1036 {
1037 sym_addr += addend;
1038 switch (ELF_R_TYPE (info))
1039 {
1040 case R_AARCH64_ABS64:
1041 {
1042 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
1043 }
1044 break;
1045 case R_AARCH64_PREL32:
1046 {
1047 grub_uint32_t *t32 = (grub_uint32_t *) target;
1048 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
1049 + sym_addr
1050 - target_section_addr - offset
1051 - image_target->vaddr_offset);
1052 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
1053 GRUB_HOST_PRIxLONG_LONG,
1054 *t32, (unsigned long long) offset);
1055 break;
1056 }
1057 case R_AARCH64_ADD_ABS_LO12_NC:
1058 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
1059 sym_addr);
1060 break;
1061 case R_AARCH64_LDST64_ABS_LO12_NC:
1062 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
1063 sym_addr);
1064 break;
1065 case R_AARCH64_JUMP26:
1066 case R_AARCH64_CALL26:
1067 {
1068 sym_addr -= offset;
1069 sym_addr -= target_section_addr + image_target->vaddr_offset;
1070 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1071 grub_util_error ("%s", "CALL26 Relocation out of range");
1072
1073 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1074 sym_addr);
1075 }
1076 break;
1077 case R_AARCH64_ADR_GOT_PAGE:
1078 {
1079 Elf64_Rela *rel2;
1080 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1081 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1082 unsigned k;
1083 *gpptr = grub_host_to_target64 (sym_addr);
1084 unmatched_adr_got_page++;
1085 if (!grub_arm64_check_hi21_signed (gpoffset))
1086 grub_util_error ("HI21 out of range");
1087 grub_arm64_set_hi21((grub_uint32_t *)target,
1088 gpoffset);
1089 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1090 k < num_rs;
1091 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1092 if (ELF_R_SYM (rel2->r_info)
1093 == ELF_R_SYM (r->r_info)
1094 && r->r_addend == rel2->r_addend
1095 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1096 {
1097 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1098 grub_target_to_host (rel2->r_offset), image_target),
1099 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1100 break;
1101 }
1102 if (k >= num_rs)
1103 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1104 gpptr++;
1105 }
1106 break;
1107 case R_AARCH64_LD64_GOT_LO12_NC:
1108 if (unmatched_adr_got_page == 0)
1109 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1110 unmatched_adr_got_page--;
1111 break;
1112 case R_AARCH64_ADR_PREL_PG_HI21:
1113 {
1114 sym_addr &= ~0xfffULL;
1115 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1116 if (!grub_arm64_check_hi21_signed (sym_addr))
1117 grub_util_error ("%s", "CALL26 Relocation out of range");
1118
1119 grub_arm64_set_hi21((grub_uint32_t *)target,
1120 sym_addr);
1121 }
1122 break;
1123 default:
1124 grub_util_error (_("relocation 0x%x is not implemented yet"),
1125 (unsigned int) ELF_R_TYPE (info));
1126 break;
1127 }
1128 break;
1129 }
1130 case EM_MIPS:
1131 {
1132 sym_addr += addend;
1133 switch (ELF_R_TYPE (info))
1134 {
1135 case R_MIPS_NONE:
1136 break;
1137 case R_MIPS_64:
1138 {
1139 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
1140 }
1141 break;
1142 case R_MIPS_32:
1143 {
1144 grub_uint32_t *t32 = (grub_uint32_t *) target;
1145 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32) + sym_addr);
1146 }
1147 break;
1148 case R_MIPS_26:
1149 {
1150 grub_uint32_t *t32 = (grub_uint32_t *) target;
1151 grub_addr_t addr = grub_host_to_target64 (sym_addr);
1152 *t32 = ((*t32) & 0xfc000000U) | ((addr >> 2) & 0x3ffffffUL);
1153 }
1154 break;
1155 case R_MIPS_LO16:
1156 {
1157 grub_int16_t *t16 = (grub_int16_t *) target;
1158 grub_addr_t addr = grub_host_to_target64 (sym_addr);
1159 *t16 = (grub_int16_t) addr;
1160 }
1161 break;
1162 case R_MIPS_HI16:
1163 {
1164 grub_int16_t *t16 = (grub_int16_t *) target;
1165 grub_addr_t addr = grub_host_to_target64 (sym_addr);
1166 *t16 = (grub_int16_t) ((addr + 0x8000UL) >> 16);
1167 }
1168 break;
1169 case R_MIPS_HIGHER:
1170 {
1171 grub_int16_t *t16 = (grub_int16_t *) target;
1172 grub_addr_t addr = grub_host_to_target64 (sym_addr);
1173 *t16 = (grub_int16_t) ((addr + 0x80008000UL) >> 32);
1174 }
1175 break;
1176 case R_MIPS_HIGHEST:
1177 {
1178 grub_uint16_t *t16 = (grub_uint16_t *) target;
1179 grub_addr_t addr = grub_host_to_target64 (sym_addr);
1180 *t16 = (grub_uint16_t) ((addr + 0x800080008000UL) >> 48);
1181 }
1182 break;
1183 default:
1184 grub_util_error (_("relocation 0x%x is not implemented yet"),
1185 (unsigned int) ELF_R_TYPE (info));
1186 break;
1187 }
1188 break;
1189 }
1190 #endif
1191 #if defined(MKIMAGE_ELF32)
1192 case EM_ARM:
1193 {
1194 sym_addr += addend;
1195 sym_addr -= image_target->vaddr_offset;
1196 switch (ELF_R_TYPE (info))
1197 {
1198 case R_ARM_ABS32:
1199 {
1200 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1201 (int) sym_addr, (int) sym_addr);
1202 /* Data will be naturally aligned */
1203 if (image_target->id == IMAGE_EFI)
1204 sym_addr += GRUB_PE32_SECTION_ALIGNMENT;
1205 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1206 }
1207 break;
1208 /* Happens when compiled with -march=armv4.
1209 Since currently we need at least armv5, keep bx as-is.
1210 */
1211 case R_ARM_V4BX:
1212 break;
1213 case R_ARM_THM_CALL:
1214 case R_ARM_THM_JUMP24:
1215 case R_ARM_THM_JUMP19:
1216 {
1217 grub_err_t err;
1218 Elf_Sym *sym;
1219 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1220 (unsigned long) ((char *) target
1221 - (char *) e),
1222 sym_addr);
1223 sym = (Elf_Sym *) ((char *) e
1224 + grub_target_to_host (smd->symtab->sh_offset)
1225 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
1226 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1227 sym_addr |= 1;
1228 if (!(sym_addr & 1))
1229 {
1230 grub_uint32_t tr_addr;
1231 grub_int32_t new_offset;
1232 tr_addr = (char *) tr - (char *) pe_target
1233 - target_section_addr;
1234 new_offset = sym_addr - tr_addr - 12;
1235
1236 if (!grub_arm_jump24_check_offset (new_offset))
1237 return grub_util_error ("jump24 relocation out of range");
1238
1239 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1240 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1241 tr += 2;
1242 sym_addr = tr_addr | 1;
1243 }
1244 sym_addr -= offset;
1245 /* Thumb instructions can be 16-bit aligned */
1246 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1247 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1248 else
1249 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1250 sym_addr);
1251 if (err)
1252 grub_util_error ("%s", grub_errmsg);
1253 }
1254 break;
1255
1256 case R_ARM_CALL:
1257 case R_ARM_JUMP24:
1258 {
1259 grub_err_t err;
1260 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1261 if (sym_addr & 1)
1262 {
1263 grub_uint32_t tr_addr;
1264 grub_int32_t new_offset;
1265 tr_addr = (char *) tr - (char *) pe_target
1266 - target_section_addr;
1267 new_offset = sym_addr - tr_addr - 12;
1268
1269 /* There is no immediate version of bx, only register one... */
1270 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1271 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1272 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1273 tr[3] = grub_host_to_target32 (new_offset | 1);
1274 tr += 4;
1275 sym_addr = tr_addr;
1276 }
1277 sym_addr -= offset;
1278 err = grub_arm_reloc_jump24 (target,
1279 sym_addr);
1280 if (err)
1281 grub_util_error ("%s", grub_errmsg);
1282 }
1283 break;
1284
1285 default:
1286 grub_util_error (_("relocation 0x%x is not implemented yet"),
1287 (unsigned int) ELF_R_TYPE (info));
1288 break;
1289 }
1290 break;
1291 }
1292 #endif /* MKIMAGE_ELF32 */
1293 case EM_RISCV:
1294 {
1295 grub_uint64_t *t64 = (grub_uint64_t *) target;
1296 grub_uint32_t *t32 = (grub_uint32_t *) target;
1297 grub_uint16_t *t16 = (grub_uint16_t *) target;
1298 grub_uint8_t *t8 = (grub_uint8_t *) target;
1299 grub_int64_t off = (long)sym_addr - target_section_addr - offset
1300 - image_target->vaddr_offset;
1301
1302 /*
1303 * Instructions and instruction encoding are documented in the RISC-V
1304 * specification. This file is based on version 2.2:
1305 *
1306 * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
1307 */
1308
1309 sym_addr += addend;
1310
1311 switch (ELF_R_TYPE (info))
1312 {
1313 case R_RISCV_ADD8:
1314 *t8 = *t8 + sym_addr;
1315 break;
1316 case R_RISCV_ADD16:
1317 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) + sym_addr);
1318 break;
1319 case R_RISCV_32:
1320 case R_RISCV_ADD32:
1321 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
1322 break;
1323 case R_RISCV_64:
1324 case R_RISCV_ADD64:
1325 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
1326 break;
1327
1328 case R_RISCV_SUB8:
1329 *t8 = sym_addr - *t8;
1330 break;
1331 case R_RISCV_SUB16:
1332 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) - sym_addr);
1333 break;
1334 case R_RISCV_SUB32:
1335 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) - sym_addr);
1336 break;
1337 case R_RISCV_SUB64:
1338 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) - sym_addr);
1339 break;
1340 case R_RISCV_BRANCH:
1341 {
1342 grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
1343 grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
1344 grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
1345 grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
1346 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
1347 | imm12 | imm11 | imm10_5 | imm4_1);
1348 }
1349 break;
1350 case R_RISCV_JAL:
1351 {
1352 grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
1353 grub_uint32_t imm19_12 = (off & 0xff000);
1354 grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
1355 grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
1356 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
1357 | imm20 | imm19_12 | imm11 | imm10_1);
1358 }
1359 break;
1360 case R_RISCV_CALL:
1361 {
1362 grub_uint32_t hi20, lo12;
1363
1364 if (off != (grub_int32_t)off)
1365 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
1366
1367 hi20 = (off + 0x800) & 0xfffff000;
1368 lo12 = (off - hi20) & 0xfff;
1369 t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
1370 t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
1371 }
1372 break;
1373 case R_RISCV_RVC_BRANCH:
1374 {
1375 grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
1376 grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
1377 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1378 grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
1379 grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
1380 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
1381 | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
1382 }
1383 break;
1384 case R_RISCV_RVC_JUMP:
1385 {
1386 grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
1387 grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
1388 grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
1389 grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
1390 grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
1391 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1392 grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
1393 grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
1394 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
1395 | imm11 | imm10 | imm9_8 | imm7 | imm6
1396 | imm5 | imm4 | imm3_1);
1397 }
1398 break;
1399 case R_RISCV_PCREL_HI20:
1400 {
1401 grub_int32_t hi20;
1402
1403 if (off != (grub_int32_t)off)
1404 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
1405
1406 hi20 = (off + 0x800) & 0xfffff000;
1407 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
1408 }
1409 break;
1410 case R_RISCV_PCREL_LO12_I:
1411 case R_RISCV_PCREL_LO12_S:
1412 {
1413 Elf_Rela *rel2;
1414 Elf_Word k;
1415 /* Search backwards for matching HI20 reloc. */
1416 for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
1417 k > 0;
1418 k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
1419 {
1420 Elf_Addr rel2_info;
1421 Elf_Addr rel2_offset;
1422 Elf_Addr rel2_sym_addr;
1423 Elf_Addr rel2_addend;
1424 Elf_Addr rel2_loc;
1425 grub_int64_t rel2_off;
1426
1427 rel2_offset = grub_target_to_host (rel2->r_offset);
1428 rel2_info = grub_target_to_host (rel2->r_info);
1429 rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
1430
1431 if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
1432 && rel2_loc == sym_addr)
1433 {
1434 rel2_sym_addr = SUFFIX (get_symbol_address)
1435 (e, smd->symtab, ELF_R_SYM (rel2_info),
1436 image_target);
1437 rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
1438 grub_target_to_host (rel2->r_addend) : 0;
1439 rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
1440 off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
1441
1442 if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
1443 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
1444 else
1445 {
1446 grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
1447 grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
1448 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1449 }
1450 break;
1451 }
1452 }
1453 if (k == 0)
1454 grub_util_error ("cannot find matching HI20 relocation");
1455 }
1456 break;
1457 case R_RISCV_HI20:
1458 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
1459 break;
1460 case R_RISCV_LO12_I:
1461 {
1462 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1463 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
1464 }
1465 break;
1466 case R_RISCV_LO12_S:
1467 {
1468 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1469 grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
1470 grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
1471 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1472 }
1473 break;
1474 case R_RISCV_RELAX:
1475 break;
1476 default:
1477 grub_util_error (_("relocation 0x%x is not implemented yet"),
1478 (unsigned int) ELF_R_TYPE (info));
1479 break;
1480 }
1481 break;
1482 }
1483 default:
1484 grub_util_error ("unknown architecture type %d",
1485 image_target->elf_target);
1486 }
1487 }
1488 }
1489 }
1490
1491 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1492 after having written to the file OUT. */
1493 static Elf_Addr
1494 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1495 Elf_Addr addr, int flush, Elf_Addr current_address,
1496 const struct grub_install_image_target_desc *image_target)
1497 {
1498 struct grub_pe32_fixup_block *b;
1499
1500 b = &((*cblock)->b);
1501
1502 /* First, check if it is necessary to write out the current block. */
1503 if ((*cblock)->state)
1504 {
1505 if (flush || (type && (addr < b->page_rva || b->page_rva + 0x1000 <= addr)))
1506 {
1507 grub_uint32_t size;
1508
1509 if (flush)
1510 {
1511 /* Add as much padding as necessary to align the address
1512 with a section boundary. */
1513 Elf_Addr next_address;
1514 unsigned padding_size;
1515 size_t cur_index;
1516
1517 next_address = current_address + b->block_size;
1518 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1519 - next_address)
1520 >> 1);
1521 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1522 grub_util_info ("adding %d padding fixup entries", padding_size);
1523 while (padding_size--)
1524 {
1525 b->entries[cur_index++] = 0;
1526 b->block_size += 2;
1527 }
1528 }
1529 else while (b->block_size & (8 - 1))
1530 {
1531 /* If not aligned with a 32-bit boundary, add
1532 a padding entry. */
1533 size_t cur_index;
1534
1535 grub_util_info ("adding a padding fixup entry");
1536 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1537 b->entries[cur_index] = 0;
1538 b->block_size += 2;
1539 }
1540
1541 /* Flush it. */
1542 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1543 b->block_size, b->page_rva);
1544 size = b->block_size;
1545 current_address += size;
1546 b->page_rva = grub_host_to_target32 (b->page_rva);
1547 b->block_size = grub_host_to_target32 (b->block_size);
1548 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1549 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1550 *cblock = (*cblock)->next;
1551 }
1552 }
1553
1554 b = &((*cblock)->b);
1555
1556 if (! flush)
1557 {
1558 grub_uint16_t entry;
1559 size_t cur_index;
1560
1561 /* If not allocated yet, allocate a block with enough entries. */
1562 if (! (*cblock)->state)
1563 {
1564 (*cblock)->state = 1;
1565
1566 /* The spec does not mention the requirement of a Page RVA.
1567 Here, align the address with a 4K boundary for safety. */
1568 if (type)
1569 b->page_rva = (addr & ~(0x1000 - 1));
1570 b->block_size = sizeof (*b);
1571 }
1572
1573 /* Sanity check. */
1574 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1575 grub_util_error ("too many fixup entries");
1576
1577 /* Add a new entry. */
1578 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1579 entry = GRUB_PE32_FIXUP_ENTRY (type, type ? (addr - b->page_rva) : addr);
1580 b->entries[cur_index] = grub_host_to_target16 (entry);
1581 b->block_size += 2;
1582 }
1583
1584 return current_address;
1585 }
1586
1587 struct raw_reloc
1588 {
1589 struct raw_reloc *next;
1590 grub_uint32_t offset;
1591 enum raw_reloc_type {
1592 RAW_RELOC_NONE = -1,
1593 RAW_RELOC_32 = 0,
1594 RAW_RELOC_MAX = 1,
1595 } type;
1596 };
1597
1598 struct translate_context
1599 {
1600 /* PE */
1601 struct fixup_block_list *lst, *lst0;
1602 Elf_Addr current_address;
1603
1604 /* Raw */
1605 struct raw_reloc *raw_relocs;
1606 };
1607
1608 static void
1609 translate_reloc_start (struct translate_context *ctx,
1610 const struct grub_install_image_target_desc *image_target)
1611 {
1612 grub_memset (ctx, 0, sizeof (*ctx));
1613 if (image_target->id == IMAGE_EFI)
1614 {
1615 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1616 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1617 ctx->current_address = 0;
1618 }
1619 }
1620
1621 static void
1622 translate_relocation_pe (struct translate_context *ctx,
1623 Elf_Addr addr,
1624 Elf_Addr info,
1625 Elf_Addr sym_addr,
1626 Elf_Addr addend,
1627 const struct grub_install_image_target_desc *image_target)
1628 {
1629 /* Necessary to relocate only absolute addresses. */
1630 switch (image_target->elf_target)
1631 {
1632 case EM_386:
1633 if (ELF_R_TYPE (info) == R_386_32)
1634 {
1635 grub_util_info ("adding a relocation entry for 0x%"
1636 GRUB_HOST_PRIxLONG_LONG,
1637 (unsigned long long) addr);
1638 ctx->current_address
1639 = add_fixup_entry (&ctx->lst,
1640 GRUB_PE32_REL_BASED_HIGHLOW,
1641 addr, 0, ctx->current_address,
1642 image_target);
1643 }
1644 break;
1645 case EM_X86_64:
1646 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1647 (ELF_R_TYPE (info) == R_X86_64_32S))
1648 {
1649 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1650 }
1651 else if (ELF_R_TYPE (info) == R_X86_64_64)
1652 {
1653 grub_util_info ("adding a relocation entry for 0x%"
1654 GRUB_HOST_PRIxLONG_LONG,
1655 (unsigned long long) addr);
1656 ctx->current_address
1657 = add_fixup_entry (&ctx->lst,
1658 GRUB_PE32_REL_BASED_DIR64,
1659 addr,
1660 0, ctx->current_address,
1661 image_target);
1662 }
1663 break;
1664 case EM_IA_64:
1665 switch (ELF_R_TYPE (info))
1666 {
1667 case R_IA64_PCREL64LSB:
1668 case R_IA64_LDXMOV:
1669 case R_IA64_PCREL21B:
1670 case R_IA64_LTOFF_FPTR22:
1671 case R_IA64_LTOFF22X:
1672 case R_IA64_LTOFF22:
1673 case R_IA64_GPREL22:
1674 case R_IA64_GPREL64I:
1675 case R_IA64_SEGREL64LSB:
1676 break;
1677
1678 case R_IA64_FPTR64LSB:
1679 case R_IA64_DIR64LSB:
1680 #if 1
1681 {
1682 grub_util_info ("adding a relocation entry for 0x%"
1683 GRUB_HOST_PRIxLONG_LONG,
1684 (unsigned long long) addr);
1685 ctx->current_address
1686 = add_fixup_entry (&ctx->lst,
1687 GRUB_PE32_REL_BASED_DIR64,
1688 addr,
1689 0, ctx->current_address,
1690 image_target);
1691 }
1692 #endif
1693 break;
1694 default:
1695 grub_util_error (_("relocation 0x%x is not implemented yet"),
1696 (unsigned int) ELF_R_TYPE (info));
1697 break;
1698 }
1699 break;
1700 case EM_AARCH64:
1701 switch (ELF_R_TYPE (info))
1702 {
1703 case R_AARCH64_ABS64:
1704 {
1705 ctx->current_address
1706 = add_fixup_entry (&ctx->lst,
1707 GRUB_PE32_REL_BASED_DIR64,
1708 addr, 0, ctx->current_address,
1709 image_target);
1710 }
1711 break;
1712 /* Relative relocations do not require fixup entries. */
1713 case R_AARCH64_CALL26:
1714 case R_AARCH64_JUMP26:
1715 case R_AARCH64_PREL32:
1716 break;
1717 /* Page-relative relocations do not require fixup entries. */
1718 case R_AARCH64_ADR_PREL_PG_HI21:
1719 /* We page-align the whole kernel, so no need
1720 for fixup entries.
1721 */
1722 case R_AARCH64_ADD_ABS_LO12_NC:
1723 case R_AARCH64_LDST64_ABS_LO12_NC:
1724 break;
1725
1726 /* GOT is relocated separately. */
1727 case R_AARCH64_ADR_GOT_PAGE:
1728 case R_AARCH64_LD64_GOT_LO12_NC:
1729 break;
1730
1731 default:
1732 grub_util_error (_("relocation 0x%x is not implemented yet"),
1733 (unsigned int) ELF_R_TYPE (info));
1734 break;
1735 }
1736 break;
1737 #if defined(MKIMAGE_ELF64)
1738 case EM_MIPS:
1739 switch (ELF_R_TYPE (info))
1740 {
1741 case R_MIPS_64:
1742 {
1743 ctx->current_address
1744 = add_fixup_entry (&ctx->lst,
1745 GRUB_PE32_REL_BASED_DIR64,
1746 addr, 0, ctx->current_address,
1747 image_target);
1748 }
1749 break;
1750 case R_MIPS_32:
1751 #if 0
1752 {
1753 ctx->current_address
1754 = add_fixup_entry (&ctx->lst,
1755 GRUB_PE32_REL_BASED_HIGHLOW,
1756 addr, 0, ctx->current_address,
1757 image_target);
1758 }
1759 #endif
1760 break;
1761 case R_MIPS_26:
1762 {
1763 ctx->current_address
1764 = add_fixup_entry (&ctx->lst,
1765 GRUB_PE32_REL_BASED_MIPS_JMPADDR,
1766 addr, 0, ctx->current_address,
1767 image_target);
1768 }
1769 break;
1770 case R_MIPS_LO16:
1771 {
1772 Elf_Addr target = sym_addr + addend;
1773
1774 ctx->current_address
1775 = add_fixup_entry (&ctx->lst,
1776 GRUB_PE32_REL_BASED_MIPS_LOW,
1777 addr, 0, ctx->current_address,
1778 image_target);
1779 /* Hi */
1780 ctx->current_address
1781 = add_fixup_entry (&ctx->lst, 0,
1782 (grub_int16_t) ((target & 0x8000UL) >> 16),
1783 0, ctx->current_address,
1784 image_target);
1785 /* Higher */
1786 ctx->current_address
1787 = add_fixup_entry (&ctx->lst, 0,
1788 (grub_int16_t) ((target & 0x80008000UL) >> 32),
1789 0, ctx->current_address,
1790 image_target);
1791 /* Highest */
1792 ctx->current_address
1793 = add_fixup_entry (&ctx->lst, 0,
1794 (grub_uint16_t) ((target & 0x800080008000UL) >> 48),
1795 0, ctx->current_address,
1796 image_target);
1797 }
1798 break;
1799 case R_MIPS_HI16:
1800 {
1801 Elf_Addr target = sym_addr + addend;
1802
1803 ctx->current_address
1804 = add_fixup_entry (&ctx->lst,
1805 GRUB_PE32_REL_BASED_MIPS_HIGH,
1806 addr, 0, ctx->current_address,
1807 image_target);
1808 /* Lo */
1809 ctx->current_address
1810 = add_fixup_entry (&ctx->lst, 0,
1811 (grub_int16_t) target,
1812 0, ctx->current_address,
1813 image_target);
1814 /* Higher */
1815 ctx->current_address
1816 = add_fixup_entry (&ctx->lst, 0,
1817 (grub_int16_t) ((target & 0x80008000UL) >> 32),
1818 0, ctx->current_address,
1819 image_target);
1820 /* Highest */
1821 ctx->current_address
1822 = add_fixup_entry (&ctx->lst, 0,
1823 (grub_uint16_t) ((target & 0x800080008000UL) >> 48),
1824 0, ctx->current_address,
1825 image_target);
1826 }
1827 break;
1828 case R_MIPS_HIGHER:
1829 {
1830 Elf_Addr target = sym_addr + addend;
1831
1832 ctx->current_address
1833 = add_fixup_entry (&ctx->lst,
1834 GRUB_PE32_REL_BASED_MIPS_HIGHER,
1835 addr, 0, ctx->current_address,
1836 image_target);
1837 /* Lo */
1838 ctx->current_address
1839 = add_fixup_entry (&ctx->lst, 0,
1840 (grub_int16_t) target,
1841 0, ctx->current_address,
1842 image_target);
1843 /* Hi */
1844 ctx->current_address
1845 = add_fixup_entry (&ctx->lst, 0,
1846 (grub_int16_t) ((target & 0x8000UL) >> 16),
1847 0, ctx->current_address,
1848 image_target);
1849 /* Highest */
1850 ctx->current_address
1851 = add_fixup_entry (&ctx->lst, 0,
1852 (grub_uint16_t) ((target & 0x800080008000UL) >> 48),
1853 0, ctx->current_address,
1854 image_target);
1855 }
1856 break;
1857 case R_MIPS_HIGHEST:
1858 {
1859 Elf_Addr target = sym_addr + addend;
1860
1861 ctx->current_address
1862 = add_fixup_entry (&ctx->lst,
1863 GRUB_PE32_REL_BASED_MIPS_HIGHEST,
1864 addr, 0, ctx->current_address,
1865 image_target);
1866 /* Lo */
1867 ctx->current_address
1868 = add_fixup_entry (&ctx->lst, 0,
1869 (grub_int16_t) target,
1870 0, ctx->current_address,
1871 image_target);
1872 /* Hi */
1873 ctx->current_address
1874 = add_fixup_entry (&ctx->lst, 0,
1875 (grub_int16_t) ((target & 0x8000UL) >> 16),
1876 0, ctx->current_address,
1877 image_target);
1878 /* Higher */
1879 ctx->current_address
1880 = add_fixup_entry (&ctx->lst, 0,
1881 (grub_int16_t) ((target & 0x80008000UL) >> 32),
1882 0, ctx->current_address,
1883 image_target);
1884 }
1885 break;
1886 default:
1887 grub_util_error (_("relocation 0x%x is not implemented yet"),
1888 (unsigned int) ELF_R_TYPE (info));
1889 break;
1890 }
1891 break;
1892 #endif
1893 #if defined(MKIMAGE_ELF32)
1894 case EM_ARM:
1895 switch (ELF_R_TYPE (info))
1896 {
1897 case R_ARM_V4BX:
1898 /* Relative relocations do not require fixup entries. */
1899 case R_ARM_JUMP24:
1900 case R_ARM_THM_CALL:
1901 case R_ARM_THM_JUMP19:
1902 case R_ARM_THM_JUMP24:
1903 case R_ARM_CALL:
1904 {
1905 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1906 }
1907 break;
1908 /* Create fixup entry for PE/COFF loader */
1909 case R_ARM_ABS32:
1910 {
1911 ctx->current_address
1912 = add_fixup_entry (&ctx->lst,
1913 GRUB_PE32_REL_BASED_HIGHLOW,
1914 addr, 0, ctx->current_address,
1915 image_target);
1916 }
1917 break;
1918 default:
1919 grub_util_error (_("relocation 0x%x is not implemented yet"),
1920 (unsigned int) ELF_R_TYPE (info));
1921 break;
1922 }
1923 break;
1924 #endif /* defined(MKIMAGE_ELF32) */
1925 case EM_RISCV:
1926 switch (ELF_R_TYPE (info))
1927 {
1928 case R_RISCV_32:
1929 {
1930 ctx->current_address
1931 = add_fixup_entry (&ctx->lst,
1932 GRUB_PE32_REL_BASED_HIGHLOW,
1933 addr, 0, ctx->current_address,
1934 image_target);
1935 }
1936 break;
1937 case R_RISCV_64:
1938 {
1939 ctx->current_address
1940 = add_fixup_entry (&ctx->lst,
1941 GRUB_PE32_REL_BASED_DIR64,
1942 addr, 0, ctx->current_address,
1943 image_target);
1944 }
1945 break;
1946 /* Relative relocations do not require fixup entries. */
1947 case R_RISCV_BRANCH:
1948 case R_RISCV_JAL:
1949 case R_RISCV_CALL:
1950 case R_RISCV_PCREL_HI20:
1951 case R_RISCV_PCREL_LO12_I:
1952 case R_RISCV_PCREL_LO12_S:
1953 case R_RISCV_RVC_BRANCH:
1954 case R_RISCV_RVC_JUMP:
1955 case R_RISCV_ADD32:
1956 case R_RISCV_SUB32:
1957 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1958 break;
1959 case R_RISCV_HI20:
1960 {
1961 ctx->current_address
1962 = add_fixup_entry (&ctx->lst,
1963 GRUB_PE32_REL_BASED_RISCV_HI20,
1964 addr, 0, ctx->current_address,
1965 image_target);
1966 }
1967 break;
1968 case R_RISCV_LO12_I:
1969 {
1970 ctx->current_address
1971 = add_fixup_entry (&ctx->lst,
1972 GRUB_PE32_REL_BASED_RISCV_LOW12I,
1973 addr, 0, ctx->current_address,
1974 image_target);
1975 }
1976 break;
1977 case R_RISCV_LO12_S:
1978 {
1979 ctx->current_address
1980 = add_fixup_entry (&ctx->lst,
1981 GRUB_PE32_REL_BASED_RISCV_LOW12S,
1982 addr, 0, ctx->current_address,
1983 image_target);
1984 }
1985 break;
1986 case R_RISCV_RELAX:
1987 break;
1988 default:
1989 grub_util_error (_("relocation 0x%x is not implemented yet"),
1990 (unsigned int) ELF_R_TYPE (info));
1991 break;
1992 }
1993 break;
1994 default:
1995 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1996 }
1997 }
1998
1999 static enum raw_reloc_type
2000 classify_raw_reloc (Elf_Addr info,
2001 const struct grub_install_image_target_desc *image_target)
2002 {
2003 /* Necessary to relocate only absolute addresses. */
2004 switch (image_target->elf_target)
2005 {
2006 case EM_ARM:
2007 switch (ELF_R_TYPE (info))
2008 {
2009 case R_ARM_V4BX:
2010 case R_ARM_JUMP24:
2011 case R_ARM_THM_CALL:
2012 case R_ARM_THM_JUMP19:
2013 case R_ARM_THM_JUMP24:
2014 case R_ARM_CALL:
2015 return RAW_RELOC_NONE;
2016 case R_ARM_ABS32:
2017 return RAW_RELOC_32;
2018 default:
2019 grub_util_error (_("relocation 0x%x is not implemented yet"),
2020 (unsigned int) ELF_R_TYPE (info));
2021 break;
2022 }
2023 break;
2024 default:
2025 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
2026 }
2027 }
2028
2029 static void
2030 translate_relocation_raw (struct translate_context *ctx,
2031 Elf_Addr addr,
2032 Elf_Addr info,
2033 const struct grub_install_image_target_desc *image_target)
2034 {
2035 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
2036 struct raw_reloc *rel;
2037 if (class == RAW_RELOC_NONE)
2038 return;
2039 rel = xmalloc (sizeof (*rel));
2040 rel->next = ctx->raw_relocs;
2041 rel->type = class;
2042 rel->offset = addr;
2043 ctx->raw_relocs = rel;
2044 }
2045
2046 static void
2047 translate_relocation (struct translate_context *ctx,
2048 Elf_Addr addr,
2049 Elf_Addr info,
2050 Elf_Addr sym_addr,
2051 Elf_Addr addend,
2052 const struct grub_install_image_target_desc *image_target)
2053 {
2054 if (image_target->id == IMAGE_EFI)
2055 translate_relocation_pe (ctx, addr, info, sym_addr, addend, image_target);
2056 else
2057 translate_relocation_raw (ctx, addr, info, image_target);
2058 }
2059
2060 static void
2061 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2062 const struct grub_install_image_target_desc *image_target)
2063 {
2064 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
2065
2066 {
2067 grub_uint8_t *ptr;
2068 layout->reloc_section = ptr = xmalloc (ctx->current_address);
2069 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
2070 if (ctx->lst->state)
2071 {
2072 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
2073 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
2074 }
2075 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
2076 }
2077
2078 for (ctx->lst = ctx->lst0; ctx->lst; )
2079 {
2080 struct fixup_block_list *next;
2081 next = ctx->lst->next;
2082 free (ctx->lst);
2083 ctx->lst = next;
2084 }
2085
2086 layout->reloc_size = ctx->current_address;
2087 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
2088 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
2089 "This breaks assembly assumptions. Please increase stack size",
2090 (int) layout->reloc_size,
2091 (int) GRUB_KERNEL_ARM_STACK_SIZE);
2092 }
2093
2094 /*
2095 Layout:
2096 <type 0 relocations>
2097 <fffffffe>
2098 <type 1 relocations>
2099 <fffffffe>
2100 ...
2101 <type n relocations>
2102 <ffffffff>
2103 each relocation starts with 32-bit offset. Rest depends on relocation.
2104 mkimage stops when it sees first unknown type or end marker.
2105 This allows images to be created with mismatched mkimage and
2106 kernel as long as no relocations are present in kernel that mkimage
2107 isn't aware of (in which case mkimage aborts).
2108 This also allows simple assembly to do the relocs.
2109 */
2110
2111 #define RAW_SEPARATOR 0xfffffffe
2112 #define RAW_END_MARKER 0xffffffff
2113
2114 static void
2115 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2116 const struct grub_install_image_target_desc *image_target)
2117 {
2118 size_t count = 0, sz;
2119 enum raw_reloc_type highest = RAW_RELOC_NONE;
2120 enum raw_reloc_type curtype;
2121 struct raw_reloc *cur;
2122 grub_uint32_t *p;
2123 if (!ctx->raw_relocs)
2124 {
2125 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
2126 p[0] = RAW_END_MARKER;
2127 layout->reloc_size = sizeof (grub_uint32_t);
2128 return;
2129 }
2130 for (cur = ctx->raw_relocs; cur; cur = cur->next)
2131 {
2132 count++;
2133 if (cur->type > highest)
2134 highest = cur->type;
2135 }
2136 /* highest separators, count relocations and one end marker. */
2137 sz = (highest + count + 1) * sizeof (grub_uint32_t);
2138 layout->reloc_section = p = xmalloc (sz);
2139 for (curtype = 0; curtype <= highest; curtype++)
2140 {
2141 /* Support for special cases would go here. */
2142 for (cur = ctx->raw_relocs; cur; cur = cur->next)
2143 if (cur->type == curtype)
2144 {
2145 *p++ = cur->offset;
2146 }
2147 *p++ = RAW_SEPARATOR;
2148 }
2149 *--p = RAW_END_MARKER;
2150 layout->reloc_size = sz;
2151 }
2152
2153 static void
2154 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
2155 const struct grub_install_image_target_desc *image_target)
2156 {
2157 if (image_target->id == IMAGE_EFI)
2158 finish_reloc_translation_pe (ctx, layout, image_target);
2159 else
2160 finish_reloc_translation_raw (ctx, layout, image_target);
2161 }
2162
2163
2164 static void
2165 create_u64_fixups (struct translate_context *ctx,
2166 Elf_Addr jumpers, grub_size_t njumpers,
2167 const struct grub_install_image_target_desc *image_target)
2168 {
2169 unsigned i;
2170 assert (image_target->id == IMAGE_EFI);
2171 for (i = 0; i < njumpers; i++)
2172 ctx->current_address = add_fixup_entry (&ctx->lst,
2173 GRUB_PE32_REL_BASED_DIR64,
2174 jumpers + 8 * i,
2175 0, ctx->current_address,
2176 image_target);
2177 }
2178
2179 /* Make a .reloc section. */
2180 static void
2181 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
2182 struct section_metadata *smd,
2183 const struct grub_install_image_target_desc *image_target)
2184 {
2185 unsigned i;
2186 Elf_Shdr *s;
2187 struct translate_context ctx;
2188
2189 translate_reloc_start (&ctx, image_target);
2190
2191 for (i = 0, s = smd->sections; i < smd->num_sections;
2192 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2193 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
2194 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
2195 {
2196 Elf_Rela *r;
2197 Elf_Word rtab_size, r_size, num_rs;
2198 Elf_Off rtab_offset;
2199 Elf_Shdr *symtab_section;
2200 Elf_Addr section_address;
2201 Elf_Word j;
2202
2203 if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
2204 {
2205 grub_util_info ("not translating the skipped relocation section %s",
2206 smd->strtab + grub_le_to_cpu32 (s->sh_name));
2207 continue;
2208 }
2209
2210 symtab_section = (Elf_Shdr *) ((char *) smd->sections
2211 + (grub_target_to_host32 (s->sh_link)
2212 * smd->section_entsize));
2213
2214 grub_util_info ("translating the relocation section %s",
2215 smd->strtab + grub_le_to_cpu32 (s->sh_name));
2216
2217 rtab_size = grub_target_to_host (s->sh_size);
2218 r_size = grub_target_to_host (s->sh_entsize);
2219 rtab_offset = grub_target_to_host (s->sh_offset);
2220 num_rs = rtab_size / r_size;
2221
2222 section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
2223
2224 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
2225 j < num_rs;
2226 j++, r = (Elf_Rela *) ((char *) r + r_size))
2227 {
2228 Elf_Addr info;
2229 Elf_Addr offset;
2230 Elf_Addr addr;
2231 Elf_Addr sym_addr;
2232 Elf_Addr addend;
2233
2234 offset = grub_target_to_host (r->r_offset);
2235 if (image_target->elf_target == EM_MIPS && image_target->voidp_sizeof == 8)
2236 info = ((grub_uint64_t) r->r_info << 32) |
2237 (grub_uint32_t) grub_be_to_cpu64 (r->r_info);
2238 else
2239 info = grub_target_to_host (r->r_info);
2240
2241 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
2242 ELF_R_SYM (info), image_target);
2243 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
2244 grub_target_to_host (r->r_addend) : 0;
2245 addr = section_address + offset;
2246
2247 translate_relocation (&ctx, addr, info, sym_addr, addend, image_target);
2248 }
2249 }
2250
2251 if (image_target->elf_target == EM_IA_64)
2252 create_u64_fixups (&ctx,
2253 layout->ia64jmp_off
2254 + image_target->vaddr_offset,
2255 2 * layout->ia64jmpnum,
2256 image_target);
2257 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
2258 create_u64_fixups (&ctx,
2259 layout->got_off
2260 + image_target->vaddr_offset,
2261 (layout->got_size / 8),
2262 image_target);
2263
2264 finish_reloc_translation (&ctx, layout, image_target);
2265 }
2266
2267 /* Determine if this section is a text section. Return false if this
2268 section is not allocated. */
2269 static int
2270 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2271 {
2272 if (!is_relocatable (image_target)
2273 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2274 return 0;
2275 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2276 == (SHF_EXECINSTR | SHF_ALLOC));
2277 }
2278
2279 /* Determine if this section is a data section. */
2280 static int
2281 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2282 {
2283 if (!is_relocatable (image_target)
2284 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2285 return 0;
2286 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2287 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2288 }
2289
2290 static int
2291 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2292 {
2293 if (!is_relocatable (image_target))
2294 return 0;
2295 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2296 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2297 }
2298
2299 /* Determine if a section is going to be in the final output */
2300 static int
2301 SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2302 {
2303 /* We keep .text and .data */
2304 if (SUFFIX (is_text_section) (s, image_target)
2305 || SUFFIX (is_data_section) (s, image_target))
2306 return 1;
2307
2308 /*
2309 * And we keep .bss if we're producing PE binaries or the target doesn't
2310 * have a relocating loader. Platforms other than EFI and U-boot shouldn't
2311 * have .bss in their binaries as we build with -Wl,-Ttext.
2312 */
2313 if (SUFFIX (is_bss_section) (s, image_target)
2314 && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2315 return 1;
2316
2317 /* Otherwise this is not a section we're keeping in the final output. */
2318 return 0;
2319 }
2320
2321 static int
2322 SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
2323 struct section_metadata *smd)
2324 {
2325 int i;
2326 int r = 0;
2327 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2328
2329 if (!strncmp (name, ".rela.", 6))
2330 name += 5;
2331 else if (!strncmp (name, ".rel.", 5))
2332 name += 4;
2333 else
2334 return 1;
2335
2336 for (i = 0, s = smd->sections; i < smd->num_sections;
2337 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2338 {
2339 const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
2340 if (strcmp (sname, name))
2341 continue;
2342
2343 return SUFFIX (is_kept_section) (s, image_target);
2344 }
2345
2346 return r;
2347 }
2348
2349 /* Return if the ELF header is valid. */
2350 static int
2351 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
2352 {
2353 if (size < sizeof (*e)
2354 || e->e_ident[EI_MAG0] != ELFMAG0
2355 || e->e_ident[EI_MAG1] != ELFMAG1
2356 || e->e_ident[EI_MAG2] != ELFMAG2
2357 || e->e_ident[EI_MAG3] != ELFMAG3
2358 || e->e_ident[EI_VERSION] != EV_CURRENT
2359 || e->e_ident[EI_CLASS] != ELFCLASSXX
2360 || e->e_version != grub_host_to_target32 (EV_CURRENT))
2361 return 0;
2362
2363 return 1;
2364 }
2365
2366 static Elf_Addr
2367 SUFFIX (put_section) (Elf_Shdr *s, int i,
2368 Elf_Addr current_address,
2369 struct section_metadata *smd,
2370 const struct grub_install_image_target_desc *image_target)
2371 {
2372 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
2373 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2374
2375 if (align)
2376 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2377 align)
2378 - image_target->vaddr_offset;
2379
2380 grub_util_info ("locating the section %s at 0x%"
2381 GRUB_HOST_PRIxLONG_LONG,
2382 name, (unsigned long long) current_address);
2383 if (!is_relocatable (image_target))
2384 current_address = grub_host_to_target_addr (s->sh_addr)
2385 - image_target->link_addr;
2386 smd->addrs[i] = current_address;
2387 current_address += grub_host_to_target_addr (s->sh_size);
2388 return current_address;
2389 }
2390
2391 /*
2392 * Locate section addresses by merging code sections and data sections
2393 * into .text and .data, respectively.
2394 */
2395 static void
2396 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
2397 struct section_metadata *smd,
2398 struct grub_mkimage_layout *layout,
2399 const struct grub_install_image_target_desc *image_target)
2400 {
2401 int i;
2402 Elf_Shdr *s;
2403
2404 layout->align = 1;
2405 /* Page-aligning simplifies relocation handling. */
2406 if (image_target->elf_target == EM_AARCH64)
2407 layout->align = 4096;
2408
2409 layout->kernel_size = 0;
2410
2411 for (i = 0, s = smd->sections;
2412 i < smd->num_sections;
2413 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2414 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
2415 && grub_host_to_target32 (s->sh_addralign) > layout->align)
2416 layout->align = grub_host_to_target32 (s->sh_addralign);
2417
2418 /* .text */
2419 for (i = 0, s = smd->sections;
2420 i < smd->num_sections;
2421 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2422 if (SUFFIX (is_text_section) (s, image_target))
2423 {
2424 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
2425 smd, image_target);
2426 if (!is_relocatable (image_target) &&
2427 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
2428 {
2429 char *msg
2430 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
2431 " instead of 0x%llx: ld.gold bug?"),
2432 kernel_path,
2433 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
2434 (unsigned long long) image_target->link_addr);
2435 grub_util_error ("%s", msg);
2436 }
2437 }
2438
2439 #ifdef MKIMAGE_ELF32
2440 if (image_target->elf_target == EM_ARM)
2441 {
2442 grub_size_t tramp;
2443
2444 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2445
2446 tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
2447 smd->num_sections, image_target);
2448
2449 layout->tramp_off = layout->kernel_size;
2450 layout->kernel_size += ALIGN_UP (tramp, 16);
2451 }
2452 #endif
2453
2454 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
2455 image_target->section_align)
2456 - image_target->vaddr_offset;
2457 layout->exec_size = layout->kernel_size;
2458
2459 /* .data */
2460 for (i = 0, s = smd->sections;
2461 i < smd->num_sections;
2462 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2463 if (SUFFIX (is_data_section) (s, image_target))
2464 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
2465 image_target);
2466
2467 layout->bss_start = layout->kernel_size;
2468 layout->end = layout->kernel_size;
2469
2470 /* .bss */
2471 for (i = 0, s = smd->sections;
2472 i < smd->num_sections;
2473 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2474 {
2475 if (SUFFIX (is_bss_section) (s, image_target))
2476 layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
2477
2478 /*
2479 * This must to be in the last time this function passes through the loop.
2480 */
2481 smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
2482 }
2483
2484 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
2485 image_target->section_align) - image_target->vaddr_offset;
2486 /* Explicitly initialize BSS
2487 when producing PE32 to avoid a bug in EFI implementations.
2488 Platforms other than EFI and U-boot shouldn't have .bss in
2489 their binaries as we build with -Wl,-Ttext.
2490 */
2491 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
2492 layout->kernel_size = layout->end;
2493 }
2494
2495 char *
2496 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
2497 size_t total_module_size,
2498 struct grub_mkimage_layout *layout,
2499 const struct grub_install_image_target_desc *image_target)
2500 {
2501 char *kernel_img, *out_img;
2502 struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
2503 Elf_Ehdr *e;
2504 int i;
2505 Elf_Shdr *s;
2506 Elf_Off section_offset;
2507 grub_size_t kernel_size;
2508
2509 grub_memset (layout, 0, sizeof (*layout));
2510
2511 layout->start_address = 0;
2512
2513 kernel_size = grub_util_get_image_size (kernel_path);
2514 kernel_img = xmalloc (kernel_size);
2515 grub_util_load_image (kernel_path, kernel_img);
2516
2517 e = (Elf_Ehdr *) kernel_img;
2518 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
2519 grub_util_error ("invalid ELF header");
2520
2521 section_offset = grub_target_to_host (e->e_shoff);
2522 smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
2523 smd.num_sections = grub_target_to_host16 (e->e_shnum);
2524
2525 if (kernel_size < section_offset
2526 + (grub_uint32_t) smd.section_entsize * smd.num_sections)
2527 grub_util_error (_("premature end of file %s"), kernel_path);
2528
2529 smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
2530
2531 /* Relocate sections then symbols in the virtual address space. */
2532 s = (Elf_Shdr *) ((char *) smd.sections
2533 + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
2534 smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
2535
2536 smd.addrs = xmalloc (sizeof (*smd.addrs) * smd.num_sections);
2537 memset (smd.addrs, 0, sizeof (*smd.addrs) * smd.num_sections);
2538 smd.vaddrs = xmalloc (sizeof (*smd.vaddrs) * smd.num_sections);
2539 memset (smd.vaddrs, 0, sizeof (*smd.vaddrs) * smd.num_sections);
2540
2541 SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
2542
2543 if (!is_relocatable (image_target))
2544 {
2545 Elf_Addr current_address = layout->kernel_size;
2546
2547 for (i = 0, s = smd.sections;
2548 i < smd.num_sections;
2549 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2550 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2551 {
2552 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
2553 const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
2554
2555 if (sec_align)
2556 current_address = ALIGN_UP (current_address
2557 + image_target->vaddr_offset,
2558 sec_align)
2559 - image_target->vaddr_offset;
2560
2561 grub_util_info ("locating the section %s at 0x%"
2562 GRUB_HOST_PRIxLONG_LONG,
2563 name, (unsigned long long) current_address);
2564 if (!is_relocatable (image_target))
2565 current_address = grub_host_to_target_addr (s->sh_addr)
2566 - image_target->link_addr;
2567
2568 smd.vaddrs[i] = current_address
2569 + image_target->vaddr_offset;
2570 current_address += grub_host_to_target_addr (s->sh_size);
2571 }
2572 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2573 image_target->section_align)
2574 - image_target->vaddr_offset;
2575 layout->bss_size = current_address - layout->kernel_size;
2576 }
2577 else
2578 layout->bss_size = 0;
2579
2580 if (image_target->id == IMAGE_SPARC64_AOUT
2581 || image_target->id == IMAGE_SPARC64_RAW
2582 || image_target->id == IMAGE_UBOOT
2583 || image_target->id == IMAGE_COREBOOT
2584 || image_target->id == IMAGE_SPARC64_CDCORE)
2585 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
2586
2587 if (is_relocatable (image_target))
2588 {
2589 smd.symtab = NULL;
2590 for (i = 0, s = smd.sections;
2591 i < smd.num_sections;
2592 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2593 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2594 {
2595 smd.symtab = s;
2596 break;
2597 }
2598 if (! smd.symtab)
2599 grub_util_error ("%s", _("no symbol table"));
2600 #ifdef MKIMAGE_ELF64
2601 if (image_target->elf_target == EM_IA_64)
2602 {
2603 grub_size_t tramp;
2604
2605 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2606
2607 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2608
2609 layout->tramp_off = layout->kernel_size;
2610 layout->kernel_size += ALIGN_UP (tramp, 16);
2611
2612 layout->ia64jmp_off = layout->kernel_size;
2613 layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
2614 image_target);
2615 layout->kernel_size += 16 * layout->ia64jmpnum;
2616
2617 layout->got_off = layout->kernel_size;
2618 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2619 }
2620 if (image_target->elf_target == EM_AARCH64)
2621 {
2622 grub_size_t tramp;
2623
2624 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2625
2626 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2627
2628 layout->got_off = layout->kernel_size;
2629 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2630 }
2631 #endif
2632 }
2633 else
2634 {
2635 layout->reloc_size = 0;
2636 layout->reloc_section = NULL;
2637 }
2638
2639 out_img = xmalloc (layout->kernel_size + total_module_size);
2640 memset (out_img, 0, layout->kernel_size + total_module_size);
2641
2642 if (is_relocatable (image_target))
2643 {
2644 layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
2645 (char *) out_img + layout->ia64jmp_off,
2646 layout->ia64jmp_off + image_target->vaddr_offset,
2647 layout->bss_start, layout->end, image_target);
2648
2649 if (layout->start_address == (Elf_Addr) -1)
2650 grub_util_error ("start symbol is not defined");
2651
2652 /* Resolve addrs in the virtual address space. */
2653 SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
2654 layout->got_off, image_target);
2655
2656 make_reloc_section (e, layout, &smd, image_target);
2657 if (image_target->id != IMAGE_EFI)
2658 {
2659 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2660 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2661 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2662 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2663 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2664 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2665 }
2666 }
2667
2668 for (i = 0, s = smd.sections;
2669 i < smd.num_sections;
2670 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2671 if (SUFFIX (is_kept_section) (s, image_target))
2672 {
2673 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2674 memset (out_img + smd.addrs[i], 0,
2675 grub_host_to_target_addr (s->sh_size));
2676 else
2677 memcpy (out_img + smd.addrs[i],
2678 kernel_img + grub_host_to_target_addr (s->sh_offset),
2679 grub_host_to_target_addr (s->sh_size));
2680 }
2681 free (kernel_img);
2682
2683 free (smd.vaddrs);
2684 smd.vaddrs = NULL;
2685 free (smd.addrs);
2686 smd.addrs = NULL;
2687
2688 return out_img;
2689 }