remove all trailing whitespace
[grub2/phcoder/solaris.git] / util / i386 / efi / grub-mkimage.c
blobf4203b5a36e5cb3f932b1008183787d93582170a
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2004,2005,2006,2007,2008,2009 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, 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 return kernel_image;
104 /* Return if the ELF header is valid. */
105 static int
106 check_elf_header (Elf_Ehdr *e, size_t size)
108 if (size < sizeof (*e)
109 || e->e_ident[EI_MAG0] != ELFMAG0
110 || e->e_ident[EI_MAG1] != ELFMAG1
111 || e->e_ident[EI_MAG2] != ELFMAG2
112 || e->e_ident[EI_MAG3] != ELFMAG3
113 || e->e_ident[EI_VERSION] != EV_CURRENT
114 || e->e_version != grub_cpu_to_le32 (EV_CURRENT)
115 || ((e->e_ident[EI_CLASS] != ELFCLASS32) &&
116 (e->e_ident[EI_CLASS] != ELFCLASS64))
117 || e->e_ident[EI_DATA] != ELFDATA2LSB
118 || ((e->e_machine != grub_cpu_to_le16 (EM_386)) &&
119 (e->e_machine != grub_cpu_to_le16 (EM_X86_64))))
120 return 0;
122 return 1;
125 /* Return the starting address right after the header,
126 aligned by the section alignment. Allocate 4 section tables for
127 .text, .data, .reloc, and mods. */
128 static Elf_Addr
129 get_starting_section_address (void)
131 return align_pe32_section (sizeof (struct grub_pe32_header)
132 + 4 * sizeof (struct grub_pe32_section_table));
135 /* Determine if this section is a text section. Return false if this
136 section is not allocated. */
137 static int
138 is_text_section (Elf_Shdr *s)
140 return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
141 == grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
144 /* Determine if this section is a data section. This assumes that
145 BSS is also a data section, since the converter initializes BSS
146 when producing PE32 to avoid a bug in EFI implementations. */
147 static int
148 is_data_section (Elf_Shdr *s)
150 return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
151 && ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
154 /* Locate section addresses by merging code sections and data sections
155 into .text and .data, respectively. Return the array of section
156 addresses. */
157 static Elf_Addr *
158 locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
159 Elf_Half num_sections, const char *strtab)
161 int i;
162 Elf_Addr current_address;
163 Elf_Addr *section_addresses;
164 Elf_Shdr *s;
166 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
167 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
169 current_address = get_starting_section_address ();
171 /* .text */
172 for (i = 0, s = sections;
173 i < num_sections;
174 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
175 if (is_text_section (s))
177 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
178 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
180 if (align)
181 current_address = align_address (current_address, align);
183 grub_util_info ("locating the section %s at 0x%x",
184 name, current_address);
185 section_addresses[i] = current_address;
186 current_address += grub_le_to_cpu32 (s->sh_size);
189 current_address = align_pe32_section (current_address);
191 /* .data */
192 for (i = 0, s = sections;
193 i < num_sections;
194 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
195 if (is_data_section (s))
197 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
198 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
200 if (align)
201 current_address = align_address (current_address, align);
203 grub_util_info ("locating the section %s at 0x%x",
204 name, current_address);
205 section_addresses[i] = current_address;
206 current_address += grub_le_to_cpu32 (s->sh_size);
209 return section_addresses;
212 /* Return the symbol table section, if any. */
213 static Elf_Shdr *
214 find_symtab_section (Elf_Shdr *sections,
215 Elf_Half section_entsize, Elf_Half num_sections)
217 int i;
218 Elf_Shdr *s;
220 for (i = 0, s = sections;
221 i < num_sections;
222 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
223 if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
224 return s;
226 return 0;
229 /* Return the address of the string table. */
230 static const char *
231 find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
233 Elf_Shdr *s;
234 char *strtab;
236 s = (Elf_Shdr *) ((char *) sections
237 + grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
238 strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
239 return strtab;
242 /* Relocate symbols; note that this function overwrites the symbol table.
243 Return the address of a start symbol. */
244 static Elf_Addr
245 relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
246 Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
247 Elf_Half section_entsize, Elf_Half num_sections)
249 Elf_Word symtab_size, sym_size, num_syms;
250 Elf_Off symtab_offset;
251 Elf_Addr start_address = 0;
252 Elf_Sym *sym;
253 Elf_Word i;
254 Elf_Shdr *strtab_section;
255 const char *strtab;
257 strtab_section
258 = (Elf_Shdr *) ((char *) sections
259 + (grub_le_to_cpu32 (symtab_section->sh_link)
260 * section_entsize));
261 strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
263 symtab_size = grub_le_to_cpu32 (symtab_section->sh_size);
264 sym_size = grub_le_to_cpu32 (symtab_section->sh_entsize);
265 symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
266 num_syms = symtab_size / sym_size;
268 for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
269 i < num_syms;
270 i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
272 Elf_Section index;
273 const char *name;
275 name = strtab + grub_le_to_cpu32 (sym->st_name);
277 index = grub_le_to_cpu16 (sym->st_shndx);
278 if (index == STN_ABS)
280 continue;
282 else if ((index == STN_UNDEF))
284 if (sym->st_name)
285 grub_util_error ("undefined symbol %s", name);
286 else
287 continue;
289 else if (index >= num_sections)
290 grub_util_error ("section %d does not exist", index);
292 sym->st_value = (grub_le_to_cpu32 (sym->st_value)
293 + section_addresses[index]);
294 grub_util_info ("locating %s at 0x%x", name, sym->st_value);
296 if (! start_address)
297 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
298 start_address = sym->st_value;
301 return start_address;
304 /* Return the address of a symbol at the index I in the section S. */
305 static Elf_Addr
306 get_symbol_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i)
308 Elf_Sym *sym;
310 sym = (Elf_Sym *) ((char *) e
311 + grub_le_to_cpu32 (s->sh_offset)
312 + i * grub_le_to_cpu32 (s->sh_entsize));
313 return sym->st_value;
316 /* Return the address of a modified value. */
317 static Elf_Addr *
318 get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
320 return (Elf_Addr *) ((char *) e + grub_le_to_cpu32 (s->sh_offset) + offset);
323 /* Deal with relocation information. This function relocates addresses
324 within the virtual address space starting from 0. So only relative
325 addresses can be fully resolved. Absolute addresses must be relocated
326 again by a PE32 relocator when loaded. */
327 static void
328 relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
329 Elf_Addr *section_addresses,
330 Elf_Half section_entsize, Elf_Half num_sections,
331 const char *strtab)
333 Elf_Half i;
334 Elf_Shdr *s;
336 for (i = 0, s = sections;
337 i < num_sections;
338 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
339 if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
340 (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
342 Elf_Rela *r;
343 Elf_Word rtab_size, r_size, num_rs;
344 Elf_Off rtab_offset;
345 Elf_Shdr *symtab_section;
346 Elf_Word target_section_index;
347 Elf_Addr target_section_addr;
348 Elf_Shdr *target_section;
349 Elf_Word j;
351 symtab_section = (Elf_Shdr *) ((char *) sections
352 + (grub_le_to_cpu32 (s->sh_link)
353 * section_entsize));
354 target_section_index = grub_le_to_cpu32 (s->sh_info);
355 target_section_addr = section_addresses[target_section_index];
356 target_section = (Elf_Shdr *) ((char *) sections
357 + (target_section_index
358 * section_entsize));
360 grub_util_info ("dealing with the relocation section %s for %s",
361 strtab + grub_le_to_cpu32 (s->sh_name),
362 strtab + grub_le_to_cpu32 (target_section->sh_name));
364 rtab_size = grub_le_to_cpu32 (s->sh_size);
365 r_size = grub_le_to_cpu32 (s->sh_entsize);
366 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
367 num_rs = rtab_size / r_size;
369 for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
370 j < num_rs;
371 j++, r = (Elf_Rela *) ((char *) r + r_size))
373 Elf_Addr info;
374 Elf_Addr offset;
375 Elf_Addr sym_addr;
376 Elf_Addr *target;
377 Elf_Addr addend;
379 offset = grub_le_to_cpu (r->r_offset);
380 target = get_target_address (e, target_section, offset);
381 info = grub_le_to_cpu (r->r_info);
382 sym_addr = get_symbol_address (e, symtab_section,
383 ELF_R_SYM (info));
385 addend = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
386 r->r_addend : 0;
388 switch (ELF_R_TYPE (info))
390 #if GRUB_TARGET_SIZEOF_VOID_P == 4
391 case R_386_NONE:
392 break;
394 case R_386_32:
395 /* This is absolute. */
396 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
397 + addend + sym_addr);
398 grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
399 *target, offset);
400 break;
402 case R_386_PC32:
403 /* This is relative. */
404 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
405 + addend + sym_addr
406 - target_section_addr - offset);
407 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
408 *target, offset);
409 break;
411 #else
413 case R_X86_64_NONE:
414 break;
416 case R_X86_64_64:
417 *target = grub_cpu_to_le64 (grub_le_to_cpu64 (*target)
418 + addend + sym_addr);
419 grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
420 *target, offset);
421 break;
423 case R_X86_64_PC32:
425 grub_uint32_t *t32 = (grub_uint32_t *) target;
426 *t32 = grub_cpu_to_le64 (grub_le_to_cpu32 (*t32)
427 + addend + sym_addr
428 - target_section_addr - offset);
429 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
430 *t32, offset);
431 break;
434 case R_X86_64_32:
435 case R_X86_64_32S:
437 grub_uint32_t *t32 = (grub_uint32_t *) target;
438 *t32 = grub_cpu_to_le64 (grub_le_to_cpu32 (*t32)
439 + addend + sym_addr);
440 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
441 *t32, offset);
442 break;
445 #endif
446 default:
447 grub_util_error ("unknown relocation type %d",
448 ELF_R_TYPE (info));
449 break;
455 void
456 write_padding (FILE *out, size_t size)
458 size_t i;
460 for (i = 0; i < size; i++)
461 if (fputc (0, out) == EOF)
462 grub_util_error ("padding failed");
465 /* Add a PE32's fixup entry for a relocation. Return the resulting address
466 after having written to the file OUT. */
467 Elf_Addr
468 add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
469 Elf_Addr addr, int flush, Elf_Addr current_address,
470 FILE *out)
472 struct grub_pe32_fixup_block *b = *block;
474 /* First, check if it is necessary to write out the current block. */
475 if (b)
477 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
479 grub_uint32_t size;
481 if (flush)
483 /* Add as much padding as necessary to align the address
484 with a section boundary. */
485 Elf_Addr next_address;
486 unsigned padding_size;
487 size_t index;
489 next_address = current_address + b->block_size;
490 padding_size = ((align_pe32_section (next_address)
491 - next_address)
492 >> 1);
493 index = ((b->block_size - sizeof (*b)) >> 1);
494 grub_util_info ("adding %d padding fixup entries", padding_size);
495 while (padding_size--)
497 b->entries[index++] = 0;
498 b->block_size += 2;
501 else if (b->block_size & (8 - 1))
503 /* If not aligned with a 32-bit boundary, add
504 a padding entry. */
505 size_t index;
507 grub_util_info ("adding a padding fixup entry");
508 index = ((b->block_size - sizeof (*b)) >> 1);
509 b->entries[index] = 0;
510 b->block_size += 2;
513 /* Flush it. */
514 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
515 b->block_size, b->page_rva);
516 size = b->block_size;
517 current_address += size;
518 b->page_rva = grub_cpu_to_le32 (b->page_rva);
519 b->block_size = grub_cpu_to_le32 (b->block_size);
520 if (fwrite (b, size, 1, out) != 1)
521 grub_util_error ("write failed");
522 free (b);
523 *block = b = 0;
527 if (! flush)
529 grub_uint16_t entry;
530 size_t index;
532 /* If not allocated yet, allocate a block with enough entries. */
533 if (! b)
535 *block = b = xmalloc (sizeof (*b) + 2 * 0x1000);
537 /* The spec does not mention the requirement of a Page RVA.
538 Here, align the address with a 4K boundary for safety. */
539 b->page_rva = (addr & ~(0x1000 - 1));
540 b->block_size = sizeof (*b);
543 /* Sanity check. */
544 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
545 grub_util_error ("too many fixup entries");
547 /* Add a new entry. */
548 index = ((b->block_size - sizeof (*b)) >> 1);
549 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
550 b->entries[index] = grub_cpu_to_le16 (entry);
551 b->block_size += 2;
554 return current_address;
557 /* Write out zeros to make space for the header. */
558 static Elf_Addr
559 make_header_space (FILE *out)
561 Elf_Addr addr;
563 addr = get_starting_section_address ();
564 write_padding (out, addr);
566 return addr;
569 /* Write text sections. */
570 static Elf_Addr
571 write_text_sections (FILE *out, Elf_Addr current_address,
572 Elf_Ehdr *e, Elf_Shdr *sections,
573 Elf_Half section_entsize, Elf_Half num_sections,
574 const char *strtab)
576 Elf_Half i;
577 Elf_Shdr *s;
578 Elf_Addr addr;
580 for (i = 0, s = sections;
581 i < num_sections;
582 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
583 if (is_text_section (s))
585 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
586 Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
587 Elf_Word size = grub_le_to_cpu32 (s->sh_size);
588 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
590 if (align)
592 addr = align_address (current_address, align);
593 if (current_address != addr)
595 grub_util_info ("padding %d bytes for the ELF section alignment",
596 addr - current_address);
597 write_padding (out, addr - current_address);
598 current_address = addr;
602 grub_util_info ("writing the text section %s at 0x%x",
603 name, current_address);
605 if (fwrite ((char *) e + offset, size, 1, out) != 1)
606 grub_util_error ("write failed");
608 current_address += size;
611 addr = align_pe32_section (current_address);
612 if (addr != current_address)
614 grub_util_info ("padding %d bytes for the PE32 section alignment",
615 addr - current_address);
616 write_padding (out, addr - current_address);
619 return addr;
622 /* Write data sections. */
623 static Elf_Addr
624 write_data_sections (FILE *out, Elf_Addr current_address,
625 Elf_Ehdr *e, Elf_Shdr *sections,
626 Elf_Half section_entsize, Elf_Half num_sections,
627 const char *strtab)
629 Elf_Half i;
630 Elf_Shdr *s;
631 Elf_Addr addr;
633 for (i = 0, s = sections;
634 i < num_sections;
635 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
636 if (is_data_section (s))
638 Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
639 Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
640 Elf_Word size = grub_le_to_cpu32 (s->sh_size);
641 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
643 if (align)
645 addr = align_address (current_address, align);
646 if (current_address != addr)
648 grub_util_info ("padding %d bytes for the ELF section alignment",
649 addr - current_address);
650 write_padding (out, addr - current_address);
651 current_address = addr;
655 grub_util_info ("writing the data section %s at 0x%x",
656 name, current_address);
658 if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS))
659 write_padding (out, size);
660 else
661 if (fwrite ((char *) e + offset, size, 1, out) != 1)
662 grub_util_error ("write failed");
664 current_address += size;
667 addr = align_pe32_section (current_address);
668 if (addr != current_address)
670 grub_util_info ("padding %d bytes for the PE32 section alignment",
671 addr - current_address);
672 write_padding (out, addr - current_address);
675 return addr;
678 /* Write modules. */
679 static Elf_Addr
680 make_mods_section (FILE *out, Elf_Addr current_address,
681 const char *dir, char *mods[])
683 struct grub_util_path_list *path_list;
684 grub_size_t total_module_size;
685 struct grub_util_path_list *p;
686 struct grub_module_info modinfo;
687 Elf_Addr addr;
689 memset (&modinfo, 0, sizeof (modinfo));
691 path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
693 total_module_size = sizeof (struct grub_module_info);
694 for (p = path_list; p; p = p->next)
696 total_module_size += (grub_util_get_image_size (p->name)
697 + sizeof (struct grub_module_header));
700 grub_util_info ("the total module size is 0x%x", total_module_size);
702 modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC);
703 modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo));
704 modinfo.size = grub_cpu_to_le32 (total_module_size);
706 if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1)
707 grub_util_error ("write failed");
709 for (p = path_list; p; p = p->next)
711 struct grub_module_header header;
712 size_t mod_size;
713 char *mod_image;
715 memset (&header, 0, sizeof (header));
717 grub_util_info ("adding module %s", p->name);
719 mod_size = grub_util_get_image_size (p->name);
720 header.type = grub_cpu_to_le32 (OBJ_TYPE_ELF);
721 header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
723 mod_image = grub_util_read_image (p->name);
725 if (fwrite (&header, sizeof (header), 1, out) != 1
726 || fwrite (mod_image, mod_size, 1, out) != 1)
727 grub_util_error ("write failed");
729 free (mod_image);
732 for (p = path_list; p; )
734 struct grub_util_path_list *q;
736 q = p->next;
737 free (p);
738 p = q;
741 current_address += total_module_size;
743 addr = align_pe32_section (current_address);
744 if (addr != current_address)
746 grub_util_info ("padding %d bytes for the PE32 section alignment",
747 addr - current_address);
748 write_padding (out, addr - current_address);
751 return addr;
754 /* Make a .reloc section. */
755 static Elf_Addr
756 make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
757 Elf_Addr *section_addresses, Elf_Shdr *sections,
758 Elf_Half section_entsize, Elf_Half num_sections,
759 const char *strtab)
761 Elf_Half i;
762 Elf_Shdr *s;
763 struct grub_pe32_fixup_block *fixup_block = 0;
765 for (i = 0, s = sections;
766 i < num_sections;
767 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
768 if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
769 (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
771 Elf_Rel *r;
772 Elf_Word rtab_size, r_size, num_rs;
773 Elf_Off rtab_offset;
774 Elf_Addr section_address;
775 Elf_Word j;
777 grub_util_info ("translating the relocation section %s",
778 strtab + grub_le_to_cpu32 (s->sh_name));
780 rtab_size = grub_le_to_cpu32 (s->sh_size);
781 r_size = grub_le_to_cpu32 (s->sh_entsize);
782 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
783 num_rs = rtab_size / r_size;
785 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
787 for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
788 j < num_rs;
789 j++, r = (Elf_Rel *) ((char *) r + r_size))
791 Elf_Addr info;
792 Elf_Addr offset;
794 offset = grub_le_to_cpu32 (r->r_offset);
795 info = grub_le_to_cpu32 (r->r_info);
797 /* Necessary to relocate only absolute addresses. */
798 #if GRUB_TARGET_SIZEOF_VOID_P == 4
799 if (ELF_R_TYPE (info) == R_386_32)
801 Elf_Addr addr;
803 addr = section_address + offset;
804 grub_util_info ("adding a relocation entry for 0x%x", addr);
805 current_address = add_fixup_entry (&fixup_block,
806 GRUB_PE32_REL_BASED_HIGHLOW,
807 addr, 0, current_address,
808 out);
810 #else
811 if ((ELF_R_TYPE (info) == R_X86_64_32) ||
812 (ELF_R_TYPE (info) == R_X86_64_32S))
814 grub_util_error ("Can\'t add fixup entry for R_X86_64_32(S)");
816 else if (ELF_R_TYPE (info) == R_X86_64_64)
818 Elf_Addr addr;
820 addr = section_address + offset;
821 grub_util_info ("adding a relocation entry for 0x%llx", addr);
822 current_address = add_fixup_entry (&fixup_block,
823 GRUB_PE32_REL_BASED_DIR64,
824 addr,
825 0, current_address,
826 out);
828 #endif
832 current_address = add_fixup_entry (&fixup_block, 0, 0, 1,
833 current_address, out);
835 return current_address;
838 /* Create the header. */
839 static void
840 make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
841 Elf_Addr mods_address, Elf_Addr reloc_address,
842 Elf_Addr end_address, Elf_Addr start_address)
844 struct grub_pe32_header header;
845 struct grub_pe32_coff_header *c;
846 struct grub_pe32_optional_header *o;
847 struct grub_pe32_section_table text_section, data_section;
848 struct grub_pe32_section_table mods_section, reloc_section;
850 /* The magic. */
851 memset (&header, 0, sizeof (header));
852 memcpy (header.msdos_stub, stub, sizeof (header.msdos_stub));
853 memcpy (header.signature, "PE\0\0", sizeof (header.signature));
855 /* The COFF file header. */
856 c = &header.coff_header;
857 #if GRUB_TARGET_SIZEOF_VOID_P == 4
858 c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
859 #else
860 c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64);
861 #endif
863 c->num_sections = grub_cpu_to_le16 (4);
864 c->time = grub_cpu_to_le32 (time (0));
865 c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
866 c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
867 | GRUB_PE32_LINE_NUMS_STRIPPED
868 #if GRUB_TARGET_SIZEOF_VOID_P == 4
869 | GRUB_PE32_32BIT_MACHINE
870 #endif
871 | GRUB_PE32_LOCAL_SYMS_STRIPPED
872 | GRUB_PE32_DEBUG_STRIPPED);
874 /* The PE Optional header. */
875 o = &header.optional_header;
876 o->magic = grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC);
877 o->code_size = grub_cpu_to_le32 (data_address - text_address);
878 o->data_size = grub_cpu_to_le32 (reloc_address - data_address);
879 o->bss_size = 0;
880 o->entry_addr = grub_cpu_to_le32 (start_address);
881 o->code_base = grub_cpu_to_le32 (text_address);
882 #if GRUB_TARGET_SIZEOF_VOID_P == 4
883 o->data_base = grub_cpu_to_le32 (data_address);
884 #endif
885 o->image_base = 0;
886 o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
887 o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
888 o->image_size = grub_cpu_to_le32 (end_address);
889 o->header_size = grub_cpu_to_le32 (text_address);
890 o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
892 /* Do these really matter? */
893 o->stack_reserve_size = grub_cpu_to_le32 (0x10000);
894 o->stack_commit_size = grub_cpu_to_le32 (0x10000);
895 o->heap_reserve_size = grub_cpu_to_le32 (0x10000);
896 o->heap_commit_size = grub_cpu_to_le32 (0x10000);
898 o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
900 o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address);
901 o->base_relocation_table.size = grub_cpu_to_le32 (end_address
902 - reloc_address);
904 /* The sections. */
905 memset (&text_section, 0, sizeof (text_section));
906 strcpy (text_section.name, ".text");
907 text_section.virtual_size = grub_cpu_to_le32 (data_address - text_address);
908 text_section.virtual_address = grub_cpu_to_le32 (text_address);
909 text_section.raw_data_size = grub_cpu_to_le32 (data_address - text_address);
910 text_section.raw_data_offset = grub_cpu_to_le32 (text_address);
911 text_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
912 | GRUB_PE32_SCN_MEM_EXECUTE
913 | GRUB_PE32_SCN_MEM_READ);
915 memset (&data_section, 0, sizeof (data_section));
916 strcpy (data_section.name, ".data");
917 data_section.virtual_size = grub_cpu_to_le32 (mods_address - data_address);
918 data_section.virtual_address = grub_cpu_to_le32 (data_address);
919 data_section.raw_data_size = grub_cpu_to_le32 (mods_address - data_address);
920 data_section.raw_data_offset = grub_cpu_to_le32 (data_address);
921 data_section.characteristics
922 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
923 | GRUB_PE32_SCN_MEM_READ
924 | GRUB_PE32_SCN_MEM_WRITE);
926 memset (&mods_section, 0, sizeof (mods_section));
927 strcpy (mods_section.name, "mods");
928 mods_section.virtual_size = grub_cpu_to_le32 (reloc_address - mods_address);
929 mods_section.virtual_address = grub_cpu_to_le32 (mods_address);
930 mods_section.raw_data_size = grub_cpu_to_le32 (reloc_address - mods_address);
931 mods_section.raw_data_offset = grub_cpu_to_le32 (mods_address);
932 mods_section.characteristics
933 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
934 | GRUB_PE32_SCN_MEM_READ
935 | GRUB_PE32_SCN_MEM_WRITE);
937 memset (&reloc_section, 0, sizeof (reloc_section));
938 strcpy (reloc_section.name, ".reloc");
939 reloc_section.virtual_size = grub_cpu_to_le32 (end_address - reloc_address);
940 reloc_section.virtual_address = grub_cpu_to_le32 (reloc_address);
941 reloc_section.raw_data_size = grub_cpu_to_le32 (end_address - reloc_address);
942 reloc_section.raw_data_offset = grub_cpu_to_le32 (reloc_address);
943 reloc_section.characteristics
944 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
945 | GRUB_PE32_SCN_MEM_DISCARDABLE
946 | GRUB_PE32_SCN_MEM_READ);
948 /* Write them out. */
949 if (fseeko (out, 0, SEEK_SET) < 0)
950 grub_util_error ("seek failed");
952 if (fwrite (&header, sizeof (header), 1, out) != 1
953 || fwrite (&text_section, sizeof (text_section), 1, out) != 1
954 || fwrite (&data_section, sizeof (data_section), 1, out) != 1
955 || fwrite (&mods_section, sizeof (mods_section), 1, out) != 1
956 || fwrite (&reloc_section, sizeof (reloc_section), 1, out) != 1)
957 grub_util_error ("write failed");
960 /* Convert an ELF relocatable object into an EFI Application (PE32). */
961 void
962 convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
964 char *kernel_image;
965 size_t kernel_size;
966 const char *strtab;
967 Elf_Ehdr *e;
968 Elf_Shdr *sections;
969 Elf_Off section_offset;
970 Elf_Half section_entsize;
971 Elf_Half num_sections;
972 Elf_Addr *section_addresses;
973 Elf_Shdr *symtab_section;
974 Elf_Addr start_address;
975 Elf_Addr text_address, data_address, reloc_address, mods_address;
976 Elf_Addr end_address;
977 Elf_Shdr *s;
978 int i;
980 /* Get the kernel image and check the format. */
981 kernel_image = read_kernel_module (dir, &kernel_size);
982 e = (Elf_Ehdr *) kernel_image;
983 if (! check_elf_header (e, kernel_size))
984 grub_util_error ("invalid ELF header");
986 section_offset = grub_cpu_to_le32 (e->e_shoff);
987 section_entsize = grub_cpu_to_le16 (e->e_shentsize);
988 num_sections = grub_cpu_to_le16 (e->e_shnum);
990 if (kernel_size < section_offset + section_entsize * num_sections)
991 grub_util_error ("invalid ELF format");
993 sections = (Elf_Shdr *) (kernel_image + section_offset);
994 strtab = find_strtab (e, sections, section_entsize);
996 for (i = 0, s = sections;
997 i < num_sections;
998 i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
999 if (is_text_section (s))
1001 Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
1003 if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
1004 grub_util_error ("prefix too long");
1006 strcpy (kernel_image + offset + GRUB_KERNEL_MACHINE_PREFIX, prefix);
1007 break;
1010 /* Relocate sections then symbols in the virtual address space. */
1011 section_addresses = locate_sections (sections, section_entsize,
1012 num_sections, strtab);
1014 symtab_section = find_symtab_section (sections,
1015 section_entsize, num_sections);
1016 if (! symtab_section)
1017 grub_util_error ("no symbol table");
1019 start_address = relocate_symbols (e, sections, symtab_section,
1020 section_addresses, section_entsize,
1021 num_sections);
1022 if (start_address == 0)
1023 grub_util_error ("start symbol is not defined");
1025 /* Resolve addresses in the virtual address space. */
1026 relocate_addresses (e, sections, section_addresses, section_entsize,
1027 num_sections, strtab);
1029 /* Generate a PE32 image file. The strategy is to dump binary data first,
1030 then fill up the header. */
1031 text_address = make_header_space (out);
1032 data_address = write_text_sections (out, text_address, e, sections,
1033 section_entsize, num_sections,
1034 strtab);
1035 mods_address = write_data_sections (out, data_address, e, sections,
1036 section_entsize, num_sections,
1037 strtab);
1038 reloc_address = make_mods_section (out, mods_address, dir, mods);
1039 end_address = make_reloc_section (out, reloc_address, e, section_addresses,
1040 sections, section_entsize, num_sections,
1041 strtab);
1042 make_header (out, text_address, data_address, mods_address,
1043 reloc_address, end_address, start_address);
1045 /* Clean up. */
1046 free (section_addresses);
1047 free (kernel_image);
1050 static struct option options[] =
1052 {"directory", required_argument, 0, 'd'},
1053 {"prefix", required_argument, 0, 'p'},
1054 {"output", required_argument, 0, 'o'},
1055 {"help", no_argument, 0, 'h'},
1056 {"version", no_argument, 0, 'V'},
1057 {"verbose", no_argument, 0, 'v'},
1058 { 0, 0, 0, 0 }
1061 static void
1062 usage (int status)
1064 if (status)
1065 fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
1066 else
1067 printf ("\
1068 Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
1070 Make a bootable image of GRUB.\n\
1072 -d, --directory=DIR use images and modules under DIR [default=%s]\n\
1073 -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
1074 -o, --output=FILE output a generated image to FILE\n\
1075 -h, --help display this message and exit\n\
1076 -V, --version print version information and exit\n\
1077 -v, --verbose print verbose messages\n\
1079 Report bugs to <%s>.\n\
1080 ", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
1082 exit (status);
1086 main (int argc, char *argv[])
1088 FILE *fp;
1089 char *output = NULL;
1090 char *dir = NULL;
1091 char *prefix = NULL;
1093 progname = "grub-mkimage";
1095 while (1)
1097 int c = getopt_long (argc, argv, "d:p:o:hVv", options, 0);
1098 if (c == -1)
1099 break;
1101 switch (c)
1103 case 'd':
1104 if (dir)
1105 free (dir);
1106 dir = xstrdup (optarg);
1107 break;
1108 case 'h':
1109 usage (0);
1110 break;
1111 case 'o':
1112 if (output)
1113 free (output);
1114 output = xstrdup (optarg);
1115 break;
1116 case 'p':
1117 if (prefix)
1118 free (prefix);
1119 prefix = xstrdup (optarg);
1120 break;
1121 case 'V':
1122 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
1123 return 0;
1124 case 'v':
1125 verbosity++;
1126 break;
1127 default:
1128 usage (1);
1129 break;
1133 if (! output)
1134 usage (1);
1136 fp = fopen (output, "wb");
1137 if (! fp)
1138 grub_util_error ("cannot open %s", output);
1140 convert_elf (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind);
1142 fclose (fp);
1144 return 0;