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 #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
, char *prefix
, 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
);
101 if (GRUB_KERNEL_MACHINE_PREFIX
+ strlen (prefix
) + 1 > GRUB_KERNEL_MACHINE_DATA_END
)
102 grub_util_error ("prefix too long");
104 strcpy (kernel_image
+ sizeof (Elf_Ehdr
) + GRUB_KERNEL_MACHINE_PREFIX
, prefix
);
109 /* Return if the ELF header is valid. */
111 check_elf_header (Elf_Ehdr
*e
, size_t size
)
113 if (size
< sizeof (*e
)
114 || e
->e_ident
[EI_MAG0
] != ELFMAG0
115 || e
->e_ident
[EI_MAG1
] != ELFMAG1
116 || e
->e_ident
[EI_MAG2
] != ELFMAG2
117 || e
->e_ident
[EI_MAG3
] != ELFMAG3
118 || e
->e_ident
[EI_VERSION
] != EV_CURRENT
119 || e
->e_version
!= grub_cpu_to_le32 (EV_CURRENT
)
120 || ((e
->e_ident
[EI_CLASS
] != ELFCLASS32
) &&
121 (e
->e_ident
[EI_CLASS
] != ELFCLASS64
))
122 || e
->e_ident
[EI_DATA
] != ELFDATA2LSB
123 || ((e
->e_machine
!= grub_cpu_to_le16 (EM_386
)) &&
124 (e
->e_machine
!= grub_cpu_to_le16 (EM_X86_64
))))
130 /* Return the starting address right after the header,
131 aligned by the section alignment. Allocate 4 section tables for
132 .text, .data, .reloc, and mods. */
134 get_starting_section_address (void)
136 return align_pe32_section (sizeof (struct grub_pe32_header
)
137 + 4 * sizeof (struct grub_pe32_section_table
));
140 /* Determine if this section is a text section. Return false if this
141 section is not allocated. */
143 is_text_section (Elf_Shdr
*s
)
145 return ((s
->sh_flags
& grub_cpu_to_le32 (SHF_EXECINSTR
| SHF_ALLOC
))
146 == grub_cpu_to_le32 (SHF_EXECINSTR
| SHF_ALLOC
));
149 /* Determine if this section is a data section. This assumes that
150 BSS is also a data section, since the converter initializes BSS
151 when producing PE32 to avoid a bug in EFI implementations. */
153 is_data_section (Elf_Shdr
*s
)
155 return (s
->sh_flags
& grub_cpu_to_le32 (SHF_ALLOC
)
156 && ! (s
->sh_flags
& grub_cpu_to_le32 (SHF_EXECINSTR
)));
159 /* Locate section addresses by merging code sections and data sections
160 into .text and .data, respectively. Return the array of section
163 locate_sections (Elf_Shdr
*sections
, Elf_Half section_entsize
,
164 Elf_Half num_sections
, const char *strtab
)
167 Elf_Addr current_address
;
168 Elf_Addr
*section_addresses
;
171 section_addresses
= xmalloc (sizeof (*section_addresses
) * num_sections
);
172 memset (section_addresses
, 0, sizeof (*section_addresses
) * num_sections
);
174 current_address
= get_starting_section_address ();
177 for (i
= 0, s
= sections
;
179 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
180 if (is_text_section (s
))
182 Elf_Word align
= grub_le_to_cpu32 (s
->sh_addralign
);
183 const char *name
= strtab
+ grub_le_to_cpu32 (s
->sh_name
);
186 current_address
= align_address (current_address
, align
);
188 grub_util_info ("locating the section %s at 0x%x",
189 name
, current_address
);
190 section_addresses
[i
] = current_address
;
191 current_address
+= grub_le_to_cpu32 (s
->sh_size
);
194 current_address
= align_pe32_section (current_address
);
197 for (i
= 0, s
= sections
;
199 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
200 if (is_data_section (s
))
202 Elf_Word align
= grub_le_to_cpu32 (s
->sh_addralign
);
203 const char *name
= strtab
+ grub_le_to_cpu32 (s
->sh_name
);
206 current_address
= align_address (current_address
, align
);
208 grub_util_info ("locating the section %s at 0x%x",
209 name
, current_address
);
210 section_addresses
[i
] = current_address
;
211 current_address
+= grub_le_to_cpu32 (s
->sh_size
);
214 return section_addresses
;
217 /* Return the symbol table section, if any. */
219 find_symtab_section (Elf_Shdr
*sections
,
220 Elf_Half section_entsize
, Elf_Half num_sections
)
225 for (i
= 0, s
= sections
;
227 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
228 if (s
->sh_type
== grub_cpu_to_le32 (SHT_SYMTAB
))
234 /* Return the address of the string table. */
236 find_strtab (Elf_Ehdr
*e
, Elf_Shdr
*sections
, Elf_Half section_entsize
)
241 s
= (Elf_Shdr
*) ((char *) sections
242 + grub_le_to_cpu16 (e
->e_shstrndx
) * section_entsize
);
243 strtab
= (char *) e
+ grub_le_to_cpu32 (s
->sh_offset
);
247 /* Relocate symbols; note that this function overwrites the symbol table.
248 Return the address of a start symbol. */
250 relocate_symbols (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
251 Elf_Shdr
*symtab_section
, Elf_Addr
*section_addresses
,
252 Elf_Half section_entsize
, Elf_Half num_sections
)
254 Elf_Word symtab_size
, sym_size
, num_syms
;
255 Elf_Off symtab_offset
;
256 Elf_Addr start_address
= 0;
259 Elf_Shdr
*strtab_section
;
263 = (Elf_Shdr
*) ((char *) sections
264 + (grub_le_to_cpu32 (symtab_section
->sh_link
)
266 strtab
= (char *) e
+ grub_le_to_cpu32 (strtab_section
->sh_offset
);
268 symtab_size
= grub_le_to_cpu32 (symtab_section
->sh_size
);
269 sym_size
= grub_le_to_cpu32 (symtab_section
->sh_entsize
);
270 symtab_offset
= grub_le_to_cpu32 (symtab_section
->sh_offset
);
271 num_syms
= symtab_size
/ sym_size
;
273 for (i
= 0, sym
= (Elf_Sym
*) ((char *) e
+ symtab_offset
);
275 i
++, sym
= (Elf_Sym
*) ((char *) sym
+ sym_size
))
280 name
= strtab
+ grub_le_to_cpu32 (sym
->st_name
);
282 index
= grub_le_to_cpu16 (sym
->st_shndx
);
283 if (index
== STN_ABS
)
287 else if ((index
== STN_UNDEF
))
290 grub_util_error ("undefined symbol %s", name
);
294 else if (index
>= num_sections
)
295 grub_util_error ("section %d does not exist", index
);
297 sym
->st_value
= (grub_le_to_cpu32 (sym
->st_value
)
298 + section_addresses
[index
]);
299 grub_util_info ("locating %s at 0x%x", name
, sym
->st_value
);
302 if (strcmp (name
, "_start") == 0 || strcmp (name
, "start") == 0)
303 start_address
= sym
->st_value
;
306 return start_address
;
309 /* Return the address of a symbol at the index I in the section S. */
311 get_symbol_address (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Word i
)
315 sym
= (Elf_Sym
*) ((char *) e
316 + grub_le_to_cpu32 (s
->sh_offset
)
317 + i
* grub_le_to_cpu32 (s
->sh_entsize
));
318 return sym
->st_value
;
321 /* Return the address of a modified value. */
323 get_target_address (Elf_Ehdr
*e
, Elf_Shdr
*s
, Elf_Addr offset
)
325 return (Elf_Addr
*) ((char *) e
+ grub_le_to_cpu32 (s
->sh_offset
) + offset
);
328 /* Deal with relocation information. This function relocates addresses
329 within the virtual address space starting from 0. So only relative
330 addresses can be fully resolved. Absolute addresses must be relocated
331 again by a PE32 relocator when loaded. */
333 relocate_addresses (Elf_Ehdr
*e
, Elf_Shdr
*sections
,
334 Elf_Addr
*section_addresses
,
335 Elf_Half section_entsize
, Elf_Half num_sections
,
341 for (i
= 0, s
= sections
;
343 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
344 if ((s
->sh_type
== grub_cpu_to_le32 (SHT_REL
)) ||
345 (s
->sh_type
== grub_cpu_to_le32 (SHT_RELA
)))
348 Elf_Word rtab_size
, r_size
, num_rs
;
350 Elf_Shdr
*symtab_section
;
351 Elf_Word target_section_index
;
352 Elf_Addr target_section_addr
;
353 Elf_Shdr
*target_section
;
356 symtab_section
= (Elf_Shdr
*) ((char *) sections
357 + (grub_le_to_cpu32 (s
->sh_link
)
359 target_section_index
= grub_le_to_cpu32 (s
->sh_info
);
360 target_section_addr
= section_addresses
[target_section_index
];
361 target_section
= (Elf_Shdr
*) ((char *) sections
362 + (target_section_index
365 grub_util_info ("dealing with the relocation section %s for %s",
366 strtab
+ grub_le_to_cpu32 (s
->sh_name
),
367 strtab
+ grub_le_to_cpu32 (target_section
->sh_name
));
369 rtab_size
= grub_le_to_cpu32 (s
->sh_size
);
370 r_size
= grub_le_to_cpu32 (s
->sh_entsize
);
371 rtab_offset
= grub_le_to_cpu32 (s
->sh_offset
);
372 num_rs
= rtab_size
/ r_size
;
374 for (j
= 0, r
= (Elf_Rela
*) ((char *) e
+ rtab_offset
);
376 j
++, r
= (Elf_Rela
*) ((char *) r
+ r_size
))
381 Elf_Addr
*target
, *value
;
383 offset
= grub_le_to_cpu (r
->r_offset
);
384 target
= get_target_address (e
, target_section
, offset
);
385 info
= grub_le_to_cpu (r
->r_info
);
386 sym_addr
= get_symbol_address (e
, symtab_section
,
389 value
= (s
->sh_type
== grub_cpu_to_le32 (SHT_RELA
)) ?
390 (Elf_Addr
*) &r
->r_addend
: target
;
392 switch (ELF_R_TYPE (info
))
394 #if GRUB_TARGET_SIZEOF_VOID_P == 4
399 /* This is absolute. */
400 *target
= grub_cpu_to_le32 (grub_le_to_cpu32 (*value
)
402 grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
407 /* This is relative. */
408 *target
= grub_cpu_to_le32 (grub_le_to_cpu32 (*value
)
410 - target_section_addr
- offset
);
411 grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
421 *target
= grub_cpu_to_le64 (grub_le_to_cpu64 (*value
) + sym_addr
);
422 grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
428 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
429 *t32
= grub_cpu_to_le64 (grub_le_to_cpu64 (*value
)
431 - target_section_addr
- offset
);
432 grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
440 grub_uint32_t
*t32
= (grub_uint32_t
*) target
;
441 *t32
= grub_cpu_to_le64 (grub_le_to_cpu64 (*value
)
443 grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
450 grub_util_error ("unknown relocation type %d",
459 write_padding (FILE *out
, size_t size
)
463 for (i
= 0; i
< size
; i
++)
464 if (fputc (0, out
) == EOF
)
465 grub_util_error ("padding failed");
468 /* Add a PE32's fixup entry for a relocation. Return the resulting address
469 after having written to the file OUT. */
471 add_fixup_entry (struct grub_pe32_fixup_block
**block
, grub_uint16_t type
,
472 Elf_Addr addr
, int flush
, Elf_Addr current_address
,
475 struct grub_pe32_fixup_block
*b
= *block
;
477 /* First, check if it is necessary to write out the current block. */
480 if (flush
|| addr
< b
->page_rva
|| b
->page_rva
+ 0x1000 <= addr
)
486 /* Add as much padding as necessary to align the address
487 with a section boundary. */
488 Elf_Addr next_address
;
489 unsigned padding_size
;
492 next_address
= current_address
+ b
->block_size
;
493 padding_size
= ((align_pe32_section (next_address
)
496 index
= ((b
->block_size
- sizeof (*b
)) >> 1);
497 grub_util_info ("adding %d padding fixup entries", padding_size
);
498 while (padding_size
--)
500 b
->entries
[index
++] = 0;
504 else if (b
->block_size
& (8 - 1))
506 /* If not aligned with a 32-bit boundary, add
510 grub_util_info ("adding a padding fixup entry");
511 index
= ((b
->block_size
- sizeof (*b
)) >> 1);
512 b
->entries
[index
] = 0;
517 grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
518 b
->block_size
, b
->page_rva
);
519 size
= b
->block_size
;
520 current_address
+= size
;
521 b
->page_rva
= grub_cpu_to_le32 (b
->page_rva
);
522 b
->block_size
= grub_cpu_to_le32 (b
->block_size
);
523 if (fwrite (b
, size
, 1, out
) != 1)
524 grub_util_error ("write failed");
535 /* If not allocated yet, allocate a block with enough entries. */
538 *block
= b
= xmalloc (sizeof (*b
) + 2 * 0x1000);
540 /* The spec does not mention the requirement of a Page RVA.
541 Here, align the address with a 4K boundary for safety. */
542 b
->page_rva
= (addr
& ~(0x1000 - 1));
543 b
->block_size
= sizeof (*b
);
547 if (b
->block_size
>= sizeof (*b
) + 2 * 0x1000)
548 grub_util_error ("too many fixup entries");
550 /* Add a new entry. */
551 index
= ((b
->block_size
- sizeof (*b
)) >> 1);
552 entry
= GRUB_PE32_FIXUP_ENTRY (type
, addr
- b
->page_rva
);
553 b
->entries
[index
] = grub_cpu_to_le16 (entry
);
557 return current_address
;
560 /* Write out zeros to make space for the header. */
562 make_header_space (FILE *out
)
566 addr
= get_starting_section_address ();
567 write_padding (out
, addr
);
572 /* Write text sections. */
574 write_text_sections (FILE *out
, Elf_Addr current_address
,
575 Elf_Ehdr
*e
, Elf_Shdr
*sections
,
576 Elf_Half section_entsize
, Elf_Half num_sections
,
583 for (i
= 0, s
= sections
;
585 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
586 if (is_text_section (s
))
588 Elf_Word align
= grub_le_to_cpu32 (s
->sh_addralign
);
589 Elf_Off offset
= grub_le_to_cpu32 (s
->sh_offset
);
590 Elf_Word size
= grub_le_to_cpu32 (s
->sh_size
);
591 const char *name
= strtab
+ grub_le_to_cpu32 (s
->sh_name
);
595 addr
= align_address (current_address
, align
);
596 if (current_address
!= addr
)
598 grub_util_info ("padding %d bytes for the ELF section alignment",
599 addr
- current_address
);
600 write_padding (out
, addr
- current_address
);
601 current_address
= addr
;
605 grub_util_info ("writing the text section %s at 0x%x",
606 name
, current_address
);
608 if (fwrite ((char *) e
+ offset
, size
, 1, out
) != 1)
609 grub_util_error ("write failed");
611 current_address
+= size
;
614 addr
= align_pe32_section (current_address
);
615 if (addr
!= current_address
)
617 grub_util_info ("padding %d bytes for the PE32 section alignment",
618 addr
- current_address
);
619 write_padding (out
, addr
- current_address
);
625 /* Write data sections. */
627 write_data_sections (FILE *out
, Elf_Addr current_address
,
628 Elf_Ehdr
*e
, Elf_Shdr
*sections
,
629 Elf_Half section_entsize
, Elf_Half num_sections
,
636 for (i
= 0, s
= sections
;
638 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
639 if (is_data_section (s
))
641 Elf_Word align
= grub_le_to_cpu32 (s
->sh_addralign
);
642 Elf_Off offset
= grub_le_to_cpu32 (s
->sh_offset
);
643 Elf_Word size
= grub_le_to_cpu32 (s
->sh_size
);
644 const char *name
= strtab
+ grub_le_to_cpu32 (s
->sh_name
);
648 addr
= align_address (current_address
, align
);
649 if (current_address
!= addr
)
651 grub_util_info ("padding %d bytes for the ELF section alignment",
652 addr
- current_address
);
653 write_padding (out
, addr
- current_address
);
654 current_address
= addr
;
658 grub_util_info ("writing the data section %s at 0x%x",
659 name
, current_address
);
661 if (s
->sh_type
== grub_cpu_to_le32 (SHT_NOBITS
))
662 write_padding (out
, size
);
664 if (fwrite ((char *) e
+ offset
, size
, 1, out
) != 1)
665 grub_util_error ("write failed");
667 current_address
+= size
;
670 addr
= align_pe32_section (current_address
);
671 if (addr
!= current_address
)
673 grub_util_info ("padding %d bytes for the PE32 section alignment",
674 addr
- current_address
);
675 write_padding (out
, addr
- current_address
);
683 make_mods_section (FILE *out
, Elf_Addr current_address
,
684 const char *dir
, char *mods
[])
686 struct grub_util_path_list
*path_list
;
687 grub_size_t total_module_size
;
688 struct grub_util_path_list
*p
;
689 struct grub_module_info modinfo
;
692 path_list
= grub_util_resolve_dependencies (dir
, "moddep.lst", mods
);
694 total_module_size
= sizeof (struct grub_module_info
);
695 for (p
= path_list
; p
; p
= p
->next
)
697 total_module_size
+= (grub_util_get_image_size (p
->name
)
698 + sizeof (struct grub_module_header
));
701 grub_util_info ("the total module size is 0x%x", total_module_size
);
703 modinfo
.magic
= grub_cpu_to_le32 (GRUB_MODULE_MAGIC
);
704 modinfo
.offset
= grub_cpu_to_le32 (sizeof (modinfo
));
705 modinfo
.size
= grub_cpu_to_le32 (total_module_size
);
707 if (fwrite (&modinfo
, sizeof (modinfo
), 1, out
) != 1)
708 grub_util_error ("write failed");
710 for (p
= path_list
; p
; p
= p
->next
)
712 struct grub_module_header header
;
716 grub_util_info ("adding module %s", p
->name
);
718 mod_size
= grub_util_get_image_size (p
->name
);
719 header
.type
= grub_cpu_to_le32 (OBJ_TYPE_ELF
);
720 header
.size
= grub_cpu_to_le32 (mod_size
+ sizeof (header
));
722 mod_image
= grub_util_read_image (p
->name
);
724 if (fwrite (&header
, sizeof (header
), 1, out
) != 1
725 || fwrite (mod_image
, mod_size
, 1, out
) != 1)
726 grub_util_error ("write failed");
731 for (p
= path_list
; p
; )
733 struct grub_util_path_list
*q
;
740 current_address
+= total_module_size
;
742 addr
= align_pe32_section (current_address
);
743 if (addr
!= current_address
)
745 grub_util_info ("padding %d bytes for the PE32 section alignment",
746 addr
- current_address
);
747 write_padding (out
, addr
- current_address
);
753 /* Make a .reloc section. */
755 make_reloc_section (FILE *out
, Elf_Addr current_address
, Elf_Ehdr
*e
,
756 Elf_Addr
*section_addresses
, Elf_Shdr
*sections
,
757 Elf_Half section_entsize
, Elf_Half num_sections
,
762 struct grub_pe32_fixup_block
*fixup_block
= 0;
764 for (i
= 0, s
= sections
;
766 i
++, s
= (Elf_Shdr
*) ((char *) s
+ section_entsize
))
767 if ((s
->sh_type
== grub_cpu_to_le32 (SHT_REL
)) ||
768 (s
->sh_type
== grub_cpu_to_le32 (SHT_RELA
)))
771 Elf_Word rtab_size
, r_size
, num_rs
;
773 Elf_Addr section_address
;
776 grub_util_info ("translating the relocation section %s",
777 strtab
+ grub_le_to_cpu32 (s
->sh_name
));
779 rtab_size
= grub_le_to_cpu32 (s
->sh_size
);
780 r_size
= grub_le_to_cpu32 (s
->sh_entsize
);
781 rtab_offset
= grub_le_to_cpu32 (s
->sh_offset
);
782 num_rs
= rtab_size
/ r_size
;
784 section_address
= section_addresses
[grub_le_to_cpu32 (s
->sh_info
)];
786 for (j
= 0, r
= (Elf_Rel
*) ((char *) e
+ rtab_offset
);
788 j
++, r
= (Elf_Rel
*) ((char *) r
+ r_size
))
793 offset
= grub_le_to_cpu32 (r
->r_offset
);
794 info
= grub_le_to_cpu32 (r
->r_info
);
796 /* Necessary to relocate only absolute addresses. */
797 #if GRUB_TARGET_SIZEOF_VOID_P == 4
798 if (ELF_R_TYPE (info
) == R_386_32
)
802 addr
= section_address
+ offset
;
803 grub_util_info ("adding a relocation entry for 0x%x", addr
);
804 current_address
= add_fixup_entry (&fixup_block
,
805 GRUB_PE32_REL_BASED_HIGHLOW
,
806 addr
, 0, current_address
,
810 if ((ELF_R_TYPE (info
) == R_X86_64_64
) ||
811 (ELF_R_TYPE (info
) == R_X86_64_32
) ||
812 (ELF_R_TYPE (info
) == R_X86_64_32S
))
816 addr
= section_address
+ offset
;
817 grub_util_info ("adding a relocation entry for 0x%llx", addr
);
818 current_address
= add_fixup_entry (&fixup_block
,
819 GRUB_PE32_REL_BASED_HIGHLOW
,
820 addr
, 0, current_address
,
827 current_address
= add_fixup_entry (&fixup_block
, 0, 0, 1,
828 current_address
, out
);
830 return current_address
;
833 /* Create the header. */
835 make_header (FILE *out
, Elf_Addr text_address
, Elf_Addr data_address
,
836 Elf_Addr mods_address
, Elf_Addr reloc_address
,
837 Elf_Addr end_address
, Elf_Addr start_address
)
839 struct grub_pe32_header header
;
840 struct grub_pe32_coff_header
*c
;
841 struct grub_pe32_optional_header
*o
;
842 struct grub_pe32_section_table text_section
, data_section
;
843 struct grub_pe32_section_table mods_section
, reloc_section
;
846 memset (&header
, 0, sizeof (header
));
847 memcpy (header
.msdos_stub
, stub
, sizeof (header
.msdos_stub
));
848 memcpy (header
.signature
, "PE\0\0", sizeof (header
.signature
));
850 /* The COFF file header. */
851 c
= &header
.coff_header
;
852 #if GRUB_TARGET_SIZEOF_VOID_P == 4
853 c
->machine
= grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386
);
855 c
->machine
= grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64
);
858 c
->num_sections
= grub_cpu_to_le16 (4);
859 c
->time
= grub_cpu_to_le32 (time (0));
860 c
->optional_header_size
= grub_cpu_to_le16 (sizeof (header
.optional_header
));
861 c
->characteristics
= grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
862 | GRUB_PE32_LINE_NUMS_STRIPPED
863 #if GRUB_TARGET_SIZEOF_VOID_P == 4
864 | GRUB_PE32_32BIT_MACHINE
866 | GRUB_PE32_LOCAL_SYMS_STRIPPED
867 | GRUB_PE32_DEBUG_STRIPPED
);
869 /* The PE Optional header. */
870 o
= &header
.optional_header
;
871 o
->magic
= grub_cpu_to_le16 (GRUB_PE32_PE32_MAGIC
);
872 o
->code_size
= grub_cpu_to_le32 (data_address
- text_address
);
873 o
->data_size
= grub_cpu_to_le32 (reloc_address
- data_address
);
875 o
->entry_addr
= grub_cpu_to_le32 (start_address
);
876 o
->code_base
= grub_cpu_to_le32 (text_address
);
877 #if GRUB_TARGET_SIZEOF_VOID_P == 4
878 o
->data_base
= grub_cpu_to_le32 (data_address
);
881 o
->section_alignment
= grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT
);
882 o
->file_alignment
= grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT
);
883 o
->image_size
= grub_cpu_to_le32 (end_address
);
884 o
->header_size
= grub_cpu_to_le32 (text_address
);
885 o
->subsystem
= grub_cpu_to_le16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION
);
887 /* Do these really matter? */
888 o
->stack_reserve_size
= grub_cpu_to_le32 (0x10000);
889 o
->stack_commit_size
= grub_cpu_to_le32 (0x10000);
890 o
->heap_reserve_size
= grub_cpu_to_le32 (0x10000);
891 o
->heap_commit_size
= grub_cpu_to_le32 (0x10000);
893 o
->num_data_directories
= grub_cpu_to_le32 (GRUB_PE32_NUM_DATA_DIRECTORIES
);
895 o
->base_relocation_table
.rva
= grub_cpu_to_le32 (reloc_address
);
896 o
->base_relocation_table
.size
= grub_cpu_to_le32 (end_address
900 memset (&text_section
, 0, sizeof (text_section
));
901 strcpy (text_section
.name
, ".text");
902 text_section
.virtual_size
= grub_cpu_to_le32 (data_address
- text_address
);
903 text_section
.virtual_address
= grub_cpu_to_le32 (text_address
);
904 text_section
.raw_data_size
= grub_cpu_to_le32 (data_address
- text_address
);
905 text_section
.raw_data_offset
= grub_cpu_to_le32 (text_address
);
906 text_section
.characteristics
= grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_CODE
907 | GRUB_PE32_SCN_MEM_EXECUTE
908 | GRUB_PE32_SCN_MEM_READ
);
910 memset (&data_section
, 0, sizeof (data_section
));
911 strcpy (data_section
.name
, ".data");
912 data_section
.virtual_size
= grub_cpu_to_le32 (mods_address
- data_address
);
913 data_section
.virtual_address
= grub_cpu_to_le32 (data_address
);
914 data_section
.raw_data_size
= grub_cpu_to_le32 (mods_address
- data_address
);
915 data_section
.raw_data_offset
= grub_cpu_to_le32 (data_address
);
916 data_section
.characteristics
917 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
918 | GRUB_PE32_SCN_MEM_READ
919 | GRUB_PE32_SCN_MEM_WRITE
);
921 memset (&mods_section
, 0, sizeof (mods_section
));
922 strcpy (mods_section
.name
, "mods");
923 mods_section
.virtual_size
= grub_cpu_to_le32 (reloc_address
- mods_address
);
924 mods_section
.virtual_address
= grub_cpu_to_le32 (mods_address
);
925 mods_section
.raw_data_size
= grub_cpu_to_le32 (reloc_address
- mods_address
);
926 mods_section
.raw_data_offset
= grub_cpu_to_le32 (mods_address
);
927 mods_section
.characteristics
928 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
929 | GRUB_PE32_SCN_MEM_READ
930 | GRUB_PE32_SCN_MEM_WRITE
);
932 memset (&reloc_section
, 0, sizeof (reloc_section
));
933 strcpy (reloc_section
.name
, ".reloc");
934 reloc_section
.virtual_size
= grub_cpu_to_le32 (end_address
- reloc_address
);
935 reloc_section
.virtual_address
= grub_cpu_to_le32 (reloc_address
);
936 reloc_section
.raw_data_size
= grub_cpu_to_le32 (end_address
- reloc_address
);
937 reloc_section
.raw_data_offset
= grub_cpu_to_le32 (reloc_address
);
938 reloc_section
.characteristics
939 = grub_cpu_to_le32 (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
940 | GRUB_PE32_SCN_MEM_DISCARDABLE
941 | GRUB_PE32_SCN_MEM_READ
);
943 /* Write them out. */
944 if (fseeko (out
, 0, SEEK_SET
) < 0)
945 grub_util_error ("seek failed");
947 if (fwrite (&header
, sizeof (header
), 1, out
) != 1
948 || fwrite (&text_section
, sizeof (text_section
), 1, out
) != 1
949 || fwrite (&data_section
, sizeof (data_section
), 1, out
) != 1
950 || fwrite (&mods_section
, sizeof (mods_section
), 1, out
) != 1
951 || fwrite (&reloc_section
, sizeof (reloc_section
), 1, out
) != 1)
952 grub_util_error ("write failed");
955 /* Convert an ELF relocatable object into an EFI Application (PE32). */
957 convert_elf (const char *dir
, char *prefix
, FILE *out
, char *mods
[])
964 Elf_Off section_offset
;
965 Elf_Half section_entsize
;
966 Elf_Half num_sections
;
967 Elf_Addr
*section_addresses
;
968 Elf_Shdr
*symtab_section
;
969 Elf_Addr start_address
;
970 Elf_Addr text_address
, data_address
, reloc_address
, mods_address
;
971 Elf_Addr end_address
;
973 /* Get the kernel image and check the format. */
974 kernel_image
= read_kernel_module (dir
, prefix
, &kernel_size
);
975 e
= (Elf_Ehdr
*) kernel_image
;
976 if (! check_elf_header (e
, kernel_size
))
977 grub_util_error ("invalid ELF header");
979 section_offset
= grub_cpu_to_le32 (e
->e_shoff
);
980 section_entsize
= grub_cpu_to_le16 (e
->e_shentsize
);
981 num_sections
= grub_cpu_to_le16 (e
->e_shnum
);
983 if (kernel_size
< section_offset
+ section_entsize
* num_sections
)
984 grub_util_error ("invalid ELF format");
986 sections
= (Elf_Shdr
*) (kernel_image
+ section_offset
);
987 strtab
= find_strtab (e
, sections
, section_entsize
);
989 /* Relocate sections then symbols in the virtual address space. */
990 section_addresses
= locate_sections (sections
, section_entsize
,
991 num_sections
, strtab
);
993 symtab_section
= find_symtab_section (sections
,
994 section_entsize
, num_sections
);
995 if (! symtab_section
)
996 grub_util_error ("no symbol table");
998 start_address
= relocate_symbols (e
, sections
, symtab_section
,
999 section_addresses
, section_entsize
,
1001 if (start_address
== 0)
1002 grub_util_error ("start symbol is not defined");
1004 /* Resolve addresses in the virtual address space. */
1005 relocate_addresses (e
, sections
, section_addresses
, section_entsize
,
1006 num_sections
, strtab
);
1008 /* Generate a PE32 image file. The strategy is to dump binary data first,
1009 then fill up the header. */
1010 text_address
= make_header_space (out
);
1011 data_address
= write_text_sections (out
, text_address
, e
, sections
,
1012 section_entsize
, num_sections
,
1014 mods_address
= write_data_sections (out
, data_address
, e
, sections
,
1015 section_entsize
, num_sections
,
1017 reloc_address
= make_mods_section (out
, mods_address
, dir
, mods
);
1018 end_address
= make_reloc_section (out
, reloc_address
, e
, section_addresses
,
1019 sections
, section_entsize
, num_sections
,
1021 make_header (out
, text_address
, data_address
, mods_address
,
1022 reloc_address
, end_address
, start_address
);
1025 free (section_addresses
);
1026 free (kernel_image
);
1029 static struct option options
[] =
1031 {"directory", required_argument
, 0, 'd'},
1032 {"prefix", required_argument
, 0, 'p'},
1033 {"output", required_argument
, 0, 'o'},
1034 {"help", no_argument
, 0, 'h'},
1035 {"version", no_argument
, 0, 'V'},
1036 {"verbose", no_argument
, 0, 'v'},
1044 fprintf (stderr
, "Try ``grub-mkimage --help'' for more information.\n");
1047 Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
1049 Make a bootable image of GRUB.\n\
1051 -d, --directory=DIR use images and modules under DIR [default=%s]\n\
1052 -p, --prefix=DIR set grub_prefix directory [default=%s]\n\
1053 -o, --output=FILE output a generated image to FILE\n\
1054 -h, --help display this message and exit\n\
1055 -V, --version print version information and exit\n\
1056 -v, --verbose print verbose messages\n\
1058 Report bugs to <%s>.\n\
1059 ", GRUB_LIBDIR
, DEFAULT_DIRECTORY
, PACKAGE_BUGREPORT
);
1065 main (int argc
, char *argv
[])
1068 char *output
= NULL
;
1070 char *prefix
= NULL
;
1072 progname
= "grub-mkimage";
1076 int c
= getopt_long (argc
, argv
, "d:p:o:hVv", options
, 0);
1085 dir
= xstrdup (optarg
);
1093 output
= xstrdup (optarg
);
1098 prefix
= xstrdup (optarg
);
1101 printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME
, PACKAGE_VERSION
);
1115 fp
= fopen (output
, "wb");
1117 grub_util_error ("cannot open %s", output
);
1119 convert_elf (dir
? : GRUB_LIBDIR
, prefix
? : DEFAULT_DIRECTORY
, fp
, argv
+ optind
);