1 /* i386 CPU-specific part of loadcore.c for 32-bit mode */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
22 #include <grub/misc.h>
23 #include <grub/efiemu/efiemu.h>
24 #include <grub/cpu/efiemu.h>
26 #include <grub/i18n.h>
28 /* Check if EHDR is a valid ELF header. */
30 grub_arch_efiemu_check_header64 (void *ehdr
)
34 return (e
->e_ident
[EI_CLASS
] == ELFCLASS64
35 && e
->e_ident
[EI_DATA
] == ELFDATA2LSB
36 && e
->e_machine
== EM_X86_64
);
39 /* Relocate symbols. */
41 grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs
,
42 struct grub_efiemu_elf_sym
*elfsyms
,
50 for (i
= 0, s
= (Elf64_Shdr
*) ((char *) e
+ e
->e_shoff
);
52 i
++, s
= (Elf64_Shdr
*) ((char *) s
+ e
->e_shentsize
))
53 if (s
->sh_type
== SHT_RELA
)
55 grub_efiemu_segment_t seg
;
56 grub_dprintf ("efiemu", "shtrel\n");
58 /* Find the target segment. */
59 for (seg
= segs
; seg
; seg
= seg
->next
)
60 if (seg
->section
== s
->sh_info
)
65 Elf64_Rela
*rel
, *max
;
67 for (rel
= (Elf64_Rela
*) ((char *) e
+ s
->sh_offset
),
68 max
= rel
+ (unsigned long) s
->sh_size
69 / (unsigned long)s
->sh_entsize
;
74 grub_uint32_t
*addr32
;
75 grub_uint64_t
*addr64
;
76 struct grub_efiemu_elf_sym sym
;
77 if (seg
->size
< rel
->r_offset
)
78 return grub_error (GRUB_ERR_BAD_MODULE
,
79 "reloc offset is out of the segment");
82 ((char *) grub_efiemu_mm_obtain_request (seg
->handle
)
83 + seg
->off
+ rel
->r_offset
);
84 addr32
= (grub_uint32_t
*) addr
;
85 addr64
= (grub_uint64_t
*) addr
;
86 sym
= elfsyms
[ELF64_R_SYM (rel
->r_info
)];
88 switch (ELF64_R_TYPE (rel
->r_info
))
91 err
= grub_efiemu_write_value (addr
,
92 *addr64
+ rel
->r_addend
93 + sym
.off
, sym
.handle
,
94 0, seg
->ptv_rel_needed
,
95 sizeof (grub_uint64_t
));
101 err
= grub_efiemu_write_value (addr
,
102 *addr32
+ rel
->r_addend
104 - rel
->r_offset
- seg
->off
,
105 sym
.handle
, seg
->handle
,
107 sizeof (grub_uint32_t
));
114 err
= grub_efiemu_write_value (addr
,
115 *addr32
+ rel
->r_addend
116 + sym
.off
, sym
.handle
,
117 0, seg
->ptv_rel_needed
,
118 sizeof (grub_uint32_t
));
123 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
124 N_("relocation 0x%x is not implemented yet"),
125 ELF_R_TYPE (rel
->r_info
));
131 return GRUB_ERR_NONE
;