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/>.
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. */
51 read_kernel_module (const char *dir
, char *prefix
, size_t *size
)
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
);
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
);
68 /* Return if the ELF header is valid. */
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
))
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. */
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. */
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. */
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
120 locate_sections (Elf32_Shdr
*sections
, Elf32_Half section_entsize
,
121 Elf32_Half num_sections
, const char *strtab
)
124 Elf32_Addr current_address
;
125 Elf32_Addr
*section_addresses
;
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 ();
134 for (i
= 0, s
= 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
);
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
);
154 for (i
= 0, s
= 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
);
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. */
176 find_symtab_section (Elf32_Shdr
*sections
,
177 Elf32_Half section_entsize
, Elf32_Half num_sections
)
182 for (i
= 0, s
= sections
;
184 i
++, s
= (Elf32_Shdr
*) ((char *) s
+ section_entsize
))
185 if (s
->sh_type
== grub_cpu_to_le32 (SHT_SYMTAB
))
191 /* Return the address of the string table. */
193 find_strtab (Elf32_Ehdr
*e
, Elf32_Shdr
*sections
, Elf32_Half section_entsize
)
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
);
204 /* Relocate symbols; note that this function overwrites the symbol table.
205 Return the address of a start symbol. */
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;
216 Elf32_Shdr
*strtab_section
;
220 = (Elf32_Shdr
*) ((char *) sections
221 + (grub_le_to_cpu32 (symtab_section
->sh_link
)
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
);
232 i
++, sym
= (Elf32_Sym
*) ((char *) sym
+ sym_size
))
237 name
= strtab
+ grub_le_to_cpu32 (sym
->st_name
);
239 index
= grub_le_to_cpu16 (sym
->st_shndx
);
240 if (index
== STN_UNDEF
)
243 grub_util_error ("undefined symbol %s", name
);
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
);
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. */
264 get_symbol_address (Elf32_Ehdr
*e
, Elf32_Shdr
*s
, Elf32_Word i
)
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. */
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. */
286 relocate_addresses (Elf32_Ehdr
*e
, Elf32_Shdr
*sections
,
287 Elf32_Addr
*section_addresses
,
288 Elf32_Half section_entsize
, Elf32_Half num_sections
,
294 for (i
= 0, s
= sections
;
296 i
++, s
= (Elf32_Shdr
*) ((char *) s
+ section_entsize
))
297 if (s
->sh_type
== grub_cpu_to_le32 (SHT_REL
))
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
;
308 symtab_section
= (Elf32_Shdr
*) ((char *) sections
309 + (grub_le_to_cpu32 (s
->sh_link
)
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
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
);
328 j
++, r
= (Elf32_Rel
*) ((char *) r
+ r_size
))
335 offset
= grub_le_to_cpu32 (r
->r_offset
);
336 target
= (Elf32_Addr
*) get_target_address (e
, target_section
,
338 info
= grub_le_to_cpu32 (r
->r_info
);
339 sym_addr
= get_symbol_address (e
, symtab_section
,
342 switch (ELF32_R_TYPE (info
))
348 /* This is absolute. */
349 *target
= grub_cpu_to_le32 (grub_le_to_cpu32 (*target
)
351 grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
356 /* This is relative. */
357 *target
= grub_cpu_to_le32 (grub_le_to_cpu32 (*target
)
359 - target_section_addr
- offset
);
360 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
365 grub_util_error ("unknown relocation type %d",
366 ELF32_R_TYPE (info
));
374 write_padding (FILE *out
, size_t size
)
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. */
386 add_fixup_entry (struct grub_pe32_fixup_block
**block
, grub_uint16_t type
,
387 Elf32_Addr addr
, int flush
, Elf32_Addr current_address
,
390 struct grub_pe32_fixup_block
*b
= *block
;
392 /* First, check if it is necessary to write out the current block. */
395 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
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
;
407 next_address
= current_address
+ b
->block_size
;
408 padding_size
= ((align_pe32_section (next_address
)
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;
419 else if (b
->block_size
& (8 - 1))
421 /* If not aligned with a 32-bit boundary, add
425 grub_util_info ("adding a padding fixup entry");
426 index
= ((b
->block_size
- sizeof (*b
)) >> 1);
427 b
->entries
[index
] = 0;
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");
450 /* If not allocated yet, allocate a block with enough entries. */
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
);
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
);
472 return current_address
;
475 /* Write out zeros to make space for the header. */
477 make_header_space (FILE *out
)
481 addr
= get_starting_section_address ();
482 write_padding (out
, addr
);
487 /* Write text sections. */
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
,
498 for (i
= 0, s
= 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
);
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
);
540 /* Write data sections. */
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
,
551 for (i
= 0, s
= 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
);
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
);
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
);
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
;
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
;
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");
646 for (p
= path_list
; p
; )
648 struct grub_util_path_list
*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
);
668 /* Make a .reloc section. */
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
,
677 struct grub_pe32_fixup_block
*fixup_block
= 0;
679 for (i
= 0, s
= sections
;
681 i
++, s
= (Elf32_Shdr
*) ((char *) s
+ section_entsize
))
682 if (s
->sh_type
== grub_cpu_to_le32 (SHT_REL
))
685 Elf32_Word rtab_size
, r_size
, num_rs
;
686 Elf32_Off rtab_offset
;
687 Elf32_Addr section_address
;
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
);
702 j
++, r
= (Elf32_Rel
*) ((char *) r
+ r_size
))
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
)
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
,
725 current_address
= add_fixup_entry (&fixup_block
, 0, 0, 1,
726 current_address
, out
);
728 return current_address
;
731 /* Create the header. */
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
;
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
);
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
);
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
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). */
845 convert_elf (const char *dir
, char *prefix
, FILE *out
, char *mods
[])
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
,
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
,
901 mods_address
= write_data_sections (out
, data_address
, e
, sections
,
902 section_entsize
, num_sections
,
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
,
908 make_header (out
, text_address
, data_address
, mods_address
,
909 reloc_address
, end_address
, start_address
);
912 free (section_addresses
);
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'},
931 fprintf (stderr
, "Try ``grub-mkimage --help'' for more information.\n");
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
);
952 main (int argc
, char *argv
[])
959 progname
= "grub-mkimage";
963 int c
= getopt_long (argc
, argv
, "d:p:o:hVv", options
, 0);
972 dir
= xstrdup (optarg
);
980 output
= xstrdup (optarg
);
985 prefix
= xstrdup (optarg
);
988 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME
, PACKAGE_VERSION
);
1002 fp
= fopen (output
, "wb");
1004 grub_util_error ("cannot open %s", output
);
1006 convert_elf (dir
? : GRUB_LIBDIR
, prefix
? : DEFAULT_DIRECTORY
, fp
, argv
+ optind
);