]> git.proxmox.com Git - grub2.git/blob - util/grub-mkimagexx.c
RISC-V: Add awareness for RISC-V reloations
[grub2.git] / 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 info = grub_target_to_host (r->r_info);
843 sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
844 ELF_R_SYM (info), image_target);
845
846 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
847 grub_target_to_host (r->r_addend) : 0;
848
849 switch (image_target->elf_target)
850 {
851 case EM_386:
852 switch (ELF_R_TYPE (info))
853 {
854 case R_386_NONE:
855 break;
856
857 case R_386_32:
858 /* This is absolute. */
859 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
860 + addend + sym_addr);
861 grub_util_info ("relocating an R_386_32 entry to 0x%"
862 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
863 GRUB_HOST_PRIxLONG_LONG,
864 (unsigned long long) *target,
865 (unsigned long long) offset);
866 break;
867
868 case R_386_PC32:
869 /* This is relative. */
870 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
871 + addend + sym_addr
872 - target_section_addr - offset
873 - image_target->vaddr_offset);
874 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
875 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
876 GRUB_HOST_PRIxLONG_LONG,
877 (unsigned long long) *target,
878 (unsigned long long) offset);
879 break;
880 default:
881 grub_util_error (_("relocation 0x%x is not implemented yet"),
882 (unsigned int) ELF_R_TYPE (info));
883 break;
884 }
885 break;
886 #ifdef MKIMAGE_ELF64
887 case EM_X86_64:
888 switch (ELF_R_TYPE (info))
889 {
890
891 case R_X86_64_NONE:
892 break;
893
894 case R_X86_64_64:
895 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
896 + addend + sym_addr);
897 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
898 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
899 GRUB_HOST_PRIxLONG_LONG,
900 (unsigned long long) *target,
901 (unsigned long long) offset);
902 break;
903
904 case R_X86_64_PC32:
905 case R_X86_64_PLT32:
906 {
907 grub_uint32_t *t32 = (grub_uint32_t *) target;
908 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
909 + addend + sym_addr
910 - target_section_addr - offset
911 - image_target->vaddr_offset);
912 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
913 GRUB_HOST_PRIxLONG_LONG,
914 *t32, (unsigned long long) offset);
915 break;
916 }
917
918 case R_X86_64_PC64:
919 {
920 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
921 + addend + sym_addr
922 - target_section_addr - offset
923 - image_target->vaddr_offset);
924 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
925 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
926 GRUB_HOST_PRIxLONG_LONG,
927 (unsigned long long) *target,
928 (unsigned long long) offset);
929 break;
930 }
931
932 case R_X86_64_32:
933 case R_X86_64_32S:
934 {
935 grub_uint32_t *t32 = (grub_uint32_t *) target;
936 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
937 + addend + sym_addr);
938 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
939 GRUB_HOST_PRIxLONG_LONG,
940 *t32, (unsigned long long) offset);
941 break;
942 }
943
944 default:
945 grub_util_error (_("relocation 0x%x is not implemented yet"),
946 (unsigned int) ELF_R_TYPE (info));
947 break;
948 }
949 break;
950 case EM_IA_64:
951 switch (ELF_R_TYPE (info))
952 {
953 case R_IA64_PCREL21B:
954 {
955 grub_uint64_t noff;
956 grub_ia64_make_trampoline (tr, addend + sym_addr);
957 noff = ((char *) tr - (char *) pe_target
958 - target_section_addr - (offset & ~3)) >> 4;
959 tr++;
960 if (noff & ~MASK19)
961 grub_util_error ("trampoline offset too big (%"
962 GRUB_HOST_PRIxLONG_LONG ")",
963 (unsigned long long) noff);
964 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
965 }
966 break;
967
968 case R_IA64_LTOFF22X:
969 case R_IA64_LTOFF22:
970 {
971 Elf_Sym *sym;
972
973 sym = (Elf_Sym *) ((char *) e
974 + grub_target_to_host (smd->symtab->sh_offset)
975 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
976 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
977 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
978 + sym->st_value
979 - image_target->vaddr_offset));
980 }
981 /* FALLTHROUGH */
982 case R_IA64_LTOFF_FPTR22:
983 *gpptr = grub_host_to_target64 (addend + sym_addr);
984 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
985 (char *) gpptr - (char *) pe_target
986 + image_target->vaddr_offset);
987 gpptr++;
988 break;
989
990 case R_IA64_GPREL22:
991 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
992 addend + sym_addr);
993 break;
994 case R_IA64_GPREL64I:
995 grub_ia64_set_immu64 ((grub_addr_t) target,
996 addend + sym_addr);
997 break;
998 case R_IA64_PCREL64LSB:
999 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1000 + addend + sym_addr
1001 - target_section_addr - offset
1002 - image_target->vaddr_offset);
1003 break;
1004
1005 case R_IA64_SEGREL64LSB:
1006 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1007 + addend + sym_addr - target_section_addr);
1008 break;
1009 case R_IA64_DIR64LSB:
1010 case R_IA64_FPTR64LSB:
1011 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
1012 + addend + sym_addr);
1013 grub_util_info ("relocating a direct entry to 0x%"
1014 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
1015 GRUB_HOST_PRIxLONG_LONG,
1016 (unsigned long long)
1017 grub_target_to_host64 (*target),
1018 (unsigned long long) offset);
1019 break;
1020
1021 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
1022 case R_IA64_LDXMOV:
1023 break;
1024
1025 default:
1026 grub_util_error (_("relocation 0x%x is not implemented yet"),
1027 (unsigned int) ELF_R_TYPE (info));
1028 break;
1029 }
1030 break;
1031 case EM_AARCH64:
1032 {
1033 sym_addr += addend;
1034 switch (ELF_R_TYPE (info))
1035 {
1036 case R_AARCH64_ABS64:
1037 {
1038 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
1039 }
1040 break;
1041 case R_AARCH64_PREL32:
1042 {
1043 grub_uint32_t *t32 = (grub_uint32_t *) target;
1044 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
1045 + sym_addr
1046 - target_section_addr - offset
1047 - image_target->vaddr_offset);
1048 grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
1049 GRUB_HOST_PRIxLONG_LONG,
1050 *t32, (unsigned long long) offset);
1051 break;
1052 }
1053 case R_AARCH64_ADD_ABS_LO12_NC:
1054 grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
1055 sym_addr);
1056 break;
1057 case R_AARCH64_LDST64_ABS_LO12_NC:
1058 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
1059 sym_addr);
1060 break;
1061 case R_AARCH64_JUMP26:
1062 case R_AARCH64_CALL26:
1063 {
1064 sym_addr -= offset;
1065 sym_addr -= target_section_addr + image_target->vaddr_offset;
1066 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
1067 grub_util_error ("%s", "CALL26 Relocation out of range");
1068
1069 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
1070 sym_addr);
1071 }
1072 break;
1073 case R_AARCH64_ADR_GOT_PAGE:
1074 {
1075 Elf64_Rela *rel2;
1076 grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
1077 - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
1078 unsigned k;
1079 *gpptr = grub_host_to_target64 (sym_addr);
1080 unmatched_adr_got_page++;
1081 if (!grub_arm64_check_hi21_signed (gpoffset))
1082 grub_util_error ("HI21 out of range");
1083 grub_arm64_set_hi21((grub_uint32_t *)target,
1084 gpoffset);
1085 for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
1086 k < num_rs;
1087 k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
1088 if (ELF_R_SYM (rel2->r_info)
1089 == ELF_R_SYM (r->r_info)
1090 && r->r_addend == rel2->r_addend
1091 && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
1092 {
1093 grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
1094 grub_target_to_host (rel2->r_offset), image_target),
1095 ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
1096 break;
1097 }
1098 if (k >= num_rs)
1099 grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
1100 gpptr++;
1101 }
1102 break;
1103 case R_AARCH64_LD64_GOT_LO12_NC:
1104 if (unmatched_adr_got_page == 0)
1105 grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
1106 unmatched_adr_got_page--;
1107 break;
1108 case R_AARCH64_ADR_PREL_PG_HI21:
1109 {
1110 sym_addr &= ~0xfffULL;
1111 sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
1112 if (!grub_arm64_check_hi21_signed (sym_addr))
1113 grub_util_error ("%s", "CALL26 Relocation out of range");
1114
1115 grub_arm64_set_hi21((grub_uint32_t *)target,
1116 sym_addr);
1117 }
1118 break;
1119 default:
1120 grub_util_error (_("relocation 0x%x is not implemented yet"),
1121 (unsigned int) ELF_R_TYPE (info));
1122 break;
1123 }
1124 break;
1125 }
1126 #endif
1127 #if defined(MKIMAGE_ELF32)
1128 case EM_ARM:
1129 {
1130 sym_addr += addend;
1131 sym_addr -= image_target->vaddr_offset;
1132 switch (ELF_R_TYPE (info))
1133 {
1134 case R_ARM_ABS32:
1135 {
1136 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
1137 (int) sym_addr, (int) sym_addr);
1138 /* Data will be naturally aligned */
1139 if (image_target->id == IMAGE_EFI)
1140 sym_addr += 0x400;
1141 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
1142 }
1143 break;
1144 /* Happens when compiled with -march=armv4.
1145 Since currently we need at least armv5, keep bx as-is.
1146 */
1147 case R_ARM_V4BX:
1148 break;
1149 case R_ARM_THM_CALL:
1150 case R_ARM_THM_JUMP24:
1151 case R_ARM_THM_JUMP19:
1152 {
1153 grub_err_t err;
1154 Elf_Sym *sym;
1155 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
1156 (unsigned long) ((char *) target
1157 - (char *) e),
1158 sym_addr);
1159 sym = (Elf_Sym *) ((char *) e
1160 + grub_target_to_host (smd->symtab->sh_offset)
1161 + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
1162 if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
1163 sym_addr |= 1;
1164 if (!(sym_addr & 1))
1165 {
1166 grub_uint32_t tr_addr;
1167 grub_int32_t new_offset;
1168 tr_addr = (char *) tr - (char *) pe_target
1169 - target_section_addr;
1170 new_offset = sym_addr - tr_addr - 12;
1171
1172 if (!grub_arm_jump24_check_offset (new_offset))
1173 return grub_util_error ("jump24 relocation out of range");
1174
1175 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
1176 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
1177 tr += 2;
1178 sym_addr = tr_addr | 1;
1179 }
1180 sym_addr -= offset;
1181 /* Thumb instructions can be 16-bit aligned */
1182 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
1183 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
1184 else
1185 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
1186 sym_addr);
1187 if (err)
1188 grub_util_error ("%s", grub_errmsg);
1189 }
1190 break;
1191
1192 case R_ARM_CALL:
1193 case R_ARM_JUMP24:
1194 {
1195 grub_err_t err;
1196 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
1197 if (sym_addr & 1)
1198 {
1199 grub_uint32_t tr_addr;
1200 grub_int32_t new_offset;
1201 tr_addr = (char *) tr - (char *) pe_target
1202 - target_section_addr;
1203 new_offset = sym_addr - tr_addr - 12;
1204
1205 /* There is no immediate version of bx, only register one... */
1206 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
1207 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
1208 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
1209 tr[3] = grub_host_to_target32 (new_offset | 1);
1210 tr += 4;
1211 sym_addr = tr_addr;
1212 }
1213 sym_addr -= offset;
1214 err = grub_arm_reloc_jump24 (target,
1215 sym_addr);
1216 if (err)
1217 grub_util_error ("%s", grub_errmsg);
1218 }
1219 break;
1220
1221 default:
1222 grub_util_error (_("relocation 0x%x is not implemented yet"),
1223 (unsigned int) ELF_R_TYPE (info));
1224 break;
1225 }
1226 break;
1227 }
1228 #endif /* MKIMAGE_ELF32 */
1229 case EM_RISCV:
1230 {
1231 grub_uint64_t *t64 = (grub_uint64_t *) target;
1232 grub_uint32_t *t32 = (grub_uint32_t *) target;
1233 grub_uint16_t *t16 = (grub_uint16_t *) target;
1234 grub_uint8_t *t8 = (grub_uint8_t *) target;
1235 grub_int64_t off = (long)sym_addr - target_section_addr - offset
1236 - image_target->vaddr_offset;
1237
1238 /*
1239 * Instructions and instruction encoding are documented in the RISC-V
1240 * specification. This file is based on version 2.2:
1241 *
1242 * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
1243 */
1244
1245 sym_addr += addend;
1246
1247 switch (ELF_R_TYPE (info))
1248 {
1249 case R_RISCV_ADD8:
1250 *t8 = *t8 + sym_addr;
1251 break;
1252 case R_RISCV_ADD16:
1253 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) + sym_addr);
1254 break;
1255 case R_RISCV_32:
1256 case R_RISCV_ADD32:
1257 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
1258 break;
1259 case R_RISCV_64:
1260 case R_RISCV_ADD64:
1261 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
1262 break;
1263
1264 case R_RISCV_SUB8:
1265 *t8 = sym_addr - *t8;
1266 break;
1267 case R_RISCV_SUB16:
1268 *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) - sym_addr);
1269 break;
1270 case R_RISCV_SUB32:
1271 *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) - sym_addr);
1272 break;
1273 case R_RISCV_SUB64:
1274 *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) - sym_addr);
1275 break;
1276 case R_RISCV_BRANCH:
1277 {
1278 grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
1279 grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
1280 grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
1281 grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
1282 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
1283 | imm12 | imm11 | imm10_5 | imm4_1);
1284 }
1285 break;
1286 case R_RISCV_JAL:
1287 {
1288 grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
1289 grub_uint32_t imm19_12 = (off & 0xff000);
1290 grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
1291 grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
1292 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
1293 | imm20 | imm19_12 | imm11 | imm10_1);
1294 }
1295 break;
1296 case R_RISCV_CALL:
1297 {
1298 grub_uint32_t hi20, lo12;
1299
1300 if (off != (grub_int32_t)off)
1301 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)target);
1302
1303 hi20 = (off + 0x800) & 0xfffff000;
1304 lo12 = (off - hi20) & 0xfff;
1305 t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
1306 t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
1307 }
1308 break;
1309 case R_RISCV_RVC_BRANCH:
1310 {
1311 grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
1312 grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
1313 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1314 grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
1315 grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
1316 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
1317 | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
1318 }
1319 break;
1320 case R_RISCV_RVC_JUMP:
1321 {
1322 grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
1323 grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
1324 grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
1325 grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
1326 grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
1327 grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
1328 grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
1329 grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
1330 *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
1331 | imm11 | imm10 | imm9_8 | imm7 | imm6
1332 | imm5 | imm4 | imm3_1);
1333 }
1334 break;
1335 case R_RISCV_PCREL_HI20:
1336 {
1337 grub_int32_t hi20;
1338
1339 if (off != (grub_int32_t)off)
1340 grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)target);
1341
1342 hi20 = (off + 0x800) & 0xfffff000;
1343 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
1344 }
1345 break;
1346 case R_RISCV_PCREL_LO12_I:
1347 case R_RISCV_PCREL_LO12_S:
1348 {
1349 Elf_Rela *rel2;
1350 Elf_Word k;
1351 /* Search backwards for matching HI20 reloc. */
1352 for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
1353 k > 0;
1354 k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
1355 {
1356 Elf_Addr rel2_info;
1357 Elf_Addr rel2_offset;
1358 Elf_Addr rel2_sym_addr;
1359 Elf_Addr rel2_addend;
1360 Elf_Addr rel2_loc;
1361 grub_int64_t rel2_off;
1362
1363 rel2_offset = grub_target_to_host (rel2->r_offset);
1364 rel2_info = grub_target_to_host (rel2->r_info);
1365 rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
1366
1367 if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
1368 && rel2_loc == sym_addr)
1369 {
1370 rel2_sym_addr = SUFFIX (get_symbol_address)
1371 (e, smd->symtab, ELF_R_SYM (rel2_info),
1372 image_target);
1373 rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
1374 grub_target_to_host (rel2->r_addend) : 0;
1375 rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
1376 off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
1377
1378 if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
1379 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
1380 else
1381 {
1382 grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
1383 grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
1384 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1385 }
1386 break;
1387 }
1388 }
1389 if (k == 0)
1390 grub_util_error ("cannot find matching HI20 relocation");
1391 }
1392 break;
1393 case R_RISCV_HI20:
1394 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
1395 break;
1396 case R_RISCV_LO12_I:
1397 {
1398 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1399 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
1400 }
1401 break;
1402 case R_RISCV_LO12_S:
1403 {
1404 grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
1405 grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
1406 grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
1407 *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
1408 }
1409 break;
1410 case R_RISCV_RELAX:
1411 break;
1412 default:
1413 grub_util_error (_("relocation 0x%x is not implemented yet"),
1414 (unsigned int) ELF_R_TYPE (info));
1415 break;
1416 }
1417 break;
1418 }
1419 default:
1420 grub_util_error ("unknown architecture type %d",
1421 image_target->elf_target);
1422 }
1423 }
1424 }
1425 }
1426
1427 /* Add a PE32's fixup entry for a relocation. Return the resulting address
1428 after having written to the file OUT. */
1429 static Elf_Addr
1430 add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
1431 Elf_Addr addr, int flush, Elf_Addr current_address,
1432 const struct grub_install_image_target_desc *image_target)
1433 {
1434 struct grub_pe32_fixup_block *b;
1435
1436 b = &((*cblock)->b);
1437
1438 /* First, check if it is necessary to write out the current block. */
1439 if ((*cblock)->state)
1440 {
1441 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
1442 {
1443 grub_uint32_t size;
1444
1445 if (flush)
1446 {
1447 /* Add as much padding as necessary to align the address
1448 with a section boundary. */
1449 Elf_Addr next_address;
1450 unsigned padding_size;
1451 size_t cur_index;
1452
1453 next_address = current_address + b->block_size;
1454 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
1455 - next_address)
1456 >> 1);
1457 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1458 grub_util_info ("adding %d padding fixup entries", padding_size);
1459 while (padding_size--)
1460 {
1461 b->entries[cur_index++] = 0;
1462 b->block_size += 2;
1463 }
1464 }
1465 else while (b->block_size & (8 - 1))
1466 {
1467 /* If not aligned with a 32-bit boundary, add
1468 a padding entry. */
1469 size_t cur_index;
1470
1471 grub_util_info ("adding a padding fixup entry");
1472 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1473 b->entries[cur_index] = 0;
1474 b->block_size += 2;
1475 }
1476
1477 /* Flush it. */
1478 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1479 b->block_size, b->page_rva);
1480 size = b->block_size;
1481 current_address += size;
1482 b->page_rva = grub_host_to_target32 (b->page_rva);
1483 b->block_size = grub_host_to_target32 (b->block_size);
1484 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1485 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1486 *cblock = (*cblock)->next;
1487 }
1488 }
1489
1490 b = &((*cblock)->b);
1491
1492 if (! flush)
1493 {
1494 grub_uint16_t entry;
1495 size_t cur_index;
1496
1497 /* If not allocated yet, allocate a block with enough entries. */
1498 if (! (*cblock)->state)
1499 {
1500 (*cblock)->state = 1;
1501
1502 /* The spec does not mention the requirement of a Page RVA.
1503 Here, align the address with a 4K boundary for safety. */
1504 b->page_rva = (addr & ~(0x1000 - 1));
1505 b->block_size = sizeof (*b);
1506 }
1507
1508 /* Sanity check. */
1509 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1510 grub_util_error ("too many fixup entries");
1511
1512 /* Add a new entry. */
1513 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1514 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
1515 b->entries[cur_index] = grub_host_to_target16 (entry);
1516 b->block_size += 2;
1517 }
1518
1519 return current_address;
1520 }
1521
1522 struct raw_reloc
1523 {
1524 struct raw_reloc *next;
1525 grub_uint32_t offset;
1526 enum raw_reloc_type {
1527 RAW_RELOC_NONE = -1,
1528 RAW_RELOC_32 = 0,
1529 RAW_RELOC_MAX = 1,
1530 } type;
1531 };
1532
1533 struct translate_context
1534 {
1535 /* PE */
1536 struct fixup_block_list *lst, *lst0;
1537 Elf_Addr current_address;
1538
1539 /* Raw */
1540 struct raw_reloc *raw_relocs;
1541 };
1542
1543 static void
1544 translate_reloc_start (struct translate_context *ctx,
1545 const struct grub_install_image_target_desc *image_target)
1546 {
1547 grub_memset (ctx, 0, sizeof (*ctx));
1548 if (image_target->id == IMAGE_EFI)
1549 {
1550 ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
1551 memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
1552 ctx->current_address = 0;
1553 }
1554 }
1555
1556 static void
1557 translate_relocation_pe (struct translate_context *ctx,
1558 Elf_Addr addr,
1559 Elf_Addr info,
1560 const struct grub_install_image_target_desc *image_target)
1561 {
1562 /* Necessary to relocate only absolute addresses. */
1563 switch (image_target->elf_target)
1564 {
1565 case EM_386:
1566 if (ELF_R_TYPE (info) == R_386_32)
1567 {
1568 grub_util_info ("adding a relocation entry for 0x%"
1569 GRUB_HOST_PRIxLONG_LONG,
1570 (unsigned long long) addr);
1571 ctx->current_address
1572 = add_fixup_entry (&ctx->lst,
1573 GRUB_PE32_REL_BASED_HIGHLOW,
1574 addr, 0, ctx->current_address,
1575 image_target);
1576 }
1577 break;
1578 case EM_X86_64:
1579 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1580 (ELF_R_TYPE (info) == R_X86_64_32S))
1581 {
1582 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1583 }
1584 else if (ELF_R_TYPE (info) == R_X86_64_64)
1585 {
1586 grub_util_info ("adding a relocation entry for 0x%"
1587 GRUB_HOST_PRIxLONG_LONG,
1588 (unsigned long long) addr);
1589 ctx->current_address
1590 = add_fixup_entry (&ctx->lst,
1591 GRUB_PE32_REL_BASED_DIR64,
1592 addr,
1593 0, ctx->current_address,
1594 image_target);
1595 }
1596 break;
1597 case EM_IA_64:
1598 switch (ELF_R_TYPE (info))
1599 {
1600 case R_IA64_PCREL64LSB:
1601 case R_IA64_LDXMOV:
1602 case R_IA64_PCREL21B:
1603 case R_IA64_LTOFF_FPTR22:
1604 case R_IA64_LTOFF22X:
1605 case R_IA64_LTOFF22:
1606 case R_IA64_GPREL22:
1607 case R_IA64_GPREL64I:
1608 case R_IA64_SEGREL64LSB:
1609 break;
1610
1611 case R_IA64_FPTR64LSB:
1612 case R_IA64_DIR64LSB:
1613 #if 1
1614 {
1615 grub_util_info ("adding a relocation entry for 0x%"
1616 GRUB_HOST_PRIxLONG_LONG,
1617 (unsigned long long) addr);
1618 ctx->current_address
1619 = add_fixup_entry (&ctx->lst,
1620 GRUB_PE32_REL_BASED_DIR64,
1621 addr,
1622 0, ctx->current_address,
1623 image_target);
1624 }
1625 #endif
1626 break;
1627 default:
1628 grub_util_error (_("relocation 0x%x is not implemented yet"),
1629 (unsigned int) ELF_R_TYPE (info));
1630 break;
1631 }
1632 break;
1633 case EM_AARCH64:
1634 switch (ELF_R_TYPE (info))
1635 {
1636 case R_AARCH64_ABS64:
1637 {
1638 ctx->current_address
1639 = add_fixup_entry (&ctx->lst,
1640 GRUB_PE32_REL_BASED_DIR64,
1641 addr, 0, ctx->current_address,
1642 image_target);
1643 }
1644 break;
1645 /* Relative relocations do not require fixup entries. */
1646 case R_AARCH64_CALL26:
1647 case R_AARCH64_JUMP26:
1648 case R_AARCH64_PREL32:
1649 break;
1650 /* Page-relative relocations do not require fixup entries. */
1651 case R_AARCH64_ADR_PREL_PG_HI21:
1652 /* We page-align the whole kernel, so no need
1653 for fixup entries.
1654 */
1655 case R_AARCH64_ADD_ABS_LO12_NC:
1656 case R_AARCH64_LDST64_ABS_LO12_NC:
1657 break;
1658
1659 /* GOT is relocated separately. */
1660 case R_AARCH64_ADR_GOT_PAGE:
1661 case R_AARCH64_LD64_GOT_LO12_NC:
1662 break;
1663
1664 default:
1665 grub_util_error (_("relocation 0x%x is not implemented yet"),
1666 (unsigned int) ELF_R_TYPE (info));
1667 break;
1668 }
1669 break;
1670 break;
1671 #if defined(MKIMAGE_ELF32)
1672 case EM_ARM:
1673 switch (ELF_R_TYPE (info))
1674 {
1675 case R_ARM_V4BX:
1676 /* Relative relocations do not require fixup entries. */
1677 case R_ARM_JUMP24:
1678 case R_ARM_THM_CALL:
1679 case R_ARM_THM_JUMP19:
1680 case R_ARM_THM_JUMP24:
1681 case R_ARM_CALL:
1682 {
1683 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1684 }
1685 break;
1686 /* Create fixup entry for PE/COFF loader */
1687 case R_ARM_ABS32:
1688 {
1689 ctx->current_address
1690 = add_fixup_entry (&ctx->lst,
1691 GRUB_PE32_REL_BASED_HIGHLOW,
1692 addr, 0, ctx->current_address,
1693 image_target);
1694 }
1695 break;
1696 default:
1697 grub_util_error (_("relocation 0x%x is not implemented yet"),
1698 (unsigned int) ELF_R_TYPE (info));
1699 break;
1700 }
1701 break;
1702 #endif /* defined(MKIMAGE_ELF32) */
1703 case EM_RISCV:
1704 switch (ELF_R_TYPE (info))
1705 {
1706 case R_RISCV_32:
1707 {
1708 ctx->current_address
1709 = add_fixup_entry (&ctx->lst,
1710 GRUB_PE32_REL_BASED_HIGHLOW,
1711 addr, 0, ctx->current_address,
1712 image_target);
1713 }
1714 break;
1715 case R_RISCV_64:
1716 {
1717 ctx->current_address
1718 = add_fixup_entry (&ctx->lst,
1719 GRUB_PE32_REL_BASED_DIR64,
1720 addr, 0, ctx->current_address,
1721 image_target);
1722 }
1723 break;
1724 /* Relative relocations do not require fixup entries. */
1725 case R_RISCV_BRANCH:
1726 case R_RISCV_JAL:
1727 case R_RISCV_CALL:
1728 case R_RISCV_PCREL_HI20:
1729 case R_RISCV_PCREL_LO12_I:
1730 case R_RISCV_PCREL_LO12_S:
1731 case R_RISCV_RVC_BRANCH:
1732 case R_RISCV_RVC_JUMP:
1733 case R_RISCV_ADD32:
1734 case R_RISCV_SUB32:
1735 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
1736 break;
1737 case R_RISCV_HI20:
1738 {
1739 ctx->current_address
1740 = add_fixup_entry (&ctx->lst,
1741 GRUB_PE32_REL_BASED_RISCV_HI20,
1742 addr, 0, ctx->current_address,
1743 image_target);
1744 }
1745 break;
1746 case R_RISCV_LO12_I:
1747 {
1748 ctx->current_address
1749 = add_fixup_entry (&ctx->lst,
1750 GRUB_PE32_REL_BASED_RISCV_LOW12I,
1751 addr, 0, ctx->current_address,
1752 image_target);
1753 }
1754 break;
1755 case R_RISCV_LO12_S:
1756 {
1757 ctx->current_address
1758 = add_fixup_entry (&ctx->lst,
1759 GRUB_PE32_REL_BASED_RISCV_LOW12S,
1760 addr, 0, ctx->current_address,
1761 image_target);
1762 }
1763 break;
1764 case R_RISCV_RELAX:
1765 break;
1766 default:
1767 grub_util_error (_("relocation 0x%x is not implemented yet"),
1768 (unsigned int) ELF_R_TYPE (info));
1769 break;
1770 }
1771 break;
1772 default:
1773 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1774 }
1775 }
1776
1777 static enum raw_reloc_type
1778 classify_raw_reloc (Elf_Addr info,
1779 const struct grub_install_image_target_desc *image_target)
1780 {
1781 /* Necessary to relocate only absolute addresses. */
1782 switch (image_target->elf_target)
1783 {
1784 case EM_ARM:
1785 switch (ELF_R_TYPE (info))
1786 {
1787 case R_ARM_V4BX:
1788 case R_ARM_JUMP24:
1789 case R_ARM_THM_CALL:
1790 case R_ARM_THM_JUMP19:
1791 case R_ARM_THM_JUMP24:
1792 case R_ARM_CALL:
1793 return RAW_RELOC_NONE;
1794 case R_ARM_ABS32:
1795 return RAW_RELOC_32;
1796 default:
1797 grub_util_error (_("relocation 0x%x is not implemented yet"),
1798 (unsigned int) ELF_R_TYPE (info));
1799 break;
1800 }
1801 break;
1802 default:
1803 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
1804 }
1805 }
1806
1807 static void
1808 translate_relocation_raw (struct translate_context *ctx,
1809 Elf_Addr addr,
1810 Elf_Addr info,
1811 const struct grub_install_image_target_desc *image_target)
1812 {
1813 enum raw_reloc_type class = classify_raw_reloc (info, image_target);
1814 struct raw_reloc *rel;
1815 if (class == RAW_RELOC_NONE)
1816 return;
1817 rel = xmalloc (sizeof (*rel));
1818 rel->next = ctx->raw_relocs;
1819 rel->type = class;
1820 rel->offset = addr;
1821 ctx->raw_relocs = rel;
1822 }
1823
1824 static void
1825 translate_relocation (struct translate_context *ctx,
1826 Elf_Addr addr,
1827 Elf_Addr info,
1828 const struct grub_install_image_target_desc *image_target)
1829 {
1830 if (image_target->id == IMAGE_EFI)
1831 translate_relocation_pe (ctx, addr, info, image_target);
1832 else
1833 translate_relocation_raw (ctx, addr, info, image_target);
1834 }
1835
1836 static void
1837 finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1838 const struct grub_install_image_target_desc *image_target)
1839 {
1840 ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
1841
1842 {
1843 grub_uint8_t *ptr;
1844 layout->reloc_section = ptr = xmalloc (ctx->current_address);
1845 for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
1846 if (ctx->lst->state)
1847 {
1848 memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
1849 ptr += grub_target_to_host32 (ctx->lst->b.block_size);
1850 }
1851 assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
1852 }
1853
1854 for (ctx->lst = ctx->lst0; ctx->lst; )
1855 {
1856 struct fixup_block_list *next;
1857 next = ctx->lst->next;
1858 free (ctx->lst);
1859 ctx->lst = next;
1860 }
1861
1862 layout->reloc_size = ctx->current_address;
1863 if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
1864 grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
1865 "This breaks assembly assumptions. Please increase stack size",
1866 (int) layout->reloc_size,
1867 (int) GRUB_KERNEL_ARM_STACK_SIZE);
1868 }
1869
1870 /*
1871 Layout:
1872 <type 0 relocations>
1873 <fffffffe>
1874 <type 1 relocations>
1875 <fffffffe>
1876 ...
1877 <type n relocations>
1878 <ffffffff>
1879 each relocation starts with 32-bit offset. Rest depends on relocation.
1880 mkimage stops when it sees first unknown type or end marker.
1881 This allows images to be created with mismatched mkimage and
1882 kernel as long as no relocations are present in kernel that mkimage
1883 isn't aware of (in which case mkimage aborts).
1884 This also allows simple assembly to do the relocs.
1885 */
1886
1887 #define RAW_SEPARATOR 0xfffffffe
1888 #define RAW_END_MARKER 0xffffffff
1889
1890 static void
1891 finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1892 const struct grub_install_image_target_desc *image_target)
1893 {
1894 size_t count = 0, sz;
1895 enum raw_reloc_type highest = RAW_RELOC_NONE;
1896 enum raw_reloc_type curtype;
1897 struct raw_reloc *cur;
1898 grub_uint32_t *p;
1899 if (!ctx->raw_relocs)
1900 {
1901 layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
1902 p[0] = RAW_END_MARKER;
1903 layout->reloc_size = sizeof (grub_uint32_t);
1904 return;
1905 }
1906 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1907 {
1908 count++;
1909 if (cur->type > highest)
1910 highest = cur->type;
1911 }
1912 /* highest separators, count relocations and one end marker. */
1913 sz = (highest + count + 1) * sizeof (grub_uint32_t);
1914 layout->reloc_section = p = xmalloc (sz);
1915 for (curtype = 0; curtype <= highest; curtype++)
1916 {
1917 /* Support for special cases would go here. */
1918 for (cur = ctx->raw_relocs; cur; cur = cur->next)
1919 if (cur->type == curtype)
1920 {
1921 *p++ = cur->offset;
1922 }
1923 *p++ = RAW_SEPARATOR;
1924 }
1925 *--p = RAW_END_MARKER;
1926 layout->reloc_size = sz;
1927 }
1928
1929 static void
1930 finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
1931 const struct grub_install_image_target_desc *image_target)
1932 {
1933 if (image_target->id == IMAGE_EFI)
1934 finish_reloc_translation_pe (ctx, layout, image_target);
1935 else
1936 finish_reloc_translation_raw (ctx, layout, image_target);
1937 }
1938
1939
1940 static void
1941 create_u64_fixups (struct translate_context *ctx,
1942 Elf_Addr jumpers, grub_size_t njumpers,
1943 const struct grub_install_image_target_desc *image_target)
1944 {
1945 unsigned i;
1946 assert (image_target->id == IMAGE_EFI);
1947 for (i = 0; i < njumpers; i++)
1948 ctx->current_address = add_fixup_entry (&ctx->lst,
1949 GRUB_PE32_REL_BASED_DIR64,
1950 jumpers + 8 * i,
1951 0, ctx->current_address,
1952 image_target);
1953 }
1954
1955 /* Make a .reloc section. */
1956 static void
1957 make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
1958 struct section_metadata *smd,
1959 const struct grub_install_image_target_desc *image_target)
1960 {
1961 unsigned i;
1962 Elf_Shdr *s;
1963 struct translate_context ctx;
1964
1965 translate_reloc_start (&ctx, image_target);
1966
1967 for (i = 0, s = smd->sections; i < smd->num_sections;
1968 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
1969 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1970 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
1971 {
1972 Elf_Rel *r;
1973 Elf_Word rtab_size, r_size, num_rs;
1974 Elf_Off rtab_offset;
1975 Elf_Addr section_address;
1976 Elf_Word j;
1977
1978 if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
1979 {
1980 grub_util_info ("not translating the skipped relocation section %s",
1981 smd->strtab + grub_le_to_cpu32 (s->sh_name));
1982 continue;
1983 }
1984
1985 grub_util_info ("translating the relocation section %s",
1986 smd->strtab + grub_le_to_cpu32 (s->sh_name));
1987
1988 rtab_size = grub_target_to_host (s->sh_size);
1989 r_size = grub_target_to_host (s->sh_entsize);
1990 rtab_offset = grub_target_to_host (s->sh_offset);
1991 num_rs = rtab_size / r_size;
1992
1993 section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
1994
1995 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1996 j < num_rs;
1997 j++, r = (Elf_Rel *) ((char *) r + r_size))
1998 {
1999 Elf_Addr info;
2000 Elf_Addr offset;
2001 Elf_Addr addr;
2002
2003 offset = grub_target_to_host (r->r_offset);
2004 info = grub_target_to_host (r->r_info);
2005
2006 addr = section_address + offset;
2007
2008 translate_relocation (&ctx, addr, info, image_target);
2009 }
2010 }
2011
2012 if (image_target->elf_target == EM_IA_64)
2013 create_u64_fixups (&ctx,
2014 layout->ia64jmp_off
2015 + image_target->vaddr_offset,
2016 2 * layout->ia64jmpnum,
2017 image_target);
2018 if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
2019 create_u64_fixups (&ctx,
2020 layout->got_off
2021 + image_target->vaddr_offset,
2022 (layout->got_size / 8),
2023 image_target);
2024
2025 finish_reloc_translation (&ctx, layout, image_target);
2026 }
2027
2028 /* Determine if this section is a text section. Return false if this
2029 section is not allocated. */
2030 static int
2031 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2032 {
2033 if (!is_relocatable (image_target)
2034 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2035 return 0;
2036 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2037 == (SHF_EXECINSTR | SHF_ALLOC));
2038 }
2039
2040 /* Determine if this section is a data section. */
2041 static int
2042 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2043 {
2044 if (!is_relocatable (image_target)
2045 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
2046 return 0;
2047 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2048 == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2049 }
2050
2051 static int
2052 SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2053 {
2054 if (!is_relocatable (image_target))
2055 return 0;
2056 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
2057 == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
2058 }
2059
2060 /* Determine if a section is going to be in the final output */
2061 static int
2062 SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
2063 {
2064 /* We keep .text and .data */
2065 if (SUFFIX (is_text_section) (s, image_target)
2066 || SUFFIX (is_data_section) (s, image_target))
2067 return 1;
2068
2069 /*
2070 * And we keep .bss if we're producing PE binaries or the target doesn't
2071 * have a relocating loader. Platforms other than EFI and U-boot shouldn't
2072 * have .bss in their binaries as we build with -Wl,-Ttext.
2073 */
2074 if (SUFFIX (is_bss_section) (s, image_target)
2075 && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
2076 return 1;
2077
2078 /* Otherwise this is not a section we're keeping in the final output. */
2079 return 0;
2080 }
2081
2082 static int
2083 SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
2084 struct section_metadata *smd)
2085 {
2086 int i;
2087 int r = 0;
2088 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2089
2090 if (!strncmp (name, ".rela.", 6))
2091 name += 5;
2092 else if (!strncmp (name, ".rel.", 5))
2093 name += 4;
2094 else
2095 return 1;
2096
2097 for (i = 0, s = smd->sections; i < smd->num_sections;
2098 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2099 {
2100 const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
2101 if (strcmp (sname, name))
2102 continue;
2103
2104 return SUFFIX (is_kept_section) (s, image_target);
2105 }
2106
2107 return r;
2108 }
2109
2110 /* Return if the ELF header is valid. */
2111 static int
2112 SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
2113 {
2114 if (size < sizeof (*e)
2115 || e->e_ident[EI_MAG0] != ELFMAG0
2116 || e->e_ident[EI_MAG1] != ELFMAG1
2117 || e->e_ident[EI_MAG2] != ELFMAG2
2118 || e->e_ident[EI_MAG3] != ELFMAG3
2119 || e->e_ident[EI_VERSION] != EV_CURRENT
2120 || e->e_ident[EI_CLASS] != ELFCLASSXX
2121 || e->e_version != grub_host_to_target32 (EV_CURRENT))
2122 return 0;
2123
2124 return 1;
2125 }
2126
2127 static Elf_Addr
2128 SUFFIX (put_section) (Elf_Shdr *s, int i,
2129 Elf_Addr current_address,
2130 struct section_metadata *smd,
2131 const struct grub_install_image_target_desc *image_target)
2132 {
2133 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
2134 const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
2135
2136 if (align)
2137 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2138 align)
2139 - image_target->vaddr_offset;
2140
2141 grub_util_info ("locating the section %s at 0x%"
2142 GRUB_HOST_PRIxLONG_LONG,
2143 name, (unsigned long long) current_address);
2144 if (!is_relocatable (image_target))
2145 current_address = grub_host_to_target_addr (s->sh_addr)
2146 - image_target->link_addr;
2147 smd->addrs[i] = current_address;
2148 current_address += grub_host_to_target_addr (s->sh_size);
2149 return current_address;
2150 }
2151
2152 /*
2153 * Locate section addresses by merging code sections and data sections
2154 * into .text and .data, respectively.
2155 */
2156 static void
2157 SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
2158 struct section_metadata *smd,
2159 struct grub_mkimage_layout *layout,
2160 const struct grub_install_image_target_desc *image_target)
2161 {
2162 int i;
2163 Elf_Shdr *s;
2164
2165 layout->align = 1;
2166 /* Page-aligning simplifies relocation handling. */
2167 if (image_target->elf_target == EM_AARCH64)
2168 layout->align = 4096;
2169
2170 layout->kernel_size = 0;
2171
2172 for (i = 0, s = smd->sections;
2173 i < smd->num_sections;
2174 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2175 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
2176 && grub_host_to_target32 (s->sh_addralign) > layout->align)
2177 layout->align = grub_host_to_target32 (s->sh_addralign);
2178
2179 /* .text */
2180 for (i = 0, s = smd->sections;
2181 i < smd->num_sections;
2182 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2183 if (SUFFIX (is_text_section) (s, image_target))
2184 {
2185 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
2186 smd, image_target);
2187 if (!is_relocatable (image_target) &&
2188 grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
2189 {
2190 char *msg
2191 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
2192 " instead of 0x%llx: ld.gold bug?"),
2193 kernel_path,
2194 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
2195 (unsigned long long) image_target->link_addr);
2196 grub_util_error ("%s", msg);
2197 }
2198 }
2199
2200 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
2201 image_target->section_align)
2202 - image_target->vaddr_offset;
2203 layout->exec_size = layout->kernel_size;
2204
2205 /* .data */
2206 for (i = 0, s = smd->sections;
2207 i < smd->num_sections;
2208 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2209 if (SUFFIX (is_data_section) (s, image_target))
2210 layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
2211 image_target);
2212
2213 #ifdef MKIMAGE_ELF32
2214 if (image_target->elf_target == EM_ARM)
2215 {
2216 grub_size_t tramp;
2217 layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
2218 image_target->section_align) - image_target->vaddr_offset;
2219
2220 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2221
2222 tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
2223 smd->num_sections, image_target);
2224
2225 layout->tramp_off = layout->kernel_size;
2226 layout->kernel_size += ALIGN_UP (tramp, 16);
2227 }
2228 #endif
2229
2230 layout->bss_start = layout->kernel_size;
2231 layout->end = layout->kernel_size;
2232
2233 /* .bss */
2234 for (i = 0, s = smd->sections;
2235 i < smd->num_sections;
2236 i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
2237 {
2238 if (SUFFIX (is_bss_section) (s, image_target))
2239 layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
2240
2241 /*
2242 * This must to be in the last time this function passes through the loop.
2243 */
2244 smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
2245 }
2246
2247 layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
2248 image_target->section_align) - image_target->vaddr_offset;
2249 /* Explicitly initialize BSS
2250 when producing PE32 to avoid a bug in EFI implementations.
2251 Platforms other than EFI and U-boot shouldn't have .bss in
2252 their binaries as we build with -Wl,-Ttext.
2253 */
2254 if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
2255 layout->kernel_size = layout->end;
2256 }
2257
2258 char *
2259 SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
2260 size_t total_module_size,
2261 struct grub_mkimage_layout *layout,
2262 const struct grub_install_image_target_desc *image_target)
2263 {
2264 char *kernel_img, *out_img;
2265 struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
2266 Elf_Ehdr *e;
2267 int i;
2268 Elf_Shdr *s;
2269 Elf_Off section_offset;
2270 grub_size_t kernel_size;
2271
2272 grub_memset (layout, 0, sizeof (*layout));
2273
2274 layout->start_address = 0;
2275
2276 kernel_size = grub_util_get_image_size (kernel_path);
2277 kernel_img = xmalloc (kernel_size);
2278 grub_util_load_image (kernel_path, kernel_img);
2279
2280 e = (Elf_Ehdr *) kernel_img;
2281 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
2282 grub_util_error ("invalid ELF header");
2283
2284 section_offset = grub_target_to_host (e->e_shoff);
2285 smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
2286 smd.num_sections = grub_target_to_host16 (e->e_shnum);
2287
2288 if (kernel_size < section_offset
2289 + (grub_uint32_t) smd.section_entsize * smd.num_sections)
2290 grub_util_error (_("premature end of file %s"), kernel_path);
2291
2292 smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
2293
2294 /* Relocate sections then symbols in the virtual address space. */
2295 s = (Elf_Shdr *) ((char *) smd.sections
2296 + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
2297 smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
2298
2299 smd.addrs = xmalloc (sizeof (*smd.addrs) * smd.num_sections);
2300 memset (smd.addrs, 0, sizeof (*smd.addrs) * smd.num_sections);
2301 smd.vaddrs = xmalloc (sizeof (*smd.vaddrs) * smd.num_sections);
2302 memset (smd.vaddrs, 0, sizeof (*smd.vaddrs) * smd.num_sections);
2303
2304 SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
2305
2306 if (!is_relocatable (image_target))
2307 {
2308 Elf_Addr current_address = layout->kernel_size;
2309
2310 for (i = 0, s = smd.sections;
2311 i < smd.num_sections;
2312 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2313 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2314 {
2315 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
2316 const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
2317
2318 if (sec_align)
2319 current_address = ALIGN_UP (current_address
2320 + image_target->vaddr_offset,
2321 sec_align)
2322 - image_target->vaddr_offset;
2323
2324 grub_util_info ("locating the section %s at 0x%"
2325 GRUB_HOST_PRIxLONG_LONG,
2326 name, (unsigned long long) current_address);
2327 if (!is_relocatable (image_target))
2328 current_address = grub_host_to_target_addr (s->sh_addr)
2329 - image_target->link_addr;
2330
2331 smd.vaddrs[i] = current_address
2332 + image_target->vaddr_offset;
2333 current_address += grub_host_to_target_addr (s->sh_size);
2334 }
2335 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
2336 image_target->section_align)
2337 - image_target->vaddr_offset;
2338 layout->bss_size = current_address - layout->kernel_size;
2339 }
2340 else
2341 layout->bss_size = 0;
2342
2343 if (image_target->id == IMAGE_SPARC64_AOUT
2344 || image_target->id == IMAGE_SPARC64_RAW
2345 || image_target->id == IMAGE_UBOOT
2346 || image_target->id == IMAGE_COREBOOT
2347 || image_target->id == IMAGE_SPARC64_CDCORE)
2348 layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
2349
2350 if (is_relocatable (image_target))
2351 {
2352 smd.symtab = NULL;
2353 for (i = 0, s = smd.sections;
2354 i < smd.num_sections;
2355 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2356 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
2357 {
2358 smd.symtab = s;
2359 break;
2360 }
2361 if (! smd.symtab)
2362 grub_util_error ("%s", _("no symbol table"));
2363 #ifdef MKIMAGE_ELF64
2364 if (image_target->elf_target == EM_IA_64)
2365 {
2366 grub_size_t tramp;
2367
2368 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2369
2370 grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2371
2372 layout->tramp_off = layout->kernel_size;
2373 layout->kernel_size += ALIGN_UP (tramp, 16);
2374
2375 layout->ia64jmp_off = layout->kernel_size;
2376 layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
2377 image_target);
2378 layout->kernel_size += 16 * layout->ia64jmpnum;
2379
2380 layout->got_off = layout->kernel_size;
2381 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2382 }
2383 if (image_target->elf_target == EM_AARCH64)
2384 {
2385 grub_size_t tramp;
2386
2387 layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
2388
2389 grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
2390
2391 layout->got_off = layout->kernel_size;
2392 layout->kernel_size += ALIGN_UP (layout->got_size, 16);
2393 }
2394 #endif
2395 }
2396 else
2397 {
2398 layout->reloc_size = 0;
2399 layout->reloc_section = NULL;
2400 }
2401
2402 out_img = xmalloc (layout->kernel_size + total_module_size);
2403 memset (out_img, 0, layout->kernel_size + total_module_size);
2404
2405 if (is_relocatable (image_target))
2406 {
2407 layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
2408 (char *) out_img + layout->ia64jmp_off,
2409 layout->ia64jmp_off + image_target->vaddr_offset,
2410 layout->bss_start, layout->end, image_target);
2411
2412 if (layout->start_address == (Elf_Addr) -1)
2413 grub_util_error ("start symbol is not defined");
2414
2415 /* Resolve addrs in the virtual address space. */
2416 SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
2417 layout->got_off, image_target);
2418
2419 make_reloc_section (e, layout, &smd, image_target);
2420 if (image_target->id != IMAGE_EFI)
2421 {
2422 out_img = xrealloc (out_img, layout->kernel_size + total_module_size
2423 + ALIGN_UP (layout->reloc_size, image_target->mod_align));
2424 memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
2425 memset (out_img + layout->kernel_size + layout->reloc_size, 0,
2426 total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
2427 layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
2428 }
2429 }
2430
2431 for (i = 0, s = smd.sections;
2432 i < smd.num_sections;
2433 i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
2434 if (SUFFIX (is_kept_section) (s, image_target))
2435 {
2436 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
2437 memset (out_img + smd.addrs[i], 0,
2438 grub_host_to_target_addr (s->sh_size));
2439 else
2440 memcpy (out_img + smd.addrs[i],
2441 kernel_img + grub_host_to_target_addr (s->sh_offset),
2442 grub_host_to_target_addr (s->sh_size));
2443 }
2444 free (kernel_img);
2445
2446 free (smd.vaddrs);
2447 smd.vaddrs = NULL;
2448 free (smd.addrs);
2449 smd.addrs = NULL;
2450
2451 return out_img;
2452 }