Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / common / boot / grub2 / util / i386 / efi / grub-mkimage.c
blobeac119b470acdebc43947bf0fe77a419ac7cda57
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2004,2005,2006,2007 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <getopt.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <grub/elf.h>
28 #include <grub/util/misc.h>
29 #include <grub/util/resolve.h>
30 #include <grub/kernel.h>
31 #include <grub/efi/pe32.h>
32 #include <grub/machine/kernel.h>
34 #if GRUB_TARGET_SIZEOF_VOID_P == 4
36 typedef Elf32_Word Elf_Word;
37 typedef Elf32_Addr Elf_Addr;
38 typedef Elf32_Ehdr Elf_Ehdr;
39 typedef Elf32_Shdr Elf_Shdr;
40 typedef Elf32_Sym Elf_Sym;
41 typedef Elf32_Half Elf_Half;
42 typedef Elf32_Off Elf_Off;
43 typedef Elf32_Section Elf_Section;
44 typedef Elf32_Rel Elf_Rel;
45 typedef Elf32_Rela Elf_Rela;
47 #define ELF_R_SYM ELF32_R_SYM
48 #define ELF_R_TYPE ELF32_R_TYPE
49 #define ELF_R_INFO ELF32_R_INFO
51 #define grub_le_to_cpu grub_le_to_cpu32
53 #elif GRUB_TARGET_SIZEOF_VOID_P == 8
55 typedef Elf64_Word Elf_Word;
56 typedef Elf64_Addr Elf_Addr;
57 typedef Elf64_Ehdr Elf_Ehdr;
58 typedef Elf64_Shdr Elf_Shdr;
59 typedef Elf64_Sym Elf_Sym;
60 typedef Elf64_Half Elf_Half;
61 typedef Elf64_Off Elf_Off;
62 typedef Elf64_Section Elf_Section;
63 typedef Elf64_Rel Elf_Rel;
64 typedef Elf64_Rela Elf_Rela;
66 #define ELF_R_SYM ELF64_R_SYM
67 #define ELF_R_TYPE ELF64_R_TYPE
68 #define ELF_R_INFO ELF64_R_INFO
70 #define grub_le_to_cpu grub_le_to_cpu64
72 #endif
74 static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
76 static inline Elf_Addr
77 align_address (Elf_Addr addr, unsigned alignment)
79 return (addr + alignment - 1) & ~(alignment - 1);
82 static inline Elf_Addr
83 align_pe32_section (Elf_Addr addr)
85 return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT);
88 /* Read the whole kernel image. Return the pointer to a read image,
89 and store the size in bytes in *SIZE. */
90 static char *
91 read_kernel_module (const char *dir, char *prefix, size_t *size)
93 char *kernel_image;
94 char *kernel_path;
96 kernel_path = grub_util_get_path (dir, "kernel.mod");
97 *size = grub_util_get_image_size (kernel_path);
98 kernel_image = grub_util_read_image (kernel_path);
99 free (kernel_path);
101 if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
102 grub_util_error ("prefix too long");
104 strcpy (kernel_image + sizeof (Elf_Ehdr) + GRUB_KERNEL_MACHINE_PREFIX, prefix);
106 return kernel_image;
109 /* Return if the ELF header is valid. */
110 static int
111 check_elf_header (Elf_Ehdr *e, size_t size)
113 if (size < sizeof (*e)
114 || e->e_ident[EI_MAG0] != ELFMAG0
115 || e->e_ident[EI_MAG1] != ELFMAG1
116 || e->e_ident[EI_MAG2] != ELFMAG2
117 || e->e_ident[EI_MAG3] != ELFMAG3
118 || e->e_ident[EI_VERSION] != EV_CURRENT
119 || e->e_version != grub_cpu_to_le32 (EV_CURRENT)
120 || ((e->e_ident[EI_CLASS] != ELFCLASS32) &&
121 (e->e_ident[EI_CLASS] != ELFCLASS64))
122 || e->e_ident[EI_DATA] != ELFDATA2LSB
123 || ((e->e_machine != grub_cpu_to_le16 (EM_386)) &&
124 (e->e_machine != grub_cpu_to_le16 (EM_X86_64))))
125 return 0;
127 return 1;
130 /* Return the starting address right after the header,
131 aligned by the section alignment. Allocate 4 section tables for
132 .text, .data, .reloc, and mods. */
133 static Elf_Addr
134 get_starting_section_address (void)
136 return align_pe32_section (sizeof (struct grub_pe32_header)
137 + 4 * sizeof (struct grub_pe32_section_table));
140 /* Determine if this section is a text section. Return false if this
141 section is not allocated. */
142 static int
143 is_text_section (Elf_Shdr *s)
145 return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
146 == grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
149 /* Determine if this section is a data section. This assumes that
150 BSS is also a data section, since the converter initializes BSS
151 when producing PE32 to avoid a bug in EFI implementations. */
152 static int
153 is_data_section (Elf_Shdr *s)
155 return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
156 && ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
159 /* Locate section addresses by merging code sections and data sections
160 into .text and .data, respectively. Return the array of section
161 addresses. */
162 static Elf_Addr *
163 locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
164 Elf_Half num_sections, const char *strtab)
166 int i;
167 Elf_Addr current_address;
168 Elf_Addr *section_addresses;
169 Elf_Shdr *s;
171 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
172 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
174 current_address = get_starting_section_address ();
176 /* .text */
177 for (i = 0, s = sections;
178 i < num_sections;
179 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
180 if (is_text_section (s))
182 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
183 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
185 if (align)
186 current_address = align_address (current_address, align);
188 grub_util_info ("locating the section %s at 0x%x",
189 name, current_address);
190 section_addresses[i] = current_address;
191 current_address += grub_le_to_cpu32 (s->sh_size);
194 current_address = align_pe32_section (current_address);
196 /* .data */
197 for (i = 0, s = sections;
198 i < num_sections;
199 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
200 if (is_data_section (s))
202 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
203 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
205 if (align)
206 current_address = align_address (current_address, align);
208 grub_util_info ("locating the section %s at 0x%x",
209 name, current_address);
210 section_addresses[i] = current_address;
211 current_address += grub_le_to_cpu32 (s->sh_size);
214 return section_addresses;
217 /* Return the symbol table section, if any. */
218 static Elf_Shdr *
219 find_symtab_section (Elf_Shdr *sections,
220 Elf_Half section_entsize, Elf_Half num_sections)
222 int i;
223 Elf_Shdr *s;
225 for (i = 0, s = sections;
226 i < num_sections;
227 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
228 if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
229 return s;
231 return 0;
234 /* Return the address of the string table. */
235 static const char *
236 find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
238 Elf_Shdr *s;
239 char *strtab;
241 s = (Elf_Shdr *) ((char *) sections
242 + grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
243 strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
244 return strtab;
247 /* Relocate symbols; note that this function overwrites the symbol table.
248 Return the address of a start symbol. */
249 static Elf_Addr
250 relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
251 Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
252 Elf_Half section_entsize, Elf_Half num_sections)
254 Elf_Word symtab_size, sym_size, num_syms;
255 Elf_Off symtab_offset;
256 Elf_Addr start_address = 0;
257 Elf_Sym *sym;
258 Elf_Word i;
259 Elf_Shdr *strtab_section;
260 const char *strtab;
262 strtab_section
263 = (Elf_Shdr *) ((char *) sections
264 + (grub_le_to_cpu32 (symtab_section->sh_link)
265 * section_entsize));
266 strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
268 symtab_size = grub_le_to_cpu32 (symtab_section->sh_size);
269 sym_size = grub_le_to_cpu32 (symtab_section->sh_entsize);
270 symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
271 num_syms = symtab_size / sym_size;
273 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
274 i < num_syms;
275 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
277 Elf_Section index;
278 const char *name;
280 name = strtab + grub_le_to_cpu32 (sym->st_name);
282 index = grub_le_to_cpu16 (sym->st_shndx);
283 if (index == STN_ABS)
285 continue;
287 else if ((index == STN_UNDEF))
289 if (sym->st_name)
290 grub_util_error ("undefined symbol %s", name);
291 else
292 continue;
294 else if (index >= num_sections)
295 grub_util_error ("section %d does not exist", index);
297 sym->st_value = (grub_le_to_cpu32 (sym->st_value)
298 + section_addresses[index]);
299 grub_util_info ("locating %s at 0x%x", name, sym->st_value);
301 if (! start_address)
302 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
303 start_address = sym->st_value;
306 return start_address;
309 /* Return the address of a symbol at the index I in the section S. */
310 static Elf_Addr
311 get_symbol_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i)
313 Elf_Sym *sym;
315 sym = (Elf_Sym *) ((char *) e
316 + grub_le_to_cpu32 (s->sh_offset)
317 + i * grub_le_to_cpu32 (s->sh_entsize));
318 return sym->st_value;
321 /* Return the address of a modified value. */
322 static Elf_Addr *
323 get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
325 return (Elf_Addr *) ((char *) e + grub_le_to_cpu32 (s->sh_offset) + offset);
328 /* Deal with relocation information. This function relocates addresses
329 within the virtual address space starting from 0. So only relative
330 addresses can be fully resolved. Absolute addresses must be relocated
331 again by a PE32 relocator when loaded. */
332 static void
333 relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
334 Elf_Addr *section_addresses,
335 Elf_Half section_entsize, Elf_Half num_sections,
336 const char *strtab)
338 Elf_Half i;
339 Elf_Shdr *s;
341 for (i = 0, s = sections;
342 i < num_sections;
343 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
344 if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
345 (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
347 Elf_Rela *r;
348 Elf_Word rtab_size, r_size, num_rs;
349 Elf_Off rtab_offset;
350 Elf_Shdr *symtab_section;
351 Elf_Word target_section_index;
352 Elf_Addr target_section_addr;
353 Elf_Shdr *target_section;
354 Elf_Word j;
356 symtab_section = (Elf_Shdr *) ((char *) sections
357 + (grub_le_to_cpu32 (s->sh_link)
358 * section_entsize));
359 target_section_index = grub_le_to_cpu32 (s->sh_info);
360 target_section_addr = section_addresses[target_section_index];
361 target_section = (Elf_Shdr *) ((char *) sections
362 + (target_section_index
363 * section_entsize));
365 grub_util_info ("dealing with the relocation section %s for %s",
366 strtab + grub_le_to_cpu32 (s->sh_name),
367 strtab + grub_le_to_cpu32 (target_section->sh_name));
369 rtab_size = grub_le_to_cpu32 (s->sh_size);
370 r_size = grub_le_to_cpu32 (s->sh_entsize);
371 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
372 num_rs = rtab_size / r_size;
374 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
375 j < num_rs;
376 j++, r = (Elf_Rela *) ((char *) r + r_size))
378 Elf_Addr info;
379 Elf_Addr offset;
380 Elf_Addr sym_addr;
381 Elf_Addr *target, *value;
383 offset = grub_le_to_cpu (r->r_offset);
384 target = get_target_address (e, target_section, offset);
385 info = grub_le_to_cpu (r->r_info);
386 sym_addr = get_symbol_address (e, symtab_section,
387 ELF_R_SYM (info));
389 value = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
390 (Elf_Addr *) &r->r_addend : target;
392 switch (ELF_R_TYPE (info))
394 #if GRUB_TARGET_SIZEOF_VOID_P == 4
395 case R_386_NONE:
396 break;
398 case R_386_32:
399 /* This is absolute. */
400 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
401 + sym_addr);
402 grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
403 *target, offset);
404 break;
406 case R_386_PC32:
407 /* This is relative. */
408 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
409 + sym_addr
410 - target_section_addr - offset);
411 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
412 *target, offset);
413 break;
415 #else
417 case R_X86_64_NONE:
418 break;
420 case R_X86_64_64:
421 *target = grub_cpu_to_le64 (grub_le_to_cpu64 (*value) + sym_addr);
422 grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
423 *target, offset);
424 break;
426 case R_X86_64_PC32:
428 grub_uint32_t *t32 = (grub_uint32_t *) target;
429 *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
430 + sym_addr
431 - target_section_addr - offset);
432 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
433 *t32, offset);
434 break;
437 case R_X86_64_32:
438 case R_X86_64_32S:
440 grub_uint32_t *t32 = (grub_uint32_t *) target;
441 *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
442 + sym_addr);
443 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
444 *t32, offset);
445 break;
448 #endif
449 default:
450 grub_util_error ("unknown relocation type %d",
451 ELF_R_TYPE (info));
452 break;
458 void
459 write_padding (FILE *out, size_t size)
461 size_t i;
463 for (i = 0; i < size; i++)
464 if (fputc (0, out) == EOF)
465 grub_util_error ("padding failed");
468 /* Add a PE32's fixup entry for a relocation. Return the resulting address
469 after having written to the file OUT. */
470 Elf_Addr
471 add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
472 Elf_Addr addr, int flush, Elf_Addr current_address,
473 FILE *out)
475 struct grub_pe32_fixup_block *b = *block;
477 /* First, check if it is necessary to write out the current block. */
478 if (b)
480 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
482 grub_uint32_t size;
484 if (flush)
486 /* Add as much padding as necessary to align the address
487 with a section boundary. */
488 Elf_Addr next_address;
489 unsigned padding_size;
490 size_t index;
492 next_address = current_address + b->block_size;
493 padding_size = ((align_pe32_section (next_address)
494 - next_address)
495 >> 1);
496 index = ((b->block_size - sizeof (*b)) >> 1);
497 grub_util_info ("adding %d padding fixup entries", padding_size);
498 while (padding_size--)
500 b->entries[index++] = 0;
501 b->block_size += 2;
504 else if (b->block_size & (8 - 1))
506 /* If not aligned with a 32-bit boundary, add
507 a padding entry. */
508 size_t index;
510 grub_util_info ("adding a padding fixup entry");
511 index = ((b->block_size - sizeof (*b)) >> 1);
512 b->entries[index] = 0;
513 b->block_size += 2;
516 /* Flush it. */
517 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
518 b->block_size, b->page_rva);
519 size = b->block_size;
520 current_address += size;
521 b->page_rva = grub_cpu_to_le32 (b->page_rva);
522 b->block_size = grub_cpu_to_le32 (b->block_size);
523 if (fwrite (b, size, 1, out) != 1)
524 grub_util_error ("write failed");
525 free (b);
526 *block = b = 0;
530 if (! flush)
532 grub_uint16_t entry;
533 size_t index;
535 /* If not allocated yet, allocate a block with enough entries. */
536 if (! b)
538 *block = b = xmalloc (sizeof (*b) + 2 * 0x1000);
540 /* The spec does not mention the requirement of a Page RVA.
541 Here, align the address with a 4K boundary for safety. */
542 b->page_rva = (addr & ~(0x1000 - 1));
543 b->block_size = sizeof (*b);
546 /* Sanity check. */
547 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
548 grub_util_error ("too many fixup entries");
550 /* Add a new entry. */
551 index = ((b->block_size - sizeof (*b)) >> 1);
552 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
553 b->entries[index] = grub_cpu_to_le16 (entry);
554 b->block_size += 2;
557 return current_address;
560 /* Write out zeros to make space for the header. */
561 static Elf_Addr
562 make_header_space (FILE *out)
564 Elf_Addr addr;
566 addr = get_starting_section_address ();
567 write_padding (out, addr);
569 return addr;
572 /* Write text sections. */
573 static Elf_Addr
574 write_text_sections (FILE *out, Elf_Addr current_address,
575 Elf_Ehdr *e, Elf_Shdr *sections,
576 Elf_Half section_entsize, Elf_Half num_sections,
577 const char *strtab)
579 Elf_Half i;
580 Elf_Shdr *s;
581 Elf_Addr addr;
583 for (i = 0, s = sections;
584 i < num_sections;
585 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
586 if (is_text_section (s))
588 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
589 Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
590 Elf_Word size = grub_le_to_cpu32 (s->sh_size);
591 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
593 if (align)
595 addr = align_address (current_address, align);
596 if (current_address != addr)
598 grub_util_info ("padding %d bytes for the ELF section alignment",
599 addr - current_address);
600 write_padding (out, addr - current_address);
601 current_address = addr;
605 grub_util_info ("writing the text section %s at 0x%x",
606 name, current_address);
608 if (fwrite ((char *) e + offset, size, 1, out) != 1)
609 grub_util_error ("write failed");
611 current_address += size;
614 addr = align_pe32_section (current_address);
615 if (addr != current_address)
617 grub_util_info ("padding %d bytes for the PE32 section alignment",
618 addr - current_address);
619 write_padding (out, addr - current_address);
622 return addr;
625 /* Write data sections. */
626 static Elf_Addr
627 write_data_sections (FILE *out, Elf_Addr current_address,
628 Elf_Ehdr *e, Elf_Shdr *sections,
629 Elf_Half section_entsize, Elf_Half num_sections,
630 const char *strtab)
632 Elf_Half i;
633 Elf_Shdr *s;
634 Elf_Addr addr;
636 for (i = 0, s = sections;
637 i < num_sections;
638 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
639 if (is_data_section (s))
641 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
642 Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
643 Elf_Word size = grub_le_to_cpu32 (s->sh_size);
644 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
646 if (align)
648 addr = align_address (current_address, align);
649 if (current_address != addr)
651 grub_util_info ("padding %d bytes for the ELF section alignment",
652 addr - current_address);
653 write_padding (out, addr - current_address);
654 current_address = addr;
658 grub_util_info ("writing the data section %s at 0x%x",
659 name, current_address);
661 if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS))
662 write_padding (out, size);
663 else
664 if (fwrite ((char *) e + offset, size, 1, out) != 1)
665 grub_util_error ("write failed");
667 current_address += size;
670 addr = align_pe32_section (current_address);
671 if (addr != current_address)
673 grub_util_info ("padding %d bytes for the PE32 section alignment",
674 addr - current_address);
675 write_padding (out, addr - current_address);
678 return addr;
681 /* Write modules. */
682 static Elf_Addr
683 make_mods_section (FILE *out, Elf_Addr current_address,
684 const char *dir, char *mods[])
686 struct grub_util_path_list *path_list;
687 grub_size_t total_module_size;
688 struct grub_util_path_list *p;
689 struct grub_module_info modinfo;
690 Elf_Addr addr;
692 path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
694 total_module_size = sizeof (struct grub_module_info);
695 for (p = path_list; p; p = p->next)
697 total_module_size += (grub_util_get_image_size (p->name)
698 + sizeof (struct grub_module_header));
701 grub_util_info ("the total module size is 0x%x", total_module_size);
703 modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC);
704 modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo));
705 modinfo.size = grub_cpu_to_le32 (total_module_size);
707 if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1)
708 grub_util_error ("write failed");
710 for (p = path_list; p; p = p->next)
712 struct grub_module_header header;
713 size_t mod_size;
714 char *mod_image;
716 grub_util_info ("adding module %s", p->name);
718 mod_size = grub_util_get_image_size (p->name);
719 header.type = grub_cpu_to_le32 (OBJ_TYPE_ELF);
720 header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
722 mod_image = grub_util_read_image (p->name);
724 if (fwrite (&header, sizeof (header), 1, out) != 1
725 || fwrite (mod_image, mod_size, 1, out) != 1)
726 grub_util_error ("write failed");
728 free (mod_image);
731 for (p = path_list; p; )
733 struct grub_util_path_list *q;
735 q = p->next;
736 free (p);
737 p = q;
740 current_address += total_module_size;
742 addr = align_pe32_section (current_address);
743 if (addr != current_address)
745 grub_util_info ("padding %d bytes for the PE32 section alignment",
746 addr - current_address);
747 write_padding (out, addr - current_address);
750 return addr;
753 /* Make a .reloc section. */
754 static Elf_Addr
755 make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
756 Elf_Addr *section_addresses, Elf_Shdr *sections,
757 Elf_Half section_entsize, Elf_Half num_sections,
758 const char *strtab)
760 Elf_Half i;
761 Elf_Shdr *s;
762 struct grub_pe32_fixup_block *fixup_block = 0;
764 for (i = 0, s = sections;
765 i < num_sections;
766 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
767 if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
768 (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
770 Elf_Rel *r;
771 Elf_Word rtab_size, r_size, num_rs;
772 Elf_Off rtab_offset;
773 Elf_Addr section_address;
774 Elf_Word j;
776 grub_util_info ("translating the relocation section %s",
777 strtab + grub_le_to_cpu32 (s->sh_name));
779 rtab_size = grub_le_to_cpu32 (s->sh_size);
780 r_size = grub_le_to_cpu32 (s->sh_entsize);
781 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
782 num_rs = rtab_size / r_size;
784 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
786 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
787 j < num_rs;
788 j++, r = (Elf_Rel *) ((char *) r + r_size))
790 Elf_Addr info;
791 Elf_Addr offset;
793 offset = grub_le_to_cpu32 (r->r_offset);
794 info = grub_le_to_cpu32 (r->r_info);
796 /* Necessary to relocate only absolute addresses. */
797 #if GRUB_TARGET_SIZEOF_VOID_P == 4
798 if (ELF_R_TYPE (info) == R_386_32)
800 Elf_Addr addr;
802 addr = section_address + offset;
803 grub_util_info ("adding a relocation entry for 0x%x", addr);
804 current_address = add_fixup_entry (&fixup_block,
805 GRUB_PE32_REL_BASED_HIGHLOW,
806 addr, 0, current_address,
807 out);
809 #else
810 if ((ELF_R_TYPE (info) == R_X86_64_64) ||
811 (ELF_R_TYPE (info) == R_X86_64_32) ||
812 (ELF_R_TYPE (info) == R_X86_64_32S))
814 Elf_Addr addr;
816 addr = section_address + offset;
817 grub_util_info ("adding a relocation entry for 0x%llx", addr);
818 current_address = add_fixup_entry (&fixup_block,
819 GRUB_PE32_REL_BASED_HIGHLOW,
820 addr, 0, current_address,
821 out);
823 #endif
827 current_address = add_fixup_entry (&fixup_block, 0, 0, 1,
828 current_address, out);
830 return current_address;
833 /* Create the header. */
834 static void
835 make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
836 Elf_Addr mods_address, Elf_Addr reloc_address,
837 Elf_Addr end_address, Elf_Addr start_address)
839 struct grub_pe32_header header;
840 struct grub_pe32_coff_header *c;
841 struct grub_pe32_optional_header *o;
842 struct grub_pe32_section_table text_section, data_section;
843 struct grub_pe32_section_table mods_section, reloc_section;
845 /* The magic. */
846 memset (&header, 0, sizeof (header));
847 memcpy (header.msdos_stub, stub, sizeof (header.msdos_stub));
848 memcpy (header.signature, "PE\0\0", sizeof (header.signature));
850 /* The COFF file header. */
851 c = &header.coff_header;
852 #if GRUB_TARGET_SIZEOF_VOID_P == 4
853 c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
854 #else
855 c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64);
856 #endif
858 c->num_sections = grub_cpu_to_le16 (4);
859 c->time = grub_cpu_to_le32 (time (0));
860 c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
861 c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
862 | GRUB_PE32_LINE_NUMS_STRIPPED
863 #if GRUB_TARGET_SIZEOF_VOID_P == 4
864 | GRUB_PE32_32BIT_MACHINE
865 #endif
866 | GRUB_PE32_LOCAL_SYMS_STRIPPED
867 | GRUB_PE32_DEBUG_STRIPPED);
869 /* The PE Optional header. */
870 o = &header.optional_header;
871 o->magic = grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC);
872 o->code_size = grub_cpu_to_le32 (data_address - text_address);
873 o->data_size = grub_cpu_to_le32 (reloc_address - data_address);
874 o->bss_size = 0;
875 o->entry_addr = grub_cpu_to_le32 (start_address);
876 o->code_base = grub_cpu_to_le32 (text_address);
877 #if GRUB_TARGET_SIZEOF_VOID_P == 4
878 o->data_base = grub_cpu_to_le32 (data_address);
879 #endif
880 o->image_base = 0;
881 o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
882 o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
883 o->image_size = grub_cpu_to_le32 (end_address);
884 o->header_size = grub_cpu_to_le32 (text_address);
885 o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
887 /* Do these really matter? */
888 o->stack_reserve_size = grub_cpu_to_le32 (0x10000);
889 o->stack_commit_size = grub_cpu_to_le32 (0x10000);
890 o->heap_reserve_size = grub_cpu_to_le32 (0x10000);
891 o->heap_commit_size = grub_cpu_to_le32 (0x10000);
893 o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
895 o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address);
896 o->base_relocation_table.size = grub_cpu_to_le32 (end_address
897 - reloc_address);
899 /* The sections. */
900 memset (&text_section, 0, sizeof (text_section));
901 strcpy (text_section.name, ".text");
902 text_section.virtual_size = grub_cpu_to_le32 (data_address - text_address);
903 text_section.virtual_address = grub_cpu_to_le32 (text_address);
904 text_section.raw_data_size = grub_cpu_to_le32 (data_address - text_address);
905 text_section.raw_data_offset = grub_cpu_to_le32 (text_address);
906 text_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
907 | GRUB_PE32_SCN_MEM_EXECUTE
908 | GRUB_PE32_SCN_MEM_READ);
910 memset (&data_section, 0, sizeof (data_section));
911 strcpy (data_section.name, ".data");
912 data_section.virtual_size = grub_cpu_to_le32 (mods_address - data_address);
913 data_section.virtual_address = grub_cpu_to_le32 (data_address);
914 data_section.raw_data_size = grub_cpu_to_le32 (mods_address - data_address);
915 data_section.raw_data_offset = grub_cpu_to_le32 (data_address);
916 data_section.characteristics
917 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
918 | GRUB_PE32_SCN_MEM_READ
919 | GRUB_PE32_SCN_MEM_WRITE);
921 memset (&mods_section, 0, sizeof (mods_section));
922 strcpy (mods_section.name, "mods");
923 mods_section.virtual_size = grub_cpu_to_le32 (reloc_address - mods_address);
924 mods_section.virtual_address = grub_cpu_to_le32 (mods_address);
925 mods_section.raw_data_size = grub_cpu_to_le32 (reloc_address - mods_address);
926 mods_section.raw_data_offset = grub_cpu_to_le32 (mods_address);
927 mods_section.characteristics
928 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
929 | GRUB_PE32_SCN_MEM_READ
930 | GRUB_PE32_SCN_MEM_WRITE);
932 memset (&reloc_section, 0, sizeof (reloc_section));
933 strcpy (reloc_section.name, ".reloc");
934 reloc_section.virtual_size = grub_cpu_to_le32 (end_address - reloc_address);
935 reloc_section.virtual_address = grub_cpu_to_le32 (reloc_address);
936 reloc_section.raw_data_size = grub_cpu_to_le32 (end_address - reloc_address);
937 reloc_section.raw_data_offset = grub_cpu_to_le32 (reloc_address);
938 reloc_section.characteristics
939 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
940 | GRUB_PE32_SCN_MEM_DISCARDABLE
941 | GRUB_PE32_SCN_MEM_READ);
943 /* Write them out. */
944 if (fseeko (out, 0, SEEK_SET) < 0)
945 grub_util_error ("seek failed");
947 if (fwrite (&header, sizeof (header), 1, out) != 1
948 || fwrite (&text_section, sizeof (text_section), 1, out) != 1
949 || fwrite (&data_section, sizeof (data_section), 1, out) != 1
950 || fwrite (&mods_section, sizeof (mods_section), 1, out) != 1
951 || fwrite (&reloc_section, sizeof (reloc_section), 1, out) != 1)
952 grub_util_error ("write failed");
955 /* Convert an ELF relocatable object into an EFI Application (PE32). */
956 void
957 convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
959 char *kernel_image;
960 size_t kernel_size;
961 const char *strtab;
962 Elf_Ehdr *e;
963 Elf_Shdr *sections;
964 Elf_Off section_offset;
965 Elf_Half section_entsize;
966 Elf_Half num_sections;
967 Elf_Addr *section_addresses;
968 Elf_Shdr *symtab_section;
969 Elf_Addr start_address;
970 Elf_Addr text_address, data_address, reloc_address, mods_address;
971 Elf_Addr end_address;
973 /* Get the kernel image and check the format. */
974 kernel_image = read_kernel_module (dir, prefix, &kernel_size);
975 e = (Elf_Ehdr *) kernel_image;
976 if (! check_elf_header (e, kernel_size))
977 grub_util_error ("invalid ELF header");
979 section_offset = grub_cpu_to_le32 (e->e_shoff);
980 section_entsize = grub_cpu_to_le16 (e->e_shentsize);
981 num_sections = grub_cpu_to_le16 (e->e_shnum);
983 if (kernel_size < section_offset + section_entsize * num_sections)
984 grub_util_error ("invalid ELF format");
986 sections = (Elf_Shdr *) (kernel_image + section_offset);
987 strtab = find_strtab (e, sections, section_entsize);
989 /* Relocate sections then symbols in the virtual address space. */
990 section_addresses = locate_sections (sections, section_entsize,
991 num_sections, strtab);
993 symtab_section = find_symtab_section (sections,
994 section_entsize, num_sections);
995 if (! symtab_section)
996 grub_util_error ("no symbol table");
998 start_address = relocate_symbols (e, sections, symtab_section,
999 section_addresses, section_entsize,
1000 num_sections);
1001 if (start_address == 0)
1002 grub_util_error ("start symbol is not defined");
1004 /* Resolve addresses in the virtual address space. */
1005 relocate_addresses (e, sections, section_addresses, section_entsize,
1006 num_sections, strtab);
1008 /* Generate a PE32 image file. The strategy is to dump binary data first,
1009 then fill up the header. */
1010 text_address = make_header_space (out);
1011 data_address = write_text_sections (out, text_address, e, sections,
1012 section_entsize, num_sections,
1013 strtab);
1014 mods_address = write_data_sections (out, data_address, e, sections,
1015 section_entsize, num_sections,
1016 strtab);
1017 reloc_address = make_mods_section (out, mods_address, dir, mods);
1018 end_address = make_reloc_section (out, reloc_address, e, section_addresses,
1019 sections, section_entsize, num_sections,
1020 strtab);
1021 make_header (out, text_address, data_address, mods_address,
1022 reloc_address, end_address, start_address);
1024 /* Clean up. */
1025 free (section_addresses);
1026 free (kernel_image);
1029 static struct option options[] =
1031 {"directory", required_argument, 0, 'd'},
1032 {"prefix", required_argument, 0, 'p'},
1033 {"output", required_argument, 0, 'o'},
1034 {"help", no_argument, 0, 'h'},
1035 {"version", no_argument, 0, 'V'},
1036 {"verbose", no_argument, 0, 'v'},
1037 { 0, 0, 0, 0 }
1040 static void
1041 usage (int status)
1043 if (status)
1044 fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
1045 else
1046 printf ("\
1047 Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
1049 Make a bootable image of GRUB.\n\
1051 -d, --directory=DIR use images and modules under DIR [default=%s]\n\
1052 -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
1053 -o, --output=FILE output a generated image to FILE\n\
1054 -h, --help display this message and exit\n\
1055 -V, --version print version information and exit\n\
1056 -v, --verbose print verbose messages\n\
1058 Report bugs to <%s>.\n\
1059 ", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
1061 exit (status);
1065 main (int argc, char *argv[])
1067 FILE *fp;
1068 char *output = NULL;
1069 char *dir = NULL;
1070 char *prefix = NULL;
1072 progname = "grub-mkimage";
1074 while (1)
1076 int c = getopt_long (argc, argv, "d:p:o:hVv", options, 0);
1077 if (c == -1)
1078 break;
1080 switch (c)
1082 case 'd':
1083 if (dir)
1084 free (dir);
1085 dir = xstrdup (optarg);
1086 break;
1087 case 'h':
1088 usage (0);
1089 break;
1090 case 'o':
1091 if (output)
1092 free (output);
1093 output = xstrdup (optarg);
1094 break;
1095 case 'p':
1096 if (prefix)
1097 free (prefix);
1098 prefix = xstrdup (optarg);
1099 break;
1100 case 'V':
1101 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1102 return 0;
1103 case 'v':
1104 verbosity++;
1105 break;
1106 default:
1107 usage (1);
1108 break;
1112 if (! output)
1113 usage (1);
1115 fp = fopen (output, "wb");
1116 if (! fp)
1117 grub_util_error ("cannot open %s", output);
1119 convert_elf (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind);
1121 fclose (fp);
1123 return 0;