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>
27 /* Check if EHDR is a valid ELF header. */
29 grub_arch_efiemu_check_header32 (void *ehdr
)
33 /* Check the magic numbers. */
34 return (e
->e_ident
[EI_CLASS
] == ELFCLASS32
35 && e
->e_ident
[EI_DATA
] == ELFDATA2LSB
36 && e
->e_machine
== EM_386
);
39 /* Relocate symbols. */
41 grub_arch_efiemu_relocate_symbols32 (grub_efiemu_segment_t segs
,
42 struct grub_efiemu_elf_sym
*elfsyms
,
50 grub_dprintf ("efiemu", "relocating symbols %d %d\n",
51 e
->e_shoff
, e
->e_shnum
);
53 for (i
= 0, s
= (Elf32_Shdr
*) ((char *) e
+ e
->e_shoff
);
55 i
++, s
= (Elf32_Shdr
*) ((char *) s
+ e
->e_shentsize
))
56 if (s
->sh_type
== SHT_REL
)
58 grub_efiemu_segment_t seg
;
59 grub_dprintf ("efiemu", "shtrel\n");
61 /* Find the target segment. */
62 for (seg
= segs
; seg
; seg
= seg
->next
)
63 if (seg
->section
== s
->sh_info
)
70 for (rel
= (Elf32_Rel
*) ((char *) e
+ s
->sh_offset
),
71 max
= rel
+ s
->sh_size
/ s
->sh_entsize
;
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 sym
= elfsyms
[ELF32_R_SYM (rel
->r_info
)];
86 switch (ELF32_R_TYPE (rel
->r_info
))
89 if ((err
= grub_efiemu_write_value
90 (addr
, sym
.off
+ *addr
, sym
.handle
, 0,
91 seg
->ptv_rel_needed
, sizeof (grub_uint32_t
))))
97 if ((err
= grub_efiemu_write_value
98 (addr
, sym
.off
+ *addr
- rel
->r_offset
99 - seg
->off
, sym
.handle
, seg
->handle
,
100 seg
->ptv_rel_needed
, sizeof (grub_uint32_t
))))
104 return grub_error (GRUB_ERR_BAD_OS
,
105 "unrecognised relocation");
111 return GRUB_ERR_NONE
;