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/>.
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
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. */
91 read_kernel_module (const char *dir
, size_t *size
)
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
);
104 /* Return if the ELF header is valid. */
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
))))
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. */
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. */
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. */
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
158 locate_sections (Elf_Shdr
*sections
, Elf_Half section_entsize
,
159 Elf_Half num_sections
, const char *strtab
)
162 Elf_Addr current_address
;
163 Elf_Addr
*section_addresses
;
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 ();
172 for (i
= 0, s
= 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
);
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
);
192 for (i
= 0, s
= 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
);
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. */
214 find_symtab_section (Elf_Shdr
*sections
,
215 Elf_Half section_entsize
, Elf_Half num_sections
)
220 for (i
= 0, s
= sections
;
222 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
223 if (s
->sh_type
== grub_cpu_to_le32 (SHT_SYMTAB
))
229 /* Return the address of the string table. */
231 find_strtab (Elf_Ehdr
*e
, Elf_Shdr
*sections
, Elf_Half section_entsize
)
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
);
242 /* Relocate symbols; note that this function overwrites the symbol table.
243 Return the address of a start symbol. */
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;
254 Elf_Shdr
*strtab_section
;
258 = (Elf_Shdr
*) ((char *) sections
259 + (grub_le_to_cpu32 (symtab_section
->sh_link
)
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
);
270 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
275 name
= strtab
+ grub_le_to_cpu32 (sym
->st_name
);
277 index
= grub_le_to_cpu16 (sym
->st_shndx
);
278 if (index
== STN_ABS
)
282 else if ((index
== STN_UNDEF
))
285 grub_util_error ("undefined symbol %s", name
);
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
);
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. */
306 get_symbol_address (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Word i
)
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. */
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. */
328 relocate_addresses (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
329 Elf_Addr
*section_addresses
,
330 Elf_Half section_entsize
, Elf_Half num_sections
,
336 for (i
= 0, s
= 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
)))
343 Elf_Word rtab_size
, r_size
, num_rs
;
345 Elf_Shdr
*symtab_section
;
346 Elf_Word target_section_index
;
347 Elf_Addr target_section_addr
;
348 Elf_Shdr
*target_section
;
351 symtab_section
= (Elf_Shdr
*) ((char *) sections
352 + (grub_le_to_cpu32 (s
->sh_link
)
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
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
);
371 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
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
,
385 addend
= (s
->sh_type
== grub_cpu_to_le32 (SHT_RELA
)) ?
388 switch (ELF_R_TYPE (info
))
390 #if GRUB_TARGET_SIZEOF_VOID_P == 4
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",
403 /* This is relative. */
404 *target
= grub_cpu_to_le32 (grub_le_to_cpu32 (*target
)
406 - target_section_addr
- offset
);
407 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
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",
425 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
426 *t32
= grub_cpu_to_le64 (grub_le_to_cpu32 (*t32
)
428 - target_section_addr
- offset
);
429 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
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",
447 grub_util_error ("unknown relocation type %d",
456 write_padding (FILE *out
, size_t size
)
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. */
468 add_fixup_entry (struct grub_pe32_fixup_block
**block
, grub_uint16_t type
,
469 Elf_Addr addr
, int flush
, Elf_Addr current_address
,
472 struct grub_pe32_fixup_block
*b
= *block
;
474 /* First, check if it is necessary to write out the current block. */
477 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
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
;
489 next_address
= current_address
+ b
->block_size
;
490 padding_size
= ((align_pe32_section (next_address
)
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;
501 else if (b
->block_size
& (8 - 1))
503 /* If not aligned with a 32-bit boundary, add
507 grub_util_info ("adding a padding fixup entry");
508 index
= ((b
->block_size
- sizeof (*b
)) >> 1);
509 b
->entries
[index
] = 0;
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");
532 /* If not allocated yet, allocate a block with enough entries. */
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
);
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
);
554 return current_address
;
557 /* Write out zeros to make space for the header. */
559 make_header_space (FILE *out
)
563 addr
= get_starting_section_address ();
564 write_padding (out
, addr
);
569 /* Write text sections. */
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
,
580 for (i
= 0, s
= 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
);
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
);
622 /* Write data sections. */
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
,
633 for (i
= 0, s
= 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
);
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
);
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
);
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
;
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
;
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");
732 for (p
= path_list
; p
; )
734 struct grub_util_path_list
*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
);
754 /* Make a .reloc section. */
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
,
763 struct grub_pe32_fixup_block
*fixup_block
= 0;
765 for (i
= 0, s
= 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
)))
772 Elf_Word rtab_size
, r_size
, num_rs
;
774 Elf_Addr section_address
;
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
);
789 j
++, r
= (Elf_Rel
*) ((char *) r
+ r_size
))
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
)
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
,
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
)
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
,
832 current_address
= add_fixup_entry (&fixup_block
, 0, 0, 1,
833 current_address
, out
);
835 return current_address
;
838 /* Create the header. */
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
;
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
);
860 c
->machine
= grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64
);
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
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
);
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
);
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
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). */
962 convert_elf (const char *dir
, char *prefix
, FILE *out
, char *mods
[])
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
;
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
;
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
);
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
,
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
,
1035 mods_address
= write_data_sections (out
, data_address
, e
, sections
,
1036 section_entsize
, num_sections
,
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
,
1042 make_header (out
, text_address
, data_address
, mods_address
,
1043 reloc_address
, end_address
, start_address
);
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'},
1065 fprintf (stderr
, "Try ``grub-mkimage --help'' for more information.\n");
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
);
1086 main (int argc
, char *argv
[])
1089 char *output
= NULL
;
1091 char *prefix
= NULL
;
1093 progname
= "grub-mkimage";
1097 int c
= getopt_long (argc
, argv
, "d:p:o:hVv", options
, 0);
1106 dir
= xstrdup (optarg
);
1114 output
= xstrdup (optarg
);
1119 prefix
= xstrdup (optarg
);
1122 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME
, PACKAGE_VERSION
);
1136 fp
= fopen (output
, "wb");
1138 grub_util_error ("cannot open %s", output
);
1140 convert_elf (dir
? : GRUB_LIBDIR
, prefix
? : DEFAULT_DIRECTORY
, fp
, argv
+ optind
);