make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / common / boot / grub2 / util / i386 / efi / grub-mkimage.c
blob57c1fc88d01bb1105c43f26988d00b5ce08e967f
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 static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
36 static inline Elf32_Addr
37 align_address (Elf32_Addr addr, unsigned alignment)
39 return (addr + alignment - 1) & ~(alignment - 1);
42 static inline Elf32_Addr
43 align_pe32_section (Elf32_Addr addr)
45 return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT);
48 /* Read the whole kernel image. Return the pointer to a read image,
49 and store the size in bytes in *SIZE. */
50 static char *
51 read_kernel_module (const char *dir, char *prefix, size_t *size)
53 char *kernel_image;
54 char *kernel_path;
56 kernel_path = grub_util_get_path (dir, "kernel.mod");
57 *size = grub_util_get_image_size (kernel_path);
58 kernel_image = grub_util_read_image (kernel_path);
59 free (kernel_path);
61 if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
62 grub_util_error ("prefix too long");
63 strcpy (kernel_image + 0x34 + GRUB_KERNEL_MACHINE_PREFIX, prefix);
65 return kernel_image;
68 /* Return if the ELF header is valid. */
69 static int
70 check_elf_header (Elf32_Ehdr *e, size_t size)
72 if (size < sizeof (*e)
73 || e->e_ident[EI_MAG0] != ELFMAG0
74 || e->e_ident[EI_MAG1] != ELFMAG1
75 || e->e_ident[EI_MAG2] != ELFMAG2
76 || e->e_ident[EI_MAG3] != ELFMAG3
77 || e->e_ident[EI_VERSION] != EV_CURRENT
78 || e->e_version != grub_cpu_to_le32 (EV_CURRENT)
79 || e->e_ident[EI_CLASS] != ELFCLASS32
80 || e->e_ident[EI_DATA] != ELFDATA2LSB
81 || e->e_machine != grub_cpu_to_le16 (EM_386))
82 return 0;
84 return 1;
87 /* Return the starting address right after the header,
88 aligned by the section alignment. Allocate 4 section tables for
89 .text, .data, .reloc, and mods. */
90 static Elf32_Addr
91 get_starting_section_address (void)
93 return align_pe32_section (sizeof (struct grub_pe32_header)
94 + 4 * sizeof (struct grub_pe32_section_table));
97 /* Determine if this section is a text section. Return false if this
98 section is not allocated. */
99 static int
100 is_text_section (Elf32_Shdr *s)
102 return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
103 == grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
106 /* Determine if this section is a data section. This assumes that
107 BSS is also a data section, since the converter initializes BSS
108 when producing PE32 to avoid a bug in EFI implementations. */
109 static int
110 is_data_section (Elf32_Shdr *s)
112 return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
113 && ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
116 /* Locate section addresses by merging code sections and data sections
117 into .text and .data, respectively. Return the array of section
118 addresses. */
119 static Elf32_Addr *
120 locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
121 Elf32_Half num_sections, const char *strtab)
123 int i;
124 Elf32_Addr current_address;
125 Elf32_Addr *section_addresses;
126 Elf32_Shdr *s;
128 section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
129 memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
131 current_address = get_starting_section_address ();
133 /* .text */
134 for (i = 0, s = sections;
135 i < num_sections;
136 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
137 if (is_text_section (s))
139 Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
140 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
142 if (align)
143 current_address = align_address (current_address, align);
145 grub_util_info ("locating the section %s at 0x%x",
146 name, current_address);
147 section_addresses[i] = current_address;
148 current_address += grub_le_to_cpu32 (s->sh_size);
151 current_address = align_pe32_section (current_address);
153 /* .data */
154 for (i = 0, s = sections;
155 i < num_sections;
156 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
157 if (is_data_section (s))
159 Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
160 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
162 if (align)
163 current_address = align_address (current_address, align);
165 grub_util_info ("locating the section %s at 0x%x",
166 name, current_address);
167 section_addresses[i] = current_address;
168 current_address += grub_le_to_cpu32 (s->sh_size);
171 return section_addresses;
174 /* Return the symbol table section, if any. */
175 static Elf32_Shdr *
176 find_symtab_section (Elf32_Shdr *sections,
177 Elf32_Half section_entsize, Elf32_Half num_sections)
179 int i;
180 Elf32_Shdr *s;
182 for (i = 0, s = sections;
183 i < num_sections;
184 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
185 if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
186 return s;
188 return 0;
191 /* Return the address of the string table. */
192 static const char *
193 find_strtab (Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize)
195 Elf32_Shdr *s;
196 char *strtab;
198 s = (Elf32_Shdr *) ((char *) sections
199 + grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
200 strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
201 return strtab;
204 /* Relocate symbols; note that this function overwrites the symbol table.
205 Return the address of a start symbol. */
206 static Elf32_Addr
207 relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
208 Elf32_Shdr *symtab_section, Elf32_Addr *section_addresses,
209 Elf32_Half section_entsize, Elf32_Half num_sections)
211 Elf32_Word symtab_size, sym_size, num_syms;
212 Elf32_Off symtab_offset;
213 Elf32_Addr start_address = 0;
214 Elf32_Sym *sym;
215 Elf32_Word i;
216 Elf32_Shdr *strtab_section;
217 const char *strtab;
219 strtab_section
220 = (Elf32_Shdr *) ((char *) sections
221 + (grub_le_to_cpu32 (symtab_section->sh_link)
222 * section_entsize));
223 strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
225 symtab_size = grub_le_to_cpu32 (symtab_section->sh_size);
226 sym_size = grub_le_to_cpu32 (symtab_section->sh_entsize);
227 symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
228 num_syms = symtab_size / sym_size;
230 for (i = 0, sym = (Elf32_Sym *) ((char *) e + symtab_offset);
231 i < num_syms;
232 i++, sym = (Elf32_Sym *) ((char *) sym + sym_size))
234 Elf32_Section index;
235 const char *name;
237 name = strtab + grub_le_to_cpu32 (sym->st_name);
239 index = grub_le_to_cpu16 (sym->st_shndx);
240 if (index == STN_UNDEF)
242 if (sym->st_name)
243 grub_util_error ("undefined symbol %s", name);
244 else
245 continue;
247 else if (index >= num_sections)
248 grub_util_error ("section %d does not exist", index);
250 sym->st_value = (grub_le_to_cpu32 (sym->st_value)
251 + section_addresses[index]);
252 grub_util_info ("locating %s at 0x%x", name, sym->st_value);
254 if (! start_address)
255 if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
256 start_address = sym->st_value;
259 return start_address;
262 /* Return the address of a symbol at the index I in the section S. */
263 static Elf32_Addr
264 get_symbol_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Word i)
266 Elf32_Sym *sym;
268 sym = (Elf32_Sym *) ((char *) e
269 + grub_le_to_cpu32 (s->sh_offset)
270 + i * grub_le_to_cpu32 (s->sh_entsize));
271 return sym->st_value;
274 /* Return the address of a modified value. */
275 static Elf32_Addr
276 get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset)
278 return (Elf32_Addr) e + grub_le_to_cpu32 (s->sh_offset) + offset;
281 /* Deal with relocation information. This function relocates addresses
282 within the virtual address space starting from 0. So only relative
283 addresses can be fully resolved. Absolute addresses must be relocated
284 again by a PE32 relocator when loaded. */
285 static void
286 relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
287 Elf32_Addr *section_addresses,
288 Elf32_Half section_entsize, Elf32_Half num_sections,
289 const char *strtab)
291 Elf32_Half i;
292 Elf32_Shdr *s;
294 for (i = 0, s = sections;
295 i < num_sections;
296 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
297 if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
299 Elf32_Rel *r;
300 Elf32_Word rtab_size, r_size, num_rs;
301 Elf32_Off rtab_offset;
302 Elf32_Shdr *symtab_section;
303 Elf32_Word target_section_index;
304 Elf32_Addr target_section_addr;
305 Elf32_Shdr *target_section;
306 Elf32_Word j;
308 symtab_section = (Elf32_Shdr *) ((char *) sections
309 + (grub_le_to_cpu32 (s->sh_link)
310 * section_entsize));
311 target_section_index = grub_le_to_cpu32 (s->sh_info);
312 target_section_addr = section_addresses[target_section_index];
313 target_section = (Elf32_Shdr *) ((char *) sections
314 + (target_section_index
315 * section_entsize));
317 grub_util_info ("dealing with the relocation section %s for %s",
318 strtab + grub_le_to_cpu32 (s->sh_name),
319 strtab + grub_le_to_cpu32 (target_section->sh_name));
321 rtab_size = grub_le_to_cpu32 (s->sh_size);
322 r_size = grub_le_to_cpu32 (s->sh_entsize);
323 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
324 num_rs = rtab_size / r_size;
326 for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
327 j < num_rs;
328 j++, r = (Elf32_Rel *) ((char *) r + r_size))
330 Elf32_Word info;
331 Elf32_Addr offset;
332 Elf32_Addr sym_addr;
333 Elf32_Addr *target;
335 offset = grub_le_to_cpu32 (r->r_offset);
336 target = (Elf32_Addr *) get_target_address (e, target_section,
337 offset);
338 info = grub_le_to_cpu32 (r->r_info);
339 sym_addr = get_symbol_address (e, symtab_section,
340 ELF32_R_SYM (info));
342 switch (ELF32_R_TYPE (info))
344 case R_386_NONE:
345 break;
347 case R_386_32:
348 /* This is absolute. */
349 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
350 + sym_addr);
351 grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
352 *target, offset);
353 break;
355 case R_386_PC32:
356 /* This is relative. */
357 *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
358 + sym_addr
359 - target_section_addr - offset);
360 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
361 *target, offset);
362 break;
364 default:
365 grub_util_error ("unknown relocation type %d",
366 ELF32_R_TYPE (info));
367 break;
373 void
374 write_padding (FILE *out, size_t size)
376 size_t i;
378 for (i = 0; i < size; i++)
379 if (fputc (0, out) == EOF)
380 grub_util_error ("padding failed");
383 /* Add a PE32's fixup entry for a relocation. Return the resulting address
384 after having written to the file OUT. */
385 Elf32_Addr
386 add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
387 Elf32_Addr addr, int flush, Elf32_Addr current_address,
388 FILE *out)
390 struct grub_pe32_fixup_block *b = *block;
392 /* First, check if it is necessary to write out the current block. */
393 if (b)
395 if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
397 grub_uint32_t size;
399 if (flush)
401 /* Add as much padding as necessary to align the address
402 with a section boundary. */
403 Elf32_Addr next_address;
404 unsigned padding_size;
405 size_t index;
407 next_address = current_address + b->block_size;
408 padding_size = ((align_pe32_section (next_address)
409 - next_address)
410 >> 1);
411 index = ((b->block_size - sizeof (*b)) >> 1);
412 grub_util_info ("adding %d padding fixup entries", padding_size);
413 while (padding_size--)
415 b->entries[index++] = 0;
416 b->block_size += 2;
419 else if (b->block_size & (8 - 1))
421 /* If not aligned with a 32-bit boundary, add
422 a padding entry. */
423 size_t index;
425 grub_util_info ("adding a padding fixup entry");
426 index = ((b->block_size - sizeof (*b)) >> 1);
427 b->entries[index] = 0;
428 b->block_size += 2;
431 /* Flush it. */
432 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
433 b->block_size, b->page_rva);
434 size = b->block_size;
435 current_address += size;
436 b->page_rva = grub_cpu_to_le32 (b->page_rva);
437 b->block_size = grub_cpu_to_le32 (b->block_size);
438 if (fwrite (b, size, 1, out) != 1)
439 grub_util_error ("write failed");
440 free (b);
441 *block = b = 0;
445 if (! flush)
447 grub_uint16_t entry;
448 size_t index;
450 /* If not allocated yet, allocate a block with enough entries. */
451 if (! b)
453 *block = b = xmalloc (sizeof (*b) + 2 * 0x1000);
455 /* The spec does not mention the requirement of a Page RVA.
456 Here, align the address with a 4K boundary for safety. */
457 b->page_rva = (addr & ~(0x1000 - 1));
458 b->block_size = sizeof (*b);
461 /* Sanity check. */
462 if (b->block_size >= sizeof (*b) + 2 * 0x1000)
463 grub_util_error ("too many fixup entries");
465 /* Add a new entry. */
466 index = ((b->block_size - sizeof (*b)) >> 1);
467 entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
468 b->entries[index] = grub_cpu_to_le16 (entry);
469 b->block_size += 2;
472 return current_address;
475 /* Write out zeros to make space for the header. */
476 static Elf32_Addr
477 make_header_space (FILE *out)
479 Elf32_Addr addr;
481 addr = get_starting_section_address ();
482 write_padding (out, addr);
484 return addr;
487 /* Write text sections. */
488 static Elf32_Addr
489 write_text_sections (FILE *out, Elf32_Addr current_address,
490 Elf32_Ehdr *e, Elf32_Shdr *sections,
491 Elf32_Half section_entsize, Elf32_Half num_sections,
492 const char *strtab)
494 Elf32_Half i;
495 Elf32_Shdr *s;
496 Elf32_Addr addr;
498 for (i = 0, s = sections;
499 i < num_sections;
500 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
501 if (is_text_section (s))
503 Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
504 Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
505 Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
506 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
508 if (align)
510 addr = align_address (current_address, align);
511 if (current_address != addr)
513 grub_util_info ("padding %d bytes for the ELF section alignment",
514 addr - current_address);
515 write_padding (out, addr - current_address);
516 current_address = addr;
520 grub_util_info ("writing the text section %s at 0x%x",
521 name, current_address);
523 if (fwrite ((char *) e + offset, size, 1, out) != 1)
524 grub_util_error ("write failed");
526 current_address += size;
529 addr = align_pe32_section (current_address);
530 if (addr != current_address)
532 grub_util_info ("padding %d bytes for the PE32 section alignment",
533 addr - current_address);
534 write_padding (out, addr - current_address);
537 return addr;
540 /* Write data sections. */
541 static Elf32_Addr
542 write_data_sections (FILE *out, Elf32_Addr current_address,
543 Elf32_Ehdr *e, Elf32_Shdr *sections,
544 Elf32_Half section_entsize, Elf32_Half num_sections,
545 const char *strtab)
547 Elf32_Half i;
548 Elf32_Shdr *s;
549 Elf32_Addr addr;
551 for (i = 0, s = sections;
552 i < num_sections;
553 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
554 if (is_data_section (s))
556 Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
557 Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
558 Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
559 const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
561 if (align)
563 addr = align_address (current_address, align);
564 if (current_address != addr)
566 grub_util_info ("padding %d bytes for the ELF section alignment",
567 addr - current_address);
568 write_padding (out, addr - current_address);
569 current_address = addr;
573 grub_util_info ("writing the data section %s at 0x%x",
574 name, current_address);
576 if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS))
577 write_padding (out, size);
578 else
579 if (fwrite ((char *) e + offset, size, 1, out) != 1)
580 grub_util_error ("write failed");
582 current_address += size;
585 addr = align_pe32_section (current_address);
586 if (addr != current_address)
588 grub_util_info ("padding %d bytes for the PE32 section alignment",
589 addr - current_address);
590 write_padding (out, addr - current_address);
593 return addr;
596 /* Write modules. */
597 static Elf32_Addr
598 make_mods_section (FILE *out, Elf32_Addr current_address,
599 const char *dir, char *mods[])
601 struct grub_util_path_list *path_list;
602 grub_size_t total_module_size;
603 struct grub_util_path_list *p;
604 struct grub_module_info modinfo;
605 Elf32_Addr addr;
607 path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
609 total_module_size = sizeof (struct grub_module_info);
610 for (p = path_list; p; p = p->next)
612 total_module_size += (grub_util_get_image_size (p->name)
613 + sizeof (struct grub_module_header));
616 grub_util_info ("the total module size is 0x%x", total_module_size);
618 modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC);
619 modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo));
620 modinfo.size = grub_cpu_to_le32 (total_module_size);
622 if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1)
623 grub_util_error ("write failed");
625 for (p = path_list; p; p = p->next)
627 struct grub_module_header header;
628 size_t mod_size;
629 char *mod_image;
631 grub_util_info ("adding module %s", p->name);
633 mod_size = grub_util_get_image_size (p->name);
634 header.offset = grub_cpu_to_le32 (sizeof (header));
635 header.size = grub_cpu_to_le32 (mod_size + sizeof (header));
637 mod_image = grub_util_read_image (p->name);
639 if (fwrite (&header, sizeof (header), 1, out) != 1
640 || fwrite (mod_image, mod_size, 1, out) != 1)
641 grub_util_error ("write failed");
643 free (mod_image);
646 for (p = path_list; p; )
648 struct grub_util_path_list *q;
650 q = p->next;
651 free (p);
652 p = q;
655 current_address += total_module_size;
657 addr = align_pe32_section (current_address);
658 if (addr != current_address)
660 grub_util_info ("padding %d bytes for the PE32 section alignment",
661 addr - current_address);
662 write_padding (out, addr - current_address);
665 return addr;
668 /* Make a .reloc section. */
669 static Elf32_Addr
670 make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
671 Elf32_Addr *section_addresses, Elf32_Shdr *sections,
672 Elf32_Half section_entsize, Elf32_Half num_sections,
673 const char *strtab)
675 Elf32_Half i;
676 Elf32_Shdr *s;
677 struct grub_pe32_fixup_block *fixup_block = 0;
679 for (i = 0, s = sections;
680 i < num_sections;
681 i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
682 if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
684 Elf32_Rel *r;
685 Elf32_Word rtab_size, r_size, num_rs;
686 Elf32_Off rtab_offset;
687 Elf32_Addr section_address;
688 Elf32_Word j;
690 grub_util_info ("translating the relocation section %s",
691 strtab + grub_le_to_cpu32 (s->sh_name));
693 rtab_size = grub_le_to_cpu32 (s->sh_size);
694 r_size = grub_le_to_cpu32 (s->sh_entsize);
695 rtab_offset = grub_le_to_cpu32 (s->sh_offset);
696 num_rs = rtab_size / r_size;
698 section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
700 for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
701 j < num_rs;
702 j++, r = (Elf32_Rel *) ((char *) r + r_size))
704 Elf32_Word info;
705 Elf32_Addr offset;
707 offset = grub_le_to_cpu32 (r->r_offset);
708 info = grub_le_to_cpu32 (r->r_info);
710 /* Necessary to relocate only absolute addresses. */
711 if (ELF32_R_TYPE (info) == R_386_32)
713 Elf32_Addr addr;
715 addr = section_address + offset;
716 grub_util_info ("adding a relocation entry for 0x%x", addr);
717 current_address = add_fixup_entry (&fixup_block,
718 GRUB_PE32_REL_BASED_HIGHLOW,
719 addr, 0, current_address,
720 out);
725 current_address = add_fixup_entry (&fixup_block, 0, 0, 1,
726 current_address, out);
728 return current_address;
731 /* Create the header. */
732 static void
733 make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
734 Elf32_Addr mods_address, Elf32_Addr reloc_address,
735 Elf32_Addr end_address, Elf32_Addr start_address)
737 struct grub_pe32_header header;
738 struct grub_pe32_coff_header *c;
739 struct grub_pe32_optional_header *o;
740 struct grub_pe32_section_table text_section, data_section;
741 struct grub_pe32_section_table mods_section, reloc_section;
743 /* The magic. */
744 memset (&header, 0, sizeof (header));
745 memcpy (header.msdos_stub, stub, sizeof (header.msdos_stub));
746 memcpy (header.signature, "PE\0\0", sizeof (header.signature));
748 /* The COFF file header. */
749 c = &header.coff_header;
750 c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
751 c->num_sections = grub_cpu_to_le16 (4);
752 c->time = grub_cpu_to_le32 (time (0));
753 c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
754 c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
755 | GRUB_PE32_LINE_NUMS_STRIPPED
756 | GRUB_PE32_LOCAL_SYMS_STRIPPED
757 | GRUB_PE32_32BIT_MACHINE);
759 /* The PE Optional header. */
760 o = &header.optional_header;
761 o->magic = grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC);
762 o->code_size = grub_cpu_to_le32 (data_address - text_address);
763 o->data_size = grub_cpu_to_le32 (reloc_address - data_address);
764 o->bss_size = 0;
765 o->entry_addr = grub_cpu_to_le32 (start_address);
766 o->code_base = grub_cpu_to_le32 (text_address);
767 o->data_base = grub_cpu_to_le32 (data_address);
768 o->image_base = 0;
769 o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
770 o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
771 o->image_size = grub_cpu_to_le32 (end_address);
772 o->header_size = grub_cpu_to_le32 (text_address);
773 o->subsystem = grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
775 /* Do these really matter? */
776 o->stack_reserve_size = grub_cpu_to_le32 (0x10000);
777 o->stack_commit_size = grub_cpu_to_le32 (0x10000);
778 o->heap_reserve_size = grub_cpu_to_le32 (0x10000);
779 o->heap_commit_size = grub_cpu_to_le32 (0x10000);
781 o->num_data_directories = grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
783 o->base_relocation_table.rva = grub_cpu_to_le32 (reloc_address);
784 o->base_relocation_table.size = grub_cpu_to_le32 (end_address
785 - reloc_address);
787 /* The sections. */
788 memset (&text_section, 0, sizeof (text_section));
789 strcpy (text_section.name, ".text");
790 text_section.virtual_size = grub_cpu_to_le32 (data_address - text_address);
791 text_section.virtual_address = grub_cpu_to_le32 (text_address);
792 text_section.raw_data_size = grub_cpu_to_le32 (data_address - text_address);
793 text_section.raw_data_offset = grub_cpu_to_le32 (text_address);
794 text_section.characteristics = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
795 | GRUB_PE32_SCN_MEM_EXECUTE
796 | GRUB_PE32_SCN_MEM_READ);
798 memset (&data_section, 0, sizeof (data_section));
799 strcpy (data_section.name, ".data");
800 data_section.virtual_size = grub_cpu_to_le32 (mods_address - data_address);
801 data_section.virtual_address = grub_cpu_to_le32 (data_address);
802 data_section.raw_data_size = grub_cpu_to_le32 (mods_address - data_address);
803 data_section.raw_data_offset = grub_cpu_to_le32 (data_address);
804 data_section.characteristics
805 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
806 | GRUB_PE32_SCN_MEM_READ
807 | GRUB_PE32_SCN_MEM_WRITE);
809 memset (&mods_section, 0, sizeof (mods_section));
810 strcpy (mods_section.name, "mods");
811 mods_section.virtual_size = grub_cpu_to_le32 (reloc_address - mods_address);
812 mods_section.virtual_address = grub_cpu_to_le32 (mods_address);
813 mods_section.raw_data_size = grub_cpu_to_le32 (reloc_address - mods_address);
814 mods_section.raw_data_offset = grub_cpu_to_le32 (mods_address);
815 mods_section.characteristics
816 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
817 | GRUB_PE32_SCN_MEM_READ
818 | GRUB_PE32_SCN_MEM_WRITE);
820 memset (&reloc_section, 0, sizeof (reloc_section));
821 strcpy (reloc_section.name, ".reloc");
822 reloc_section.virtual_size = grub_cpu_to_le32 (end_address - reloc_address);
823 reloc_section.virtual_address = grub_cpu_to_le32 (reloc_address);
824 reloc_section.raw_data_size = grub_cpu_to_le32 (end_address - reloc_address);
825 reloc_section.raw_data_offset = grub_cpu_to_le32 (reloc_address);
826 reloc_section.characteristics
827 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
828 | GRUB_PE32_SCN_MEM_DISCARDABLE
829 | GRUB_PE32_SCN_MEM_READ);
831 /* Write them out. */
832 if (fseeko (out, 0, SEEK_SET) < 0)
833 grub_util_error ("seek failed");
835 if (fwrite (&header, sizeof (header), 1, out) != 1
836 || fwrite (&text_section, sizeof (text_section), 1, out) != 1
837 || fwrite (&data_section, sizeof (data_section), 1, out) != 1
838 || fwrite (&mods_section, sizeof (mods_section), 1, out) != 1
839 || fwrite (&reloc_section, sizeof (reloc_section), 1, out) != 1)
840 grub_util_error ("write failed");
843 /* Convert an ELF relocatable object into an EFI Application (PE32). */
844 void
845 convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
847 char *kernel_image;
848 size_t kernel_size;
849 const char *strtab;
850 Elf32_Ehdr *e;
851 Elf32_Shdr *sections;
852 Elf32_Off section_offset;
853 Elf32_Half section_entsize;
854 Elf32_Half num_sections;
855 Elf32_Addr *section_addresses;
856 Elf32_Shdr *symtab_section;
857 Elf32_Addr start_address;
858 Elf32_Addr text_address, data_address, reloc_address, mods_address;
859 Elf32_Addr end_address;
861 /* Get the kernel image and check the format. */
862 kernel_image = read_kernel_module (dir, prefix, &kernel_size);
863 e = (Elf32_Ehdr *) kernel_image;
864 if (! check_elf_header (e, kernel_size))
865 grub_util_error ("invalid ELF header");
867 section_offset = grub_cpu_to_le32 (e->e_shoff);
868 section_entsize = grub_cpu_to_le16 (e->e_shentsize);
869 num_sections = grub_cpu_to_le16 (e->e_shnum);
870 if (kernel_size < section_offset + section_entsize * num_sections)
871 grub_util_error ("invalid ELF format");
873 sections = (Elf32_Shdr *) (kernel_image + section_offset);
874 strtab = find_strtab (e, sections, section_entsize);
876 /* Relocate sections then symbols in the virtual address space. */
877 section_addresses = locate_sections (sections, section_entsize,
878 num_sections, strtab);
880 symtab_section = find_symtab_section (sections,
881 section_entsize, num_sections);
882 if (! symtab_section)
883 grub_util_error ("no symbol table");
885 start_address = relocate_symbols (e, sections, symtab_section,
886 section_addresses, section_entsize,
887 num_sections);
888 if (start_address == 0)
889 grub_util_error ("start symbol is not defined");
891 /* Resolve addresses in the virtual address space. */
892 relocate_addresses (e, sections, section_addresses, section_entsize,
893 num_sections, strtab);
895 /* Generate a PE32 image file. The strategy is to dump binary data first,
896 then fill up the header. */
897 text_address = make_header_space (out);
898 data_address = write_text_sections (out, text_address, e, sections,
899 section_entsize, num_sections,
900 strtab);
901 mods_address = write_data_sections (out, data_address, e, sections,
902 section_entsize, num_sections,
903 strtab);
904 reloc_address = make_mods_section (out, mods_address, dir, mods);
905 end_address = make_reloc_section (out, reloc_address, e, section_addresses,
906 sections, section_entsize, num_sections,
907 strtab);
908 make_header (out, text_address, data_address, mods_address,
909 reloc_address, end_address, start_address);
911 /* Clean up. */
912 free (section_addresses);
913 free (kernel_image);
916 static struct option options[] =
918 {"directory", required_argument, 0, 'd'},
919 {"prefix", required_argument, 0, 'p'},
920 {"output", required_argument, 0, 'o'},
921 {"help", no_argument, 0, 'h'},
922 {"version", no_argument, 0, 'V'},
923 {"verbose", no_argument, 0, 'v'},
924 { 0, 0, 0, 0 }
927 static void
928 usage (int status)
930 if (status)
931 fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
932 else
933 printf ("\
934 Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
936 Make a bootable image of GRUB.\n\
938 -d, --directory=DIR use images and modules under DIR [default=%s]\n\
939 -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
940 -o, --output=FILE output a generated image to FILE\n\
941 -h, --help display this message and exit\n\
942 -V, --version print version information and exit\n\
943 -v, --verbose print verbose messages\n\
945 Report bugs to <%s>.\n\
946 ", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT);
948 exit (status);
952 main (int argc, char *argv[])
954 FILE *fp;
955 char *output = NULL;
956 char *dir = NULL;
957 char *prefix = NULL;
959 progname = "grub-mkimage";
961 while (1)
963 int c = getopt_long (argc, argv, "d:p:o:hVv", options, 0);
964 if (c == -1)
965 break;
967 switch (c)
969 case 'd':
970 if (dir)
971 free (dir);
972 dir = xstrdup (optarg);
973 break;
974 case 'h':
975 usage (0);
976 break;
977 case 'o':
978 if (output)
979 free (output);
980 output = xstrdup (optarg);
981 break;
982 case 'p':
983 if (prefix)
984 free (prefix);
985 prefix = xstrdup (optarg);
986 break;
987 case 'V':
988 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
989 return 0;
990 case 'v':
991 verbosity++;
992 break;
993 default:
994 usage (1);
995 break;
999 if (! output)
1000 usage (1);
1002 fp = fopen (output, "wb");
1003 if (! fp)
1004 grub_util_error ("cannot open %s", output);
1006 convert_elf (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, argv + optind);
1008 fclose (fp);
1010 return 0;