]> git.proxmox.com Git - grub2.git/blame - util/grub-mkimagexx.c
configure.ac: Explicitly add -mno-sse3 on x86.
[grub2.git] / util / grub-mkimagexx.c
CommitLineData
0253aeb7
VS
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
8ea6ecb3
VS
20#undef ELF_R_SYM
21#undef ELF_R_TYPE
22
0253aeb7
VS
23#if defined(MKIMAGE_ELF32)
24# define SUFFIX(x) x ## 32
25# define ELFCLASSXX ELFCLASS32
26# define Elf_Ehdr Elf32_Ehdr
27# define Elf_Phdr Elf32_Phdr
9612ebc0 28# define Elf_Nhdr Elf32_Nhdr
0253aeb7
VS
29# define Elf_Addr Elf32_Addr
30# define Elf_Sym Elf32_Sym
31# define Elf_Off Elf32_Off
32# define Elf_Shdr Elf32_Shdr
33# define Elf_Rela Elf32_Rela
34# define Elf_Rel Elf32_Rel
c36e5cd1
VS
35# define Elf_Word Elf32_Word
36# define Elf_Half Elf32_Half
37# define Elf_Section Elf32_Section
0253aeb7
VS
38# define ELF_R_SYM(val) ELF32_R_SYM(val)
39# define ELF_R_TYPE(val) ELF32_R_TYPE(val)
c36e5cd1 40# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
9612ebc0 41#define XEN_NOTE_SIZE 132
0253aeb7
VS
42#elif defined(MKIMAGE_ELF64)
43# define SUFFIX(x) x ## 64
44# define ELFCLASSXX ELFCLASS64
45# define Elf_Ehdr Elf64_Ehdr
46# define Elf_Phdr Elf64_Phdr
9612ebc0 47# define Elf_Nhdr Elf64_Nhdr
0253aeb7
VS
48# define Elf_Addr Elf64_Addr
49# define Elf_Sym Elf64_Sym
50# define Elf_Off Elf64_Off
51# define Elf_Shdr Elf64_Shdr
52# define Elf_Rela Elf64_Rela
53# define Elf_Rel Elf64_Rel
c36e5cd1
VS
54# define Elf_Word Elf64_Word
55# define Elf_Half Elf64_Half
56# define Elf_Section Elf64_Section
0253aeb7
VS
57# define ELF_R_SYM(val) ELF64_R_SYM(val)
58# define ELF_R_TYPE(val) ELF64_R_TYPE(val)
c36e5cd1 59# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
9612ebc0 60#define XEN_NOTE_SIZE 120
0253aeb7
VS
61#else
62#error "I'm confused"
63#endif
64
389b31cd
LL
65static Elf_Addr SUFFIX (entry_point);
66
9612ebc0
VS
67static void
68SUFFIX (generate_elf) (const struct grub_install_image_target_desc *image_target,
69 int note, char **core_img, size_t *core_size,
70 Elf_Addr target_addr, grub_size_t align,
71 size_t kernel_size, size_t bss_size)
72{
73 char *elf_img;
74 size_t program_size;
75 Elf_Ehdr *ehdr;
76 Elf_Phdr *phdr;
77 Elf_Shdr *shdr;
78 int header_size, footer_size = 0;
79 int phnum = 1;
80 int shnum = 4;
81 int string_size = sizeof (".text") + sizeof ("mods") + 1;
82
83 if (image_target->id != IMAGE_LOONGSON_ELF)
84 phnum += 2;
85
86 if (note)
87 {
88 phnum++;
89 footer_size += sizeof (struct grub_ieee1275_note);
90 }
91 if (image_target->id == IMAGE_XEN)
92 {
93 phnum++;
94 shnum++;
95 string_size += sizeof (".xen");
96 footer_size += XEN_NOTE_SIZE;
97 }
98 header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
99 + shnum * sizeof (*shdr) + string_size, align);
100
101 program_size = ALIGN_ADDR (*core_size);
102
103 elf_img = xmalloc (program_size + header_size + footer_size);
104 memset (elf_img, 0, program_size + header_size);
105 memcpy (elf_img + header_size, *core_img, *core_size);
106 ehdr = (void *) elf_img;
107 phdr = (void *) (elf_img + sizeof (*ehdr));
108 shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
109 memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
110 ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
111 if (!image_target->bigendian)
112 ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
113 else
114 ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
115 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
116 ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
117 ehdr->e_type = grub_host_to_target16 (ET_EXEC);
118 ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
119 ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
120
121 ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
122 ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
123 ehdr->e_phnum = grub_host_to_target16 (phnum);
124
125 ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
126 - (grub_uint8_t *) ehdr);
127 if (image_target->id == IMAGE_LOONGSON_ELF)
128 ehdr->e_shentsize = grub_host_to_target16 (0);
129 else
130 ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
131 ehdr->e_shnum = grub_host_to_target16 (shnum);
132 ehdr->e_shstrndx = grub_host_to_target16 (1);
133
134 ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
135
136 phdr->p_type = grub_host_to_target32 (PT_LOAD);
137 phdr->p_offset = grub_host_to_target32 (header_size);
138 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
139
140 ehdr->e_entry = grub_host_to_target32 (target_addr);
141 phdr->p_vaddr = grub_host_to_target32 (target_addr);
142 phdr->p_paddr = grub_host_to_target32 (target_addr);
143 phdr->p_align = grub_host_to_target32 (align > image_target->link_align ? align : image_target->link_align);
144 if (image_target->id == IMAGE_LOONGSON_ELF)
145 ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
146 | EF_MIPS_PIC | EF_MIPS_CPIC);
147 else
148 ehdr->e_flags = 0;
149 if (image_target->id == IMAGE_LOONGSON_ELF)
150 {
151 phdr->p_filesz = grub_host_to_target32 (*core_size);
152 phdr->p_memsz = grub_host_to_target32 (*core_size);
153 }
154 else
155 {
156 grub_uint32_t target_addr_mods;
157 phdr->p_filesz = grub_host_to_target32 (kernel_size);
158 phdr->p_memsz = grub_host_to_target32 (kernel_size + bss_size);
159
160 phdr++;
161 phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
162 phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
163 phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
164 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
165 phdr->p_align = grub_host_to_target32 (image_target->link_align);
166
167 phdr++;
168 phdr->p_type = grub_host_to_target32 (PT_LOAD);
169 phdr->p_offset = grub_host_to_target32 (header_size + kernel_size);
170 phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
171 phdr->p_filesz = phdr->p_memsz
172 = grub_host_to_target32 (*core_size - kernel_size);
173
881c6a10
VS
174 if (image_target->id == IMAGE_COREBOOT)
175 target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
176 else
177 target_addr_mods = ALIGN_UP (target_addr + kernel_size + bss_size
178 + image_target->mod_gap,
179 image_target->mod_align);
9612ebc0
VS
180 phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
181 phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
182 phdr->p_align = grub_host_to_target32 (image_target->link_align);
183 }
184
185 if (image_target->id == IMAGE_XEN)
186 {
187 char *note_start = (elf_img + program_size + header_size);
188 Elf_Nhdr *note_ptr;
189 char *ptr = (char *) note_start;
190
191 grub_util_info ("adding XEN NOTE segment");
192
193 /* Guest OS. */
194 note_ptr = (Elf_Nhdr *) ptr;
195 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
196 note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
197 note_ptr->n_type = grub_host_to_target32 (6);
198 ptr += sizeof (Elf_Nhdr);
199 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
200 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
201 memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
202 ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
203
204 /* Loader. */
205 note_ptr = (Elf_Nhdr *) ptr;
206 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
207 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
208 note_ptr->n_type = grub_host_to_target32 (8);
209 ptr += sizeof (Elf_Nhdr);
210 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
211 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
212 memcpy (ptr, "generic", sizeof ("generic"));
213 ptr += ALIGN_UP (sizeof ("generic"), 4);
214
215 /* Version. */
216 note_ptr = (Elf_Nhdr *) ptr;
217 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
218 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
219 note_ptr->n_type = grub_host_to_target32 (5);
220 ptr += sizeof (Elf_Nhdr);
221 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
222 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
223 memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
224 ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
225
226 /* Entry. */
227 note_ptr = (Elf_Nhdr *) ptr;
228 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
229 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
230 note_ptr->n_type = grub_host_to_target32 (1);
231 ptr += sizeof (Elf_Nhdr);
232 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
233 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
234 memset (ptr, 0, image_target->voidp_sizeof);
235 ptr += image_target->voidp_sizeof;
236
237 /* Virt base. */
238 note_ptr = (Elf_Nhdr *) ptr;
239 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
240 note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
241 note_ptr->n_type = grub_host_to_target32 (3);
242 ptr += sizeof (Elf_Nhdr);
243 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
244 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
245 memset (ptr, 0, image_target->voidp_sizeof);
246 ptr += image_target->voidp_sizeof;
247
248 /* PAE. */
249 if (image_target->elf_target == EM_386)
250 {
251 note_ptr = (Elf_Nhdr *) ptr;
252 note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
253 note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
254 note_ptr->n_type = grub_host_to_target32 (9);
255 ptr += sizeof (Elf_Nhdr);
256 memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
257 ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
258 memcpy (ptr, "yes", sizeof ("yes"));
259 ptr += ALIGN_UP (sizeof ("yes"), 4);
260 }
261
262 assert (XEN_NOTE_SIZE == (ptr - note_start));
263
264 phdr++;
265 phdr->p_type = grub_host_to_target32 (PT_NOTE);
266 phdr->p_flags = grub_host_to_target32 (PF_R);
267 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
268 phdr->p_vaddr = 0;
269 phdr->p_paddr = 0;
270 phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
271 phdr->p_memsz = 0;
272 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
273 }
274
275 if (note)
276 {
277 int note_size = sizeof (struct grub_ieee1275_note);
278 struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
279 (elf_img + program_size + header_size);
280
281 grub_util_info ("adding CHRP NOTE segment");
282
283 note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
284 note_ptr->header.n_descsz = grub_host_to_target32 (note_size);
285 note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
286 strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
287 note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
288 note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
289 note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
290 note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
291 note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
292 note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
293
294 phdr++;
295 phdr->p_type = grub_host_to_target32 (PT_NOTE);
296 phdr->p_flags = grub_host_to_target32 (PF_R);
297 phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
298 phdr->p_vaddr = 0;
299 phdr->p_paddr = 0;
300 phdr->p_filesz = grub_host_to_target32 (note_size);
301 phdr->p_memsz = 0;
302 phdr->p_offset = grub_host_to_target32 (header_size + program_size);
303 }
304
305 {
306 char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
307 + shnum * sizeof (*shdr));
308 char *ptr = str_start + 1;
309
310 shdr++;
311
312 shdr->sh_name = grub_host_to_target32 (0);
313 shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
314 shdr->sh_addr = grub_host_to_target_addr (0);
315 shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
316 shdr->sh_size = grub_host_to_target32 (string_size);
317 shdr->sh_link = grub_host_to_target32 (0);
318 shdr->sh_info = grub_host_to_target32 (0);
319 shdr->sh_addralign = grub_host_to_target32 (align);
320 shdr->sh_entsize = grub_host_to_target32 (0);
321 shdr++;
322
323 memcpy (ptr, ".text", sizeof (".text"));
324
325 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
326 ptr += sizeof (".text");
327 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
328 shdr->sh_addr = grub_host_to_target_addr (target_addr);
329 shdr->sh_offset = grub_host_to_target_addr (header_size);
330 shdr->sh_size = grub_host_to_target32 (kernel_size);
331 shdr->sh_link = grub_host_to_target32 (0);
332 shdr->sh_info = grub_host_to_target32 (0);
333 shdr->sh_addralign = grub_host_to_target32 (align);
334 shdr->sh_entsize = grub_host_to_target32 (0);
335 shdr++;
336
337 memcpy (ptr, "mods", sizeof ("mods"));
338 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
339 ptr += sizeof ("mods");
340 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
341 shdr->sh_addr = grub_host_to_target_addr (target_addr + kernel_size);
342 shdr->sh_offset = grub_host_to_target_addr (header_size + kernel_size);
343 shdr->sh_size = grub_host_to_target32 (*core_size - kernel_size);
344 shdr->sh_link = grub_host_to_target32 (0);
345 shdr->sh_info = grub_host_to_target32 (0);
346 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
347 shdr->sh_entsize = grub_host_to_target32 (0);
348 shdr++;
349
350 if (image_target->id == IMAGE_XEN)
351 {
352 memcpy (ptr, ".xen", sizeof (".xen"));
353 shdr->sh_name = grub_host_to_target32 (ptr - str_start);
354 ptr += sizeof (".xen");
355 shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
356 shdr->sh_addr = grub_host_to_target_addr (target_addr + kernel_size);
357 shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
358 shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
359 shdr->sh_link = grub_host_to_target32 (0);
360 shdr->sh_info = grub_host_to_target32 (0);
361 shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
362 shdr->sh_entsize = grub_host_to_target32 (0);
363 shdr++;
364 }
365 }
366
367 free (*core_img);
368 *core_img = elf_img;
369 *core_size = program_size + header_size + footer_size;
370}
371
0253aeb7
VS
372/* Relocate symbols; note that this function overwrites the symbol table.
373 Return the address of a start symbol. */
374static Elf_Addr
375SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
376 Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
377 Elf_Half section_entsize, Elf_Half num_sections,
5452733f 378 void *jumpers, Elf_Addr jumpers_addr,
ec16e026 379 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
380{
381 Elf_Word symtab_size, sym_size, num_syms;
382 Elf_Off symtab_offset;
383 Elf_Addr start_address = 0;
384 Elf_Sym *sym;
385 Elf_Word i;
386 Elf_Shdr *strtab_section;
387 const char *strtab;
5452733f 388 grub_uint64_t *jptr = jumpers;
0253aeb7
VS
389
390 strtab_section
391 = (Elf_Shdr *) ((char *) sections
392 + (grub_target_to_host32 (symtab_section->sh_link)
393 * section_entsize));
962b15b4 394 strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);
0253aeb7 395
962b15b4
VS
396 symtab_size = grub_target_to_host (symtab_section->sh_size);
397 sym_size = grub_target_to_host (symtab_section->sh_entsize);
398 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
0253aeb7
VS
399 num_syms = symtab_size / sym_size;
400
401 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
402 i < num_syms;
403 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
404 {
495fc8c1 405 Elf_Section cur_index;
0253aeb7
VS
406 const char *name;
407
408 name = strtab + grub_target_to_host32 (sym->st_name);
409
495fc8c1
VS
410 cur_index = grub_target_to_host16 (sym->st_shndx);
411 if (cur_index == STN_ABS)
0253aeb7
VS
412 {
413 continue;
414 }
7cb24eb5 415 else if (cur_index == STN_UNDEF)
0253aeb7
VS
416 {
417 if (sym->st_name)
418 grub_util_error ("undefined symbol %s", name);
419 else
420 continue;
421 }
495fc8c1
VS
422 else if (cur_index >= num_sections)
423 grub_util_error ("section %d does not exist", cur_index);
0253aeb7 424
bea33583 425 sym->st_value = (grub_target_to_host (sym->st_value)
495fc8c1 426 + section_addresses[cur_index]);
5452733f
VS
427
428 if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
429 == STT_FUNC)
430 {
d5e2a158 431 *jptr = grub_host_to_target64 (sym->st_value);
5452733f
VS
432 sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
433 jptr++;
434 *jptr = 0;
435 jptr++;
436 }
18e76955
VS
437 grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
438 " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
495fc8c1
VS
439 (unsigned long long) sym->st_value,
440 (unsigned long long) section_addresses[cur_index]);
0253aeb7
VS
441
442 if (! start_address)
443 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
444 start_address = sym->st_value;
445 }
446
447 return start_address;
448}
449
450/* Return the address of a symbol at the index I in the section S. */
451static Elf_Addr
452SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
ec16e026 453 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
454{
455 Elf_Sym *sym;
456
457 sym = (Elf_Sym *) ((char *) e
d5e2a158
VS
458 + grub_target_to_host (s->sh_offset)
459 + i * grub_target_to_host (s->sh_entsize));
0253aeb7
VS
460 return sym->st_value;
461}
462
463/* Return the address of a modified value. */
464static Elf_Addr *
465SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
ec16e026 466 const struct grub_install_image_target_desc *image_target)
0253aeb7 467{
d5e2a158 468 return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
0253aeb7
VS
469}
470
495fc8c1 471#ifdef MKIMAGE_ELF64
5452733f
VS
472static Elf_Addr
473SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
ec16e026 474 const struct grub_install_image_target_desc *image_target)
5452733f
VS
475{
476 Elf_Word symtab_size, sym_size, num_syms;
477 Elf_Off symtab_offset;
5452733f
VS
478 Elf_Sym *sym;
479 Elf_Word i;
480 int ret = 0;
481
482 symtab_size = grub_target_to_host (symtab_section->sh_size);
483 sym_size = grub_target_to_host (symtab_section->sh_entsize);
484 symtab_offset = grub_target_to_host (symtab_section->sh_offset);
485 num_syms = symtab_size / sym_size;
486
487 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
488 i < num_syms;
489 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
490 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
491 ret++;
492
493 return ret;
494}
495fc8c1 495#endif
5452733f 496
8c534b85
VS
497#ifdef MKIMAGE_ELF32
498/* Deal with relocation information. This function relocates addresses
499 within the virtual address space starting from 0. So only relative
500 addresses can be fully resolved. Absolute addresses must be relocated
501 again by a PE32 relocator when loaded. */
502static grub_size_t
503arm_get_trampoline_size (Elf_Ehdr *e,
504 Elf_Shdr *sections,
505 Elf_Half section_entsize,
506 Elf_Half num_sections,
507 const struct grub_install_image_target_desc *image_target)
508{
509 Elf_Half i;
510 Elf_Shdr *s;
511 grub_size_t ret = 0;
512
513 for (i = 0, s = sections;
514 i < num_sections;
515 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
516 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
517 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
518 {
519 Elf_Rela *r;
520 Elf_Word rtab_size, r_size, num_rs;
521 Elf_Off rtab_offset;
522 Elf_Shdr *symtab_section;
523 Elf_Word j;
524
525 symtab_section = (Elf_Shdr *) ((char *) sections
526 + (grub_target_to_host32 (s->sh_link)
527 * section_entsize));
528
529 rtab_size = grub_target_to_host (s->sh_size);
530 r_size = grub_target_to_host (s->sh_entsize);
531 rtab_offset = grub_target_to_host (s->sh_offset);
532 num_rs = rtab_size / r_size;
533
534 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
535 j < num_rs;
536 j++, r = (Elf_Rela *) ((char *) r + r_size))
537 {
538 Elf_Addr info;
539 Elf_Addr sym_addr;
540
541 info = grub_target_to_host (r->r_info);
542 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
543 ELF_R_SYM (info), image_target);
544
545 sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
546 grub_target_to_host (r->r_addend) : 0;
547
548 switch (ELF_R_TYPE (info))
549 {
550 case R_ARM_ABS32:
551 case R_ARM_V4BX:
552 break;
553 case R_ARM_THM_CALL:
554 case R_ARM_THM_JUMP24:
555 case R_ARM_THM_JUMP19:
556 if (!(sym_addr & 1))
557 ret += 8;
558 break;
559
560 case R_ARM_CALL:
561 case R_ARM_JUMP24:
562 if (sym_addr & 1)
563 ret += 16;
564 break;
565
566 default:
d6c2782a
VS
567 grub_util_error (_("relocation 0x%x is not implemented yet"),
568 (unsigned int) ELF_R_TYPE (info));
8c534b85
VS
569 break;
570 }
571 }
572 }
573 return ret;
574}
575#endif
576
0253aeb7
VS
577/* Deal with relocation information. This function relocates addresses
578 within the virtual address space starting from 0. So only relative
579 addresses can be fully resolved. Absolute addresses must be relocated
580 again by a PE32 relocator when loaded. */
581static void
582SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
583 Elf_Addr *section_addresses,
584 Elf_Half section_entsize, Elf_Half num_sections,
5452733f
VS
585 const char *strtab,
586 char *pe_target, Elf_Addr tramp_off,
587 Elf_Addr got_off,
ec16e026 588 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
589{
590 Elf_Half i;
591 Elf_Shdr *s;
495fc8c1 592#ifdef MKIMAGE_ELF64
d5e2a158 593 struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
5452733f 594 grub_uint64_t *gpptr = (void *) (pe_target + got_off);
d5e2a158 595#define MASK19 ((1 << 19) - 1)
8c534b85
VS
596#else
597 grub_uint32_t *tr = (void *) (pe_target + tramp_off);
495fc8c1 598#endif
0253aeb7
VS
599
600 for (i = 0, s = sections;
601 i < num_sections;
602 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
603 if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
604 (s->sh_type == grub_host_to_target32 (SHT_RELA)))
605 {
606 Elf_Rela *r;
607 Elf_Word rtab_size, r_size, num_rs;
608 Elf_Off rtab_offset;
609 Elf_Shdr *symtab_section;
610 Elf_Word target_section_index;
611 Elf_Addr target_section_addr;
612 Elf_Shdr *target_section;
613 Elf_Word j;
614
615 symtab_section = (Elf_Shdr *) ((char *) sections
616 + (grub_target_to_host32 (s->sh_link)
617 * section_entsize));
618 target_section_index = grub_target_to_host32 (s->sh_info);
619 target_section_addr = section_addresses[target_section_index];
620 target_section = (Elf_Shdr *) ((char *) sections
621 + (target_section_index
622 * section_entsize));
623
624 grub_util_info ("dealing with the relocation section %s for %s",
625 strtab + grub_target_to_host32 (s->sh_name),
626 strtab + grub_target_to_host32 (target_section->sh_name));
627
d5e2a158
VS
628 rtab_size = grub_target_to_host (s->sh_size);
629 r_size = grub_target_to_host (s->sh_entsize);
630 rtab_offset = grub_target_to_host (s->sh_offset);
0253aeb7
VS
631 num_rs = rtab_size / r_size;
632
633 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
634 j < num_rs;
635 j++, r = (Elf_Rela *) ((char *) r + r_size))
636 {
637 Elf_Addr info;
638 Elf_Addr offset;
639 Elf_Addr sym_addr;
640 Elf_Addr *target;
641 Elf_Addr addend;
642
643 offset = grub_target_to_host (r->r_offset);
644 target = SUFFIX (get_target_address) (e, target_section,
645 offset, image_target);
646 info = grub_target_to_host (r->r_info);
647 sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
648 ELF_R_SYM (info), image_target);
649
650 addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
d5e2a158 651 grub_target_to_host (r->r_addend) : 0;
0253aeb7 652
bea33583 653 switch (image_target->elf_target)
654 {
655 case EM_386:
0253aeb7
VS
656 switch (ELF_R_TYPE (info))
657 {
658 case R_386_NONE:
659 break;
660
661 case R_386_32:
662 /* This is absolute. */
663 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
664 + addend + sym_addr);
18e76955
VS
665 grub_util_info ("relocating an R_386_32 entry to 0x%"
666 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
667 GRUB_HOST_PRIxLONG_LONG,
495fc8c1
VS
668 (unsigned long long) *target,
669 (unsigned long long) offset);
0253aeb7
VS
670 break;
671
672 case R_386_PC32:
673 /* This is relative. */
674 *target = grub_host_to_target32 (grub_target_to_host32 (*target)
675 + addend + sym_addr
676 - target_section_addr - offset
677 - image_target->vaddr_offset);
18e76955
VS
678 grub_util_info ("relocating an R_386_PC32 entry to 0x%"
679 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
680 GRUB_HOST_PRIxLONG_LONG,
495fc8c1
VS
681 (unsigned long long) *target,
682 (unsigned long long) offset);
0253aeb7
VS
683 break;
684 default:
d6c2782a
VS
685 grub_util_error (_("relocation 0x%x is not implemented yet"),
686 (unsigned int) ELF_R_TYPE (info));
0253aeb7
VS
687 break;
688 }
bea33583 689 break;
495fc8c1 690#ifdef MKIMAGE_ELF64
bea33583 691 case EM_X86_64:
0253aeb7
VS
692 switch (ELF_R_TYPE (info))
693 {
694
695 case R_X86_64_NONE:
696 break;
697
698 case R_X86_64_64:
699 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
700 + addend + sym_addr);
18e76955
VS
701 grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
702 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
703 GRUB_HOST_PRIxLONG_LONG,
495fc8c1
VS
704 (unsigned long long) *target,
705 (unsigned long long) offset);
0253aeb7
VS
706 break;
707
708 case R_X86_64_PC32:
709 {
710 grub_uint32_t *t32 = (grub_uint32_t *) target;
711 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
712 + addend + sym_addr
713 - target_section_addr - offset
714 - image_target->vaddr_offset);
18e76955
VS
715 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
716 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 717 *t32, (unsigned long long) offset);
0253aeb7
VS
718 break;
719 }
720
f4171ebd
VS
721 case R_X86_64_PC64:
722 {
723 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
724 + addend + sym_addr
725 - target_section_addr - offset
726 - image_target->vaddr_offset);
18e76955
VS
727 grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
728 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
729 GRUB_HOST_PRIxLONG_LONG,
f4171ebd
VS
730 (unsigned long long) *target,
731 (unsigned long long) offset);
732 break;
733 }
734
0253aeb7
VS
735 case R_X86_64_32:
736 case R_X86_64_32S:
737 {
738 grub_uint32_t *t32 = (grub_uint32_t *) target;
739 *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
740 + addend + sym_addr);
18e76955
VS
741 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
742 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 743 *t32, (unsigned long long) offset);
0253aeb7
VS
744 break;
745 }
746
747 default:
d6c2782a
VS
748 grub_util_error (_("relocation 0x%x is not implemented yet"),
749 (unsigned int) ELF_R_TYPE (info));
0253aeb7
VS
750 break;
751 }
bea33583 752 break;
753 case EM_IA_64:
754 switch (ELF_R_TYPE (info))
755 {
5452733f
VS
756 case R_IA64_PCREL21B:
757 {
758 grub_uint64_t noff;
d5e2a158 759 grub_ia64_make_trampoline (tr, addend + sym_addr);
5452733f 760 noff = ((char *) tr - (char *) pe_target
a988e7aa 761 - target_section_addr - (offset & ~3)) >> 4;
5452733f
VS
762 tr++;
763 if (noff & ~MASK19)
0b6225bd 764 grub_util_error ("trampoline offset too big (%"
18e76955
VS
765 GRUB_HOST_PRIxLONG_LONG ")",
766 (unsigned long long) noff);
d5e2a158 767 grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
5452733f
VS
768 }
769 break;
770
5452733f
VS
771 case R_IA64_LTOFF22X:
772 case R_IA64_LTOFF22:
2679b724
VS
773 {
774 Elf_Sym *sym;
775
776 sym = (Elf_Sym *) ((char *) e
d5e2a158
VS
777 + grub_target_to_host (symtab_section->sh_offset)
778 + ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
2679b724
VS
779 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
780 sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
781 + sym->st_value
782 - image_target->vaddr_offset));
783 }
784 case R_IA64_LTOFF_FPTR22:
5452733f 785 *gpptr = grub_host_to_target64 (addend + sym_addr);
d5e2a158
VS
786 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
787 (char *) gpptr - (char *) pe_target
788 + image_target->vaddr_offset);
5452733f
VS
789 gpptr++;
790 break;
791
792 case R_IA64_GPREL22:
d5e2a158
VS
793 grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
794 addend + sym_addr);
5452733f
VS
795 break;
796 case R_IA64_PCREL64LSB:
797 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
798 + addend + sym_addr
799 - target_section_addr - offset
800 - image_target->vaddr_offset);
801 break;
802
803 case R_IA64_SEGREL64LSB:
804 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
805 + addend + sym_addr - target_section_addr);
806 break;
807 case R_IA64_DIR64LSB:
808 case R_IA64_FPTR64LSB:
809 *target = grub_host_to_target64 (grub_target_to_host64 (*target)
810 + addend + sym_addr);
811 grub_util_info ("relocating a direct entry to 0x%"
18e76955
VS
812 GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
813 GRUB_HOST_PRIxLONG_LONG,
814 (unsigned long long)
d5e2a158
VS
815 grub_target_to_host64 (*target),
816 (unsigned long long) offset);
5452733f
VS
817 break;
818
819 /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
820 case R_IA64_LDXMOV:
821 break;
822
bea33583 823 default:
d6c2782a
VS
824 grub_util_error (_("relocation 0x%x is not implemented yet"),
825 (unsigned int) ELF_R_TYPE (info));
bea33583 826 break;
827 }
828 break;
15a463d7
LL
829 case EM_AARCH64:
830 {
831 sym_addr += addend;
832 switch (ELF_R_TYPE (info))
833 {
834 case R_AARCH64_ABS64:
835 {
836 *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
837 }
838 break;
839 case R_AARCH64_JUMP26:
840 case R_AARCH64_CALL26:
841 {
15a463d7
LL
842 sym_addr -= offset;
843 sym_addr -= SUFFIX (entry_point);
8c534b85 844 if (!grub_arm_64_check_xxxx26_offset (sym_addr))
57a691b7 845 grub_util_error ("%s", "CALL26 Relocation out of range");
8c534b85
VS
846
847 grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
15a463d7 848 sym_addr);
15a463d7
LL
849 }
850 break;
851 default:
d6c2782a
VS
852 grub_util_error (_("relocation 0x%x is not implemented yet"),
853 (unsigned int) ELF_R_TYPE (info));
15a463d7
LL
854 break;
855 }
856 break;
857 }
5452733f 858#endif
389b31cd
LL
859#if defined(MKIMAGE_ELF32)
860 case EM_ARM:
861 {
862 sym_addr += addend;
863 sym_addr -= SUFFIX (entry_point);
864 switch (ELF_R_TYPE (info))
865 {
866 case R_ARM_ABS32:
867 {
868 grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
869 (int) sym_addr, (int) sym_addr);
870 /* Data will be naturally aligned */
389b31cd
LL
871 sym_addr += 0x400;
872 *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
873 }
874 break;
8c534b85
VS
875 /* Happens when compiled with -march=armv4.
876 Since currently we need at least armv5, keep bx as-is.
877 */
878 case R_ARM_V4BX:
879 break;
389b31cd
LL
880 case R_ARM_THM_CALL:
881 case R_ARM_THM_JUMP24:
8c534b85 882 case R_ARM_THM_JUMP19:
389b31cd 883 {
28af3d86 884 grub_err_t err;
e7c418c5
VS
885 grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
886 (unsigned long) ((char *) target
887 - (char *) e),
888 sym_addr);
8c534b85
VS
889 if (!(sym_addr & 1))
890 {
891 grub_uint32_t tr_addr;
892 grub_int32_t new_offset;
893 tr_addr = (char *) tr - (char *) pe_target
894 - target_section_addr;
895 new_offset = sym_addr - tr_addr - 12;
896
897 if (!grub_arm_jump24_check_offset (new_offset))
898 return grub_util_error ("jump24 relocation out of range");
899
900 tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
901 tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
902 tr += 2;
903 sym_addr = tr_addr | 1;
904 }
389b31cd
LL
905 sym_addr -= offset;
906 /* Thumb instructions can be 16-bit aligned */
8c534b85
VS
907 if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
908 err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
909 else
910 err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
911 sym_addr);
28af3d86
VS
912 if (err)
913 grub_util_error ("%s", grub_errmsg);
389b31cd
LL
914 }
915 break;
8c534b85
VS
916
917 case R_ARM_CALL:
918 case R_ARM_JUMP24:
389b31cd 919 {
28af3d86 920 grub_err_t err;
e7c418c5 921 grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
8c534b85
VS
922 if (sym_addr & 1)
923 {
924 grub_uint32_t tr_addr;
925 grub_int32_t new_offset;
926 tr_addr = (char *) tr - (char *) pe_target
927 - target_section_addr;
928 new_offset = sym_addr - tr_addr - 12;
929
930 /* There is no immediate version of bx, only register one... */
931 tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
932 tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
933 tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
934 tr[3] = grub_host_to_target32 (new_offset | 1);
935 tr += 4;
936 sym_addr = tr_addr;
937 }
389b31cd 938 sym_addr -= offset;
8c534b85
VS
939 err = grub_arm_reloc_jump24 (target,
940 sym_addr);
28af3d86
VS
941 if (err)
942 grub_util_error ("%s", grub_errmsg);
389b31cd
LL
943 }
944 break;
8c534b85 945
389b31cd 946 default:
d6c2782a
VS
947 grub_util_error (_("relocation 0x%x is not implemented yet"),
948 (unsigned int) ELF_R_TYPE (info));
389b31cd
LL
949 break;
950 }
951 break;
952 }
953#endif /* MKIMAGE_ELF32 */
bea33583 954 default:
955 grub_util_error ("unknown architecture type %d",
956 image_target->elf_target);
957 }
0253aeb7
VS
958 }
959 }
960}
961
962/* Add a PE32's fixup entry for a relocation. Return the resulting address
963 after having written to the file OUT. */
964static Elf_Addr
965SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
966 Elf_Addr addr, int flush, Elf_Addr current_address,
ec16e026 967 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
968{
969 struct grub_pe32_fixup_block *b;
970
971 b = &((*cblock)->b);
972
973 /* First, check if it is necessary to write out the current block. */
974 if ((*cblock)->state)
975 {
976 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
977 {
978 grub_uint32_t size;
979
980 if (flush)
981 {
982 /* Add as much padding as necessary to align the address
983 with a section boundary. */
984 Elf_Addr next_address;
985 unsigned padding_size;
495fc8c1 986 size_t cur_index;
0253aeb7
VS
987
988 next_address = current_address + b->block_size;
989 padding_size = ((ALIGN_UP (next_address, image_target->section_align)
990 - next_address)
991 >> 1);
495fc8c1 992 cur_index = ((b->block_size - sizeof (*b)) >> 1);
0253aeb7
VS
993 grub_util_info ("adding %d padding fixup entries", padding_size);
994 while (padding_size--)
995 {
495fc8c1 996 b->entries[cur_index++] = 0;
0253aeb7
VS
997 b->block_size += 2;
998 }
999 }
5452733f 1000 else while (b->block_size & (8 - 1))
0253aeb7
VS
1001 {
1002 /* If not aligned with a 32-bit boundary, add
1003 a padding entry. */
495fc8c1 1004 size_t cur_index;
0253aeb7
VS
1005
1006 grub_util_info ("adding a padding fixup entry");
495fc8c1
VS
1007 cur_index = ((b->block_size - sizeof (*b)) >> 1);
1008 b->entries[cur_index] = 0;
0253aeb7
VS
1009 b->block_size += 2;
1010 }
1011
1012 /* Flush it. */
1013 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
1014 b->block_size, b->page_rva);
1015 size = b->block_size;
1016 current_address += size;
1017 b->page_rva = grub_host_to_target32 (b->page_rva);
1018 b->block_size = grub_host_to_target32 (b->block_size);
1019 (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
1020 memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
1021 *cblock = (*cblock)->next;
1022 }
1023 }
1024
1025 b = &((*cblock)->b);
1026
1027 if (! flush)
1028 {
1029 grub_uint16_t entry;
495fc8c1 1030 size_t cur_index;
0253aeb7
VS
1031
1032 /* If not allocated yet, allocate a block with enough entries. */
1033 if (! (*cblock)->state)
1034 {
1035 (*cblock)->state = 1;
1036
1037 /* The spec does not mention the requirement of a Page RVA.
1038 Here, align the address with a 4K boundary for safety. */
1039 b->page_rva = (addr & ~(0x1000 - 1));
1040 b->block_size = sizeof (*b);
1041 }
1042
1043 /* Sanity check. */
1044 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
1045 grub_util_error ("too many fixup entries");
1046
1047 /* Add a new entry. */
495fc8c1 1048 cur_index = ((b->block_size - sizeof (*b)) >> 1);
0253aeb7 1049 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
495fc8c1 1050 b->entries[cur_index] = grub_host_to_target16 (entry);
0253aeb7
VS
1051 b->block_size += 2;
1052 }
1053
1054 return current_address;
1055}
1056
1057/* Make a .reloc section. */
1058static Elf_Addr
1059SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
1060 Elf_Addr *section_addresses, Elf_Shdr *sections,
1061 Elf_Half section_entsize, Elf_Half num_sections,
5452733f
VS
1062 const char *strtab,
1063 Elf_Addr jumpers, grub_size_t njumpers,
ec16e026 1064 const struct grub_install_image_target_desc *image_target)
0253aeb7 1065{
5452733f 1066 unsigned i;
0253aeb7
VS
1067 Elf_Shdr *s;
1068 struct fixup_block_list *lst, *lst0;
1069 Elf_Addr current_address = 0;
1070
1071 lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000);
1072 memset (lst, 0, sizeof (*lst) + 2 * 0x1000);
1073
5452733f 1074 for (i = 0, s = sections; i < num_sections;
0253aeb7 1075 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
d5e2a158
VS
1076 if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
1077 (grub_target_to_host32 (s->sh_type) == SHT_RELA))
0253aeb7
VS
1078 {
1079 Elf_Rel *r;
1080 Elf_Word rtab_size, r_size, num_rs;
1081 Elf_Off rtab_offset;
1082 Elf_Addr section_address;
1083 Elf_Word j;
1084
1085 grub_util_info ("translating the relocation section %s",
1086 strtab + grub_le_to_cpu32 (s->sh_name));
1087
d5e2a158
VS
1088 rtab_size = grub_target_to_host (s->sh_size);
1089 r_size = grub_target_to_host (s->sh_entsize);
1090 rtab_offset = grub_target_to_host (s->sh_offset);
0253aeb7
VS
1091 num_rs = rtab_size / r_size;
1092
1093 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
1094
1095 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
1096 j < num_rs;
1097 j++, r = (Elf_Rel *) ((char *) r + r_size))
1098 {
1099 Elf_Addr info;
1100 Elf_Addr offset;
1101
d5e2a158
VS
1102 offset = grub_target_to_host (r->r_offset);
1103 info = grub_target_to_host (r->r_info);
0253aeb7
VS
1104
1105 /* Necessary to relocate only absolute addresses. */
bea33583 1106 switch (image_target->elf_target)
0253aeb7 1107 {
bea33583 1108 case EM_386:
0253aeb7
VS
1109 if (ELF_R_TYPE (info) == R_386_32)
1110 {
1111 Elf_Addr addr;
1112
1113 addr = section_address + offset;
18e76955
VS
1114 grub_util_info ("adding a relocation entry for 0x%"
1115 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1116 (unsigned long long) addr);
0253aeb7
VS
1117 current_address
1118 = SUFFIX (add_fixup_entry) (&lst,
1119 GRUB_PE32_REL_BASED_HIGHLOW,
1120 addr, 0, current_address,
1121 image_target);
1122 }
bea33583 1123 break;
1124 case EM_X86_64:
0253aeb7
VS
1125 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
1126 (ELF_R_TYPE (info) == R_X86_64_32S))
1127 {
1128 grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
1129 }
1130 else if (ELF_R_TYPE (info) == R_X86_64_64)
1131 {
1132 Elf_Addr addr;
1133
1134 addr = section_address + offset;
18e76955
VS
1135 grub_util_info ("adding a relocation entry for 0x%"
1136 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1137 (unsigned long long) addr);
0253aeb7
VS
1138 current_address
1139 = SUFFIX (add_fixup_entry) (&lst,
1140 GRUB_PE32_REL_BASED_DIR64,
1141 addr,
1142 0, current_address,
1143 image_target);
1144 }
bea33583 1145 break;
5452733f
VS
1146 case EM_IA_64:
1147 switch (ELF_R_TYPE (info))
1148 {
1149 case R_IA64_PCREL64LSB:
1150 case R_IA64_LDXMOV:
1151 case R_IA64_PCREL21B:
1152 case R_IA64_LTOFF_FPTR22:
1153 case R_IA64_LTOFF22X:
1154 case R_IA64_LTOFF22:
1155 case R_IA64_GPREL22:
1156 case R_IA64_SEGREL64LSB:
1157 break;
1158
1159 case R_IA64_FPTR64LSB:
1160 case R_IA64_DIR64LSB:
1161#if 1
1162 {
1163 Elf_Addr addr;
1164
1165 addr = section_address + offset;
18e76955
VS
1166 grub_util_info ("adding a relocation entry for 0x%"
1167 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1168 (unsigned long long) addr);
5452733f
VS
1169 current_address
1170 = SUFFIX (add_fixup_entry) (&lst,
1171 GRUB_PE32_REL_BASED_DIR64,
1172 addr,
1173 0, current_address,
1174 image_target);
1175 }
1176#endif
1177 break;
1178 default:
d6c2782a
VS
1179 grub_util_error (_("relocation 0x%x is not implemented yet"),
1180 (unsigned int) ELF_R_TYPE (info));
5452733f
VS
1181 break;
1182 }
1183 break;
15a463d7
LL
1184 case EM_AARCH64:
1185 switch (ELF_R_TYPE (info))
1186 {
1187 case R_AARCH64_ABS64:
1188 {
1189 Elf_Addr addr;
1190
1191 addr = section_address + offset;
1192 current_address
1193 = SUFFIX (add_fixup_entry) (&lst,
1194 GRUB_PE32_REL_BASED_DIR64,
1195 addr, 0, current_address,
1196 image_target);
1197 }
1198 break;
1199 /* Relative relocations do not require fixup entries. */
1200 case R_AARCH64_CALL26:
1201 case R_AARCH64_JUMP26:
1202 break;
1203 default:
57a691b7 1204 grub_util_error (_("relocation 0x%x is not implemented yet"),
d6c2782a 1205 (unsigned int) ELF_R_TYPE (info));
15a463d7
LL
1206 break;
1207 }
1208 break;
1209 break;
389b31cd
LL
1210#if defined(MKIMAGE_ELF32)
1211 case EM_ARM:
1212 switch (ELF_R_TYPE (info))
1213 {
8c534b85 1214 case R_ARM_V4BX:
389b31cd
LL
1215 /* Relative relocations do not require fixup entries. */
1216 case R_ARM_JUMP24:
1217 case R_ARM_THM_CALL:
1218 case R_ARM_THM_JUMP19:
1219 case R_ARM_THM_JUMP24:
8c534b85 1220 case R_ARM_CALL:
389b31cd
LL
1221 {
1222 Elf_Addr addr;
1223
1224 addr = section_address + offset;
1225 grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) current_address);
1226 }
1227 break;
1228 /* Create fixup entry for PE/COFF loader */
1229 case R_ARM_ABS32:
854f383c 1230 {
389b31cd
LL
1231 Elf_Addr addr;
1232
1233 addr = section_address + offset;
389b31cd
LL
1234 current_address
1235 = SUFFIX (add_fixup_entry) (&lst,
1236 GRUB_PE32_REL_BASED_HIGHLOW,
1237 addr, 0, current_address,
1238 image_target);
1239 }
1240 break;
1241 default:
57a691b7
VS
1242 grub_util_error (_("relocation 0x%x is not implemented yet"),
1243 (unsigned int) ELF_R_TYPE (info));
389b31cd
LL
1244 break;
1245 }
1246 break;
1247#endif /* defined(MKIMAGE_ELF32) */
bea33583 1248 default:
1249 grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
0253aeb7
VS
1250 }
1251 }
1252 }
1253
5452733f
VS
1254 if (image_target->elf_target == EM_IA_64)
1255 for (i = 0; i < njumpers; i++)
1256 current_address = SUFFIX (add_fixup_entry) (&lst,
1257 GRUB_PE32_REL_BASED_DIR64,
1258 jumpers + 8 * i,
1259 0, current_address,
1260 image_target);
1261
0253aeb7
VS
1262 current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target);
1263
1264 {
1265 grub_uint8_t *ptr;
1266 ptr = *out = xmalloc (current_address);
1267 for (lst = lst0; lst; lst = lst->next)
1268 if (lst->state)
1269 {
1270 memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size));
1271 ptr += grub_target_to_host32 (lst->b.block_size);
1272 }
495fc8c1 1273 assert ((current_address + (grub_uint8_t *) *out) == ptr);
0253aeb7
VS
1274 }
1275
663f6eb1
VS
1276 for (lst = lst0; lst; )
1277 {
1278 struct fixup_block_list *next;
1279 next = lst->next;
1280 free (lst);
1281 lst = next;
1282 }
1283
0253aeb7
VS
1284 return current_address;
1285}
1286
1287/* Determine if this section is a text section. Return false if this
1288 section is not allocated. */
1289static int
ec16e026 1290SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
1291{
1292 if (image_target->id != IMAGE_EFI
1293 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1294 return 0;
962b15b4 1295 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
0253aeb7
VS
1296 == (SHF_EXECINSTR | SHF_ALLOC));
1297}
1298
1299/* Determine if this section is a data section. This assumes that
1300 BSS is also a data section, since the converter initializes BSS
1301 when producing PE32 to avoid a bug in EFI implementations. */
1302static int
ec16e026 1303SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
1304{
1305 if (image_target->id != IMAGE_EFI
1306 && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
1307 return 0;
962b15b4 1308 return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
0253aeb7
VS
1309 == SHF_ALLOC);
1310}
1311
1312/* Return if the ELF header is valid. */
1313static int
ec16e026 1314SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
1315{
1316 if (size < sizeof (*e)
1317 || e->e_ident[EI_MAG0] != ELFMAG0
1318 || e->e_ident[EI_MAG1] != ELFMAG1
1319 || e->e_ident[EI_MAG2] != ELFMAG2
1320 || e->e_ident[EI_MAG3] != ELFMAG3
1321 || e->e_ident[EI_VERSION] != EV_CURRENT
1322 || e->e_ident[EI_CLASS] != ELFCLASSXX
1323 || e->e_version != grub_host_to_target32 (EV_CURRENT))
1324 return 0;
1325
1326 return 1;
1327}
1328
1329/* Locate section addresses by merging code sections and data sections
1330 into .text and .data, respectively. Return the array of section
1331 addresses. */
1332static Elf_Addr *
a0c9d5c6
VS
1333SUFFIX (locate_sections) (const char *kernel_path,
1334 Elf_Shdr *sections, Elf_Half section_entsize,
0253aeb7 1335 Elf_Half num_sections, const char *strtab,
f7676b70
VS
1336 size_t *exec_size, size_t *kernel_sz,
1337 size_t *all_align,
ec16e026 1338 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
1339{
1340 int i;
1341 Elf_Addr current_address;
1342 Elf_Addr *section_addresses;
1343 Elf_Shdr *s;
1344
debaf23f
VS
1345 *all_align = 1;
1346
0253aeb7
VS
1347 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
1348 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
1349
1350 current_address = 0;
1351
debaf23f
VS
1352 for (i = 0, s = sections;
1353 i < num_sections;
1354 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1355 if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
1356 && grub_host_to_target32 (s->sh_addralign) > *all_align)
1357 *all_align = grub_host_to_target32 (s->sh_addralign);
1358
1359
0253aeb7
VS
1360 /* .text */
1361 for (i = 0, s = sections;
1362 i < num_sections;
1363 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1364 if (SUFFIX (is_text_section) (s, image_target))
1365 {
fb53b340 1366 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
0253aeb7 1367 const char *name = strtab + grub_host_to_target32 (s->sh_name);
0253aeb7
VS
1368 if (align)
1369 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1370 align) - image_target->vaddr_offset;
18e76955
VS
1371 grub_util_info ("locating the section %s at 0x%"
1372 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1373 name, (unsigned long long) current_address);
9d742bd4 1374 if (image_target->id != IMAGE_EFI)
a0c9d5c6
VS
1375 {
1376 current_address = grub_host_to_target_addr (s->sh_addr)
1377 - image_target->link_addr;
1378 if (grub_host_to_target_addr (s->sh_addr)
1379 != image_target->link_addr)
f4dab3d1
VS
1380 {
1381 char *msg
496a6b30 1382 = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
f4dab3d1
VS
1383 " instead of 0x%llx: ld.gold bug?"),
1384 kernel_path,
1385 (unsigned long long) grub_host_to_target_addr (s->sh_addr),
1386 (unsigned long long) image_target->link_addr);
1387 grub_util_error ("%s", msg);
1388 }
a0c9d5c6 1389 }
0253aeb7 1390 section_addresses[i] = current_address;
962b15b4 1391 current_address += grub_host_to_target_addr (s->sh_size);
0253aeb7
VS
1392 }
1393
1394 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1395 image_target->section_align)
1396 - image_target->vaddr_offset;
1397 *exec_size = current_address;
1398
1399 /* .data */
1400 for (i = 0, s = sections;
1401 i < num_sections;
1402 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1403 if (SUFFIX (is_data_section) (s, image_target))
1404 {
fb53b340 1405 Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
0253aeb7
VS
1406 const char *name = strtab + grub_host_to_target32 (s->sh_name);
1407
1408 if (align)
1409 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1410 align)
1411 - image_target->vaddr_offset;
1412
18e76955
VS
1413 grub_util_info ("locating the section %s at 0x%"
1414 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1415 name, (unsigned long long) current_address);
9d742bd4
VS
1416 if (image_target->id != IMAGE_EFI)
1417 current_address = grub_host_to_target_addr (s->sh_addr)
1418 - image_target->link_addr;
0253aeb7 1419 section_addresses[i] = current_address;
962b15b4 1420 current_address += grub_host_to_target_addr (s->sh_size);
0253aeb7
VS
1421 }
1422
1423 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1424 image_target->section_align) - image_target->vaddr_offset;
1425 *kernel_sz = current_address;
1426 return section_addresses;
1427}
1428
1429static char *
f7676b70
VS
1430SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
1431 size_t *kernel_sz, size_t *bss_size,
1432 size_t total_module_size, grub_uint64_t *start,
1433 void **reloc_section, size_t *reloc_size,
1434 size_t *align,
ec16e026 1435 const struct grub_install_image_target_desc *image_target)
0253aeb7
VS
1436{
1437 char *kernel_img, *out_img;
1438 const char *strtab;
1439 Elf_Ehdr *e;
1440 Elf_Shdr *sections;
1441 Elf_Addr *section_addresses;
1442 Elf_Addr *section_vaddresses;
1443 int i;
1444 Elf_Shdr *s;
1445 Elf_Half num_sections;
1446 Elf_Off section_offset;
1447 Elf_Half section_entsize;
1448 grub_size_t kernel_size;
8c534b85 1449 grub_size_t ia64jmp_off = 0, tramp_off = 0, ia64_got_off = 0;
5452733f 1450 unsigned ia64jmpnum = 0;
0b6225bd 1451 Elf_Shdr *symtab_section = 0;
5452733f 1452 grub_size_t got = 0;
0253aeb7
VS
1453
1454 *start = 0;
1455
1456 kernel_size = grub_util_get_image_size (kernel_path);
1457 kernel_img = xmalloc (kernel_size);
1458 grub_util_load_image (kernel_path, kernel_img);
1459
1460 e = (Elf_Ehdr *) kernel_img;
1461 if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
1462 grub_util_error ("invalid ELF header");
1463
962b15b4 1464 section_offset = grub_target_to_host (e->e_shoff);
0253aeb7
VS
1465 section_entsize = grub_target_to_host16 (e->e_shentsize);
1466 num_sections = grub_target_to_host16 (e->e_shnum);
1467
1468 if (kernel_size < section_offset + section_entsize * num_sections)
d61386e2 1469 grub_util_error (_("premature end of file %s"), kernel_path);
0253aeb7
VS
1470
1471 sections = (Elf_Shdr *) (kernel_img + section_offset);
1472
1473 /* Relocate sections then symbols in the virtual address space. */
1474 s = (Elf_Shdr *) ((char *) sections
1475 + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
fb53b340 1476 strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
0253aeb7 1477
a0c9d5c6
VS
1478 section_addresses = SUFFIX (locate_sections) (kernel_path,
1479 sections, section_entsize,
0253aeb7 1480 num_sections, strtab,
debaf23f
VS
1481 exec_size, kernel_sz, align,
1482 image_target);
0253aeb7 1483
debaf23f 1484 section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
0253aeb7 1485
debaf23f
VS
1486 for (i = 0; i < num_sections; i++)
1487 section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
0253aeb7 1488
debaf23f
VS
1489 if (image_target->id != IMAGE_EFI)
1490 {
1491 Elf_Addr current_address = *kernel_sz;
0253aeb7 1492
debaf23f
VS
1493 for (i = 0, s = sections;
1494 i < num_sections;
1495 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1496 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1497 {
495fc8c1 1498 Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
debaf23f 1499 const char *name = strtab + grub_host_to_target32 (s->sh_name);
0253aeb7 1500
495fc8c1 1501 if (sec_align)
debaf23f 1502 current_address = ALIGN_UP (current_address
495fc8c1
VS
1503 + image_target->vaddr_offset,
1504 sec_align)
debaf23f 1505 - image_target->vaddr_offset;
0253aeb7 1506
18e76955
VS
1507 grub_util_info ("locating the section %s at 0x%"
1508 GRUB_HOST_PRIxLONG_LONG,
495fc8c1 1509 name, (unsigned long long) current_address);
9d742bd4
VS
1510 if (image_target->id != IMAGE_EFI)
1511 current_address = grub_host_to_target_addr (s->sh_addr)
1512 - image_target->link_addr;
1513
debaf23f
VS
1514 section_vaddresses[i] = current_address
1515 + image_target->vaddr_offset;
1516 current_address += grub_host_to_target_addr (s->sh_size);
1517 }
1518 current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
1519 image_target->section_align)
1520 - image_target->vaddr_offset;
1521 *bss_size = current_address - *kernel_sz;
1522 }
1523 else
1524 *bss_size = 0;
0253aeb7 1525
e5ed2f69
VS
1526 if (image_target->id == IMAGE_SPARC64_AOUT
1527 || image_target->id == IMAGE_SPARC64_RAW
1528 || image_target->id == IMAGE_SPARC64_CDCORE)
1529 *kernel_sz = ALIGN_UP (*kernel_sz, image_target->mod_align);
1530
debaf23f
VS
1531 if (image_target->id == IMAGE_EFI)
1532 {
0253aeb7
VS
1533 symtab_section = NULL;
1534 for (i = 0, s = sections;
1535 i < num_sections;
1536 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1537 if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
1538 {
1539 symtab_section = s;
1540 break;
1541 }
7aaed664
AB
1542 if (! symtab_section)
1543 grub_util_error ("%s", _("no symbol table"));
0253aeb7 1544
8c534b85
VS
1545#ifdef MKIMAGE_ELF32
1546 if (image_target->elf_target == EM_ARM)
1547 {
1548 grub_size_t tramp;
1549
1550 *kernel_sz = ALIGN_UP (*kernel_sz, 16);
1551
1552 tramp = arm_get_trampoline_size (e, sections, section_entsize,
1553 num_sections, image_target);
1554
1555 tramp_off = *kernel_sz;
1556 *kernel_sz += ALIGN_UP (tramp, 16);
1557 }
1558#endif
1559
5452733f
VS
1560#ifdef MKIMAGE_ELF64
1561 if (image_target->elf_target == EM_IA_64)
1562 {
1563 grub_size_t tramp;
1564
1565 *kernel_sz = ALIGN_UP (*kernel_sz, 16);
1566
1567 grub_ia64_dl_get_tramp_got_size (e, &tramp, &got);
5452733f 1568
8c534b85 1569 tramp_off = *kernel_sz;
5452733f
VS
1570 *kernel_sz += ALIGN_UP (tramp, 16);
1571
1572 ia64jmp_off = *kernel_sz;
1573 ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
1574 image_target);
1575 *kernel_sz += 16 * ia64jmpnum;
1576
1577 ia64_got_off = *kernel_sz;
49060520 1578 *kernel_sz += ALIGN_UP (got, 16);
5452733f
VS
1579 }
1580#endif
1581
5452733f
VS
1582 }
1583 else
1584 {
1585 *reloc_size = 0;
1586 *reloc_section = NULL;
1587 }
1588
1589 out_img = xmalloc (*kernel_sz + total_module_size);
0253aeb7 1590
5452733f
VS
1591 if (image_target->id == IMAGE_EFI)
1592 {
0253aeb7
VS
1593 *start = SUFFIX (relocate_symbols) (e, sections, symtab_section,
1594 section_vaddresses, section_entsize,
5452733f
VS
1595 num_sections,
1596 (char *) out_img + ia64jmp_off,
1597 ia64jmp_off
1598 + image_target->vaddr_offset,
1599 image_target);
0253aeb7
VS
1600 if (*start == 0)
1601 grub_util_error ("start symbol is not defined");
15a463d7 1602
389b31cd
LL
1603 SUFFIX (entry_point) = (Elf_Addr) *start;
1604
0253aeb7 1605 /* Resolve addresses in the virtual address space. */
5452733f
VS
1606 SUFFIX (relocate_addresses) (e, sections, section_addresses,
1607 section_entsize,
1608 num_sections, strtab,
8c534b85 1609 out_img, tramp_off, ia64_got_off,
5452733f 1610 image_target);
15a463d7 1611
0253aeb7
VS
1612 *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
1613 section_vaddresses, sections,
1614 section_entsize, num_sections,
5452733f
VS
1615 strtab, ia64jmp_off
1616 + image_target->vaddr_offset,
a846dd4b 1617 2 * ia64jmpnum + (got / 8),
5452733f 1618 image_target);
0253aeb7
VS
1619 }
1620
0253aeb7
VS
1621 for (i = 0, s = sections;
1622 i < num_sections;
1623 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
1624 if (SUFFIX (is_data_section) (s, image_target)
1625 || SUFFIX (is_text_section) (s, image_target))
1626 {
1627 if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
1628 memset (out_img + section_addresses[i], 0,
962b15b4 1629 grub_host_to_target_addr (s->sh_size));
0253aeb7
VS
1630 else
1631 memcpy (out_img + section_addresses[i],
962b15b4
VS
1632 kernel_img + grub_host_to_target_addr (s->sh_offset),
1633 grub_host_to_target_addr (s->sh_size));
0253aeb7
VS
1634 }
1635 free (kernel_img);
1636
663f6eb1
VS
1637 free (section_vaddresses);
1638 free (section_addresses);
1639
0253aeb7
VS
1640 return out_img;
1641}
1642
1643
1644#undef SUFFIX
1645#undef ELFCLASSXX
1646#undef Elf_Ehdr
1647#undef Elf_Phdr
9612ebc0 1648#undef Elf_Nhdr
0253aeb7
VS
1649#undef Elf_Shdr
1650#undef Elf_Addr
1651#undef Elf_Sym
1652#undef Elf_Off
1653#undef Elf_Rela
1654#undef Elf_Rel
1655#undef ELF_R_TYPE
1656#undef ELF_R_SYM
c36e5cd1
VS
1657#undef Elf_Word
1658#undef Elf_Half
1659#undef Elf_Section
1660#undef ELF_ST_TYPE
9612ebc0 1661#undef XEN_NOTE_SIZE