diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
new file mode 100644
index 0000000..e8557e1
--- /dev/null
+++ b/conf/x86_64-efi.rmk
@@ -0,0 +1,155 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m64
+COMMON_CFLAGS = -fno-builtin -m64
+COMMON_LDFLAGS = -melf_x86_64 -nostdlib
+
+# Used by various components. These rules need to precede them.
+normal/execute.c_DEPENDENCIES = grub_script.tab.h
+normal/command.c_DEPENDENCIES = grub_script.tab.h
+normal/function.c_DEPENDENCIES = grub_script.tab.h
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+#sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+ util/resolve.c
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/biosdisk.c \
+# util/misc.c util/getroot.c kern/device.c kern/disk.c \
+# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
+# fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c \
+# fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
+# kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c \
+ util/i386/get_disk_name.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
+ commands/configfile.c commands/help.c \
+ commands/terminal.c commands/ls.c commands/test.c \
+ commands/search.c commands/hexdump.c \
+ commands/halt.c commands/reboot.c \
+ commands/i386/cpuid.c \
+ disk/loopback.c \
+ \
+ fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
+ fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
+ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
+ fs/ufs.c fs/xfs.c fs/afs.c \
+ \
+ io/gzio.c \
+ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \
+ kern/err.c \
+ normal/execute.c kern/file.c kern/fs.c normal/lexer.c \
+ kern/loader.c kern/main.c kern/misc.c kern/parser.c \
+ grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
+ normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+ normal/completion.c normal/context.c normal/main.c \
+ normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
+ normal/color.c \
+ partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
+ partmap/acorn.c partmap/gpt.c \
+ util/console.c util/hostfs.c util/grub-emu.c util/misc.c \
+ util/biosdisk.c util/getroot.c \
+ util/i386/pc/misc.c \
+ \
+ disk/raid.c disk/lvm.c \
+ grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
+ cpuid.mod halt.mod reboot.mod
+# _linux.mod linux.mod
+
+# For kernel.mod.
+kernel_mod_EXPORTS = no
+kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
+ kern/main.c kern/device.c \
+ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+ kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+ kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
+ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
+ term/efi/console.c disk/efi/efidisk.c
+kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
+ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
+ partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
+ efi/efi.h efi/time.h efi/disk.h
+kernel_mod_CFLAGS = $(COMMON_CFLAGS)
+kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+MOSTLYCLEANFILES += symlist.c
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
+ /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
+ /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
+
+# For normal.mod.
+normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
+ normal/completion.c normal/execute.c \
+ normal/function.c normal/lexer.c normal/main.c normal/menu.c \
+ normal/menu_entry.c normal/misc.c grub_script.tab.c \
+ normal/script.c normal/x86_64/setjmp.S normal/color.c
+normal_mod_CFLAGS = $(COMMON_CFLAGS)
+normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
+normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _chain.mod.
+_chain_mod_SOURCES = loader/efi/chainloader.c
+_chain_mod_CFLAGS = $(COMMON_CFLAGS)
+_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For chain.mod.
+chain_mod_SOURCES = loader/efi/chainloader_normal.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For _linux.mod.
+_linux_mod_SOURCES = loader/i386/efi/linux.c
+_linux_mod_CFLAGS = $(COMMON_CFLAGS)
+_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For linux.mod.
+linux_mod_SOURCES = loader/i386/efi/linux_normal.c
+linux_mod_CFLAGS = $(COMMON_CFLAGS)
+linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For cpuid.mod.
+cpuid_mod_SOURCES = commands/i386/cpuid.c
+cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
+cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For halt.mod.
+halt_mod_SOURCES = commands/halt.c
+halt_mod_CFLAGS = $(COMMON_CFLAGS)
+halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For reboot.mod.
+reboot_mod_SOURCES = commands/reboot.c
+reboot_mod_CFLAGS = $(COMMON_CFLAGS)
+reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+include $(srcdir)/conf/common.mk
diff --git a/configure.ac b/configure.ac
index 5ec7a47..a5ce826 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,11 +49,6 @@ esac
case "$target_cpu" in
i[[3456]]86) target_cpu=i386 ;;
- x86_64) target_cpu=i386 target_m32=1 ;;
- powerpc) ;;
- powerpc64) target_cpu=powerpc target_m32=1;;
- sparc64) ;;
- *) AC_MSG_ERROR([unsupported CPU type]) ;;
esac
# Specify the platform (such as firmware).
@@ -74,9 +69,27 @@ else
platform="$with_platform"
fi
+if test "x$platform" = "xefi" ; then
+ case "$target_cpu" in
+ i386) ;;
+ x86_64) target_m64=1 ;;
+ *) AC_MSG_ERROR([unsupported CPU type for EFI]) ;;
+ esac
+else
+ case "$target_cpu" in
+ i386) ;;
+ x86_64) target_cpu=i386 target_m32=1 ;;
+ powerpc) ;;
+ powerpc64) target_cpu=powerpc target_m32=1;;
+ sparc64) ;;
+ *) AC_MSG_ERROR([unsupported CPU type]) ;;
+ esac
+fi
+
# Sanity check.
case "$target_cpu"-"$platform" in
i386-efi) ;;
+ x86_64-efi) ;;
i386-pc) ;;
i386-linuxbios) ;;
i386-ieee1275) ;;
@@ -238,6 +251,12 @@ if test "x$target_m32" = x1; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
fi
+if test "x$target_m64" = x1; then
+ # Force 64-bit mode.
+ TARGET_CFLAGS="$TARGET_CFLAGS -m64"
+ TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
+fi
+
#
# Compiler features.
#
diff --git a/disk/efi/efidisk.c b/disk/efi/efidisk.c
index e51c2ea..3c5e35f 100644
--- a/disk/efi/efidisk.c
+++ b/disk/efi/efidisk.c
@@ -574,7 +574,7 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
"reading 0x%x sectors at the sector 0x%llx from %s\n",
size, sector, disk->name);
- status = dio->read (dio, bio->media->media_id,
+ status = efi_call_5 (dio->read, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
buf);
@@ -602,7 +602,7 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
"writing 0x%x sectors at the sector 0x%llx to %s\n",
size, sector, disk->name);
- status = dio->write (dio, bio->media->media_id,
+ status = efi_call_5 (dio->write, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
(void *) buf);
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 6c29753..96db9a6 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1095,4 +1095,42 @@ struct grub_efi_block_io
};
typedef struct grub_efi_block_io grub_efi_block_io_t;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+#define efi_call_0(func) func()
+#define efi_call_1(func, a) func(a)
+#define efi_call_2(func, a, b) func(a, b)
+#define efi_call_3(func, a, b, c) func(a, b, c)
+#define efi_call_4(func, a, b, c, d) func(a, b, c, d)
+#define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e)
+#define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f)
+
+#else
+
+#define efi_call_0(func) efi_wrap_0(func)
+#define efi_call_1(func, a) efi_wrap_1(func, (grub_uint64_t) a)
+#define efi_call_2(func, a, b) efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b)
+#define efi_call_3(func, a, b, c) efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c)
+#define efi_call_4(func, a, b, c, d) efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d)
+#define efi_call_5(func, a, b, c, d, e) efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d, (grub_uint64_t) e)
+#define efi_call_6(func, a, b, c, d, e, f) efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f)
+
+grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
+grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
+grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2);
+grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3);
+grub_uint64_t EXPORT_FUNC(efi_wrap_4) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4);
+grub_uint64_t EXPORT_FUNC(efi_wrap_5) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4, grub_uint64_t arg5);
+grub_uint64_t EXPORT_FUNC(efi_wrap_6) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4, grub_uint64_t arg5,
+ grub_uint64_t arg6);
+#endif
+
#endif /* ! GRUB_EFI_API_HEADER */
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index b6f01a8..f2072c5 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -64,6 +64,7 @@ struct grub_pe32_coff_header
};
#define GRUB_PE32_MACHINE_I386 0x14c
+#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_RELOCS_STRIPPED 0x0001
#define GRUB_PE32_EXECUTABLE_IMAGE 0x0002
@@ -98,9 +99,13 @@ struct grub_pe32_optional_header
grub_uint32_t entry_addr;
grub_uint32_t code_base;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
grub_uint32_t data_base;
-
grub_uint32_t image_base;
+#else
+ grub_uint64_t image_base;
+#endif
+
grub_uint32_t section_alignment;
grub_uint32_t file_alignment;
grub_uint16_t major_os_version;
@@ -115,10 +120,23 @@ struct grub_pe32_optional_header
grub_uint32_t checksum;
grub_uint16_t subsystem;
grub_uint16_t dll_characteristics;
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
grub_uint32_t stack_reserve_size;
grub_uint32_t stack_commit_size;
grub_uint32_t heap_reserve_size;
grub_uint32_t heap_commit_size;
+
+#else
+
+ grub_uint64_t stack_reserve_size;
+ grub_uint64_t stack_commit_size;
+ grub_uint64_t heap_reserve_size;
+ grub_uint64_t heap_commit_size;
+
+#endif
+
grub_uint32_t loader_flags;
grub_uint32_t num_data_directories;
@@ -141,8 +159,16 @@ struct grub_pe32_optional_header
struct grub_pe32_data_directory reserved_entry;
};
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
#define GRUB_PE32_PE32_MAGIC 0x10b
+#else
+
+#define GRUB_PE32_PE32_MAGIC 0x20b
+
+#endif
+
#define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10
#define GRUB_PE32_NUM_DATA_DIRECTORIES 16
diff --git a/include/grub/elf.h b/include/grub/elf.h
index 9aec816..7b76f58 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -454,6 +454,7 @@ typedef struct
the end of a chain, meaning no further symbols are found in that bucket. */
#define STN_UNDEF 0 /* End of a chain. */
+#define STN_ABS 65521
/* How to extract and insert information held in the st_other field. */
@@ -1108,8 +1109,27 @@ typedef struct
/* Keep this the last entry. */
#define R_386_NUM 38
+
/* SUN SPARC specific definitions. */
+/* x86_64 specific definitions. */
+#define R_X86_64_NONE 0
+#define R_X86_64_64 1
+#define R_X86_64_PC32 2
+#define R_X86_64_GOT32 3
+#define R_X86_64_PLT32 4
+#define R_X86_64_COPY 5
+#define R_X86_64_GLOB_DAT 6
+#define R_X86_64_JUMP_SLOT 7
+#define R_X86_64_RELATIVE 8
+#define R_X86_64_GOTPCREL 9
+#define R_X86_64_32 10
+#define R_X86_64_32S 11
+#define R_X86_64_16 12
+#define R_X86_64_PC16 13
+#define R_X86_64_8 14
+#define R_X86_64_PC8 15
+
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
#define STT_REGISTER 13 /* Global register reserved to app. */
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 4a4e2cc..9cbbdaf 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -38,6 +38,9 @@ struct grub_module_info
{
/* Magic number so we know we have modules present. */
grub_uint32_t magic;
+#if GRUB_TARGET_SIZEOF_VOID_P == 8
+ grub_uint32_t padding;
+#endif
/* The offset of the modules. */
grub_target_off_t offset;
/* The size of all modules plus this header. */
diff --git a/include/grub/x86_64/efi/kernel.h b/include/grub/x86_64/efi/kernel.h
new file mode 100644
index 0000000..c0549f4
--- /dev/null
+++ b/include/grub/x86_64/efi/kernel.h
@@ -0,0 +1,33 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MACHINE_KERNEL_HEADER
+#define GRUB_MACHINE_KERNEL_HEADER 1
+
+/* The prefix which points to the directory where GRUB modules and its
+ configuration file are located. */
+extern char grub_prefix[];
+
+/* The offset of GRUB_PREFIX. */
+#define GRUB_KERNEL_MACHINE_PREFIX 0x8
+
+/* End of the data section. */
+#define GRUB_KERNEL_MACHINE_DATA_END 0x50
+
+#endif /* ! GRUB_MACHINE_KERNEL_HEADER */
+
diff --git a/include/grub/x86_64/efi/loader.h b/include/grub/x86_64/efi/loader.h
new file mode 100755
index 0000000..3308be0
--- /dev/null
+++ b/include/grub/x86_64/efi/loader.h
@@ -0,0 +1,27 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2004,2006,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER 1
+
+/* It is necessary to export these functions, because normal mode commands
+ reuse rescue mode commands. */
+void grub_rescue_cmd_linux (int argc, char *argv[]);
+void grub_rescue_cmd_initrd (int argc, char *argv[]);
+
+#endif /* ! GRUB_LOADER_MACHINE_HEADER */
diff --git a/include/grub/x86_64/efi/machine.h b/include/grub/x86_64/efi/machine.h
new file mode 100755
index 0000000..1600768
--- /dev/null
+++ b/include/grub/x86_64/efi/machine.h
@@ -0,0 +1,24 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MACHINE_MACHINE_HEADER
+#define GRUB_MACHINE_MACHINE_HEADER 1
+
+#define GRUB_MACHINE_EFI 1
+
+#endif /* ! GRUB_MACHINE_MACHINE_HEADER */
diff --git a/include/grub/x86_64/efi/time.h b/include/grub/x86_64/efi/time.h
new file mode 100644
index 0000000..7a9241f
--- /dev/null
+++ b/include/grub/x86_64/efi/time.h
@@ -0,0 +1,24 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER 1
+
+#include
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/x86_64/setjmp.h b/include/grub/x86_64/setjmp.h
new file mode 100644
index 0000000..e417f65
--- /dev/null
+++ b/include/grub/x86_64/setjmp.h
@@ -0,0 +1,27 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2006,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_SETJMP_CPU_HEADER
+#define GRUB_SETJMP_CPU_HEADER 1
+
+typedef unsigned long grub_jmp_buf[8];
+
+int grub_setjmp (grub_jmp_buf env);
+void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));
+
+#endif /* ! GRUB_SETJMP_CPU_HEADER */
diff --git a/include/grub/x86_64/time.h b/include/grub/x86_64/time.h
new file mode 100644
index 0000000..842882c
--- /dev/null
+++ b/include/grub/x86_64/time.h
@@ -0,0 +1,29 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef KERNEL_CPU_TIME_HEADER
+#define KERNEL_CPU_TIME_HEADER 1
+
+static __inline void
+grub_cpu_idle (void)
+{
+ /* FIXME: this can't work until we handle interrupts. */
+/* __asm__ __volatile__ ("hlt"); */
+}
+
+#endif /* ! KERNEL_CPU_TIME_HEADER */
diff --git a/include/grub/x86_64/types.h b/include/grub/x86_64/types.h
new file mode 100644
index 0000000..bdee5a1
--- /dev/null
+++ b/include/grub/x86_64/types.h
@@ -0,0 +1,31 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_TYPES_CPU_HEADER
+#define GRUB_TYPES_CPU_HEADER 1
+
+/* The size of void *. */
+#define GRUB_TARGET_SIZEOF_VOID_P 8
+
+/* The size of long. */
+#define GRUB_TARGET_SIZEOF_LONG 8
+
+/* x86_64 is little-endian. */
+#undef GRUB_TARGET_WORDS_BIGENDIAN
+
+#endif /* ! GRUB_TYPES_CPU_HEADER */
diff --git a/kern/dl.c b/kern/dl.c
index 9e8c24a..9654c3a 100644
--- a/kern/dl.c
+++ b/kern/dl.c
@@ -29,7 +29,7 @@
#include
#include
-#if GRUB_CPU_SIZEOF_VOID_P == 4
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
typedef Elf32_Word Elf_Word;
typedef Elf32_Addr Elf_Addr;
@@ -40,7 +40,7 @@ typedef Elf32_Sym Elf_Sym;
# define ELF_ST_BIND(val) ELF32_ST_BIND (val)
# define ELF_ST_TYPE(val) ELF32_ST_TYPE (val)
-#elif GRUB_CPU_SIZEOF_VOID_P == 8
+#elif GRUB_TARGET_SIZEOF_VOID_P == 8
typedef Elf64_Word Elf_Word;
typedef Elf64_Addr Elf_Addr;
diff --git a/kern/efi/efi.c b/kern/efi/efi.c
index 11dac58..d6d9c1d 100644
--- a/kern/efi/efi.c
+++ b/kern/efi/efi.c
@@ -43,9 +43,8 @@ grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
void *interface;
grub_efi_status_t status;
- status = grub_efi_system_table->boot_services->locate_protocol (protocol,
- registration,
- &interface);
+ status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
+ protocol, registration, &interface);
if (status != GRUB_EFI_SUCCESS)
return 0;
@@ -71,7 +70,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
return 0;
b = grub_efi_system_table->boot_services;
- status = b->locate_handle (search_type, protocol, search_key,
+ status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
&buffer_size, buffer);
if (status == GRUB_EFI_BUFFER_TOO_SMALL)
{
@@ -80,7 +79,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
if (! buffer)
return 0;
- status = b->locate_handle (search_type, protocol, search_key,
+ status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
&buffer_size, buffer);
}
@@ -104,12 +103,12 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
void *interface;
b = grub_efi_system_table->boot_services;
- status = b->open_protocol (handle,
- protocol,
- &interface,
- grub_efi_image_handle,
- 0,
- attributes);
+ status = efi_call_6 (b->open_protocol, handle,
+ protocol,
+ &interface,
+ grub_efi_image_handle,
+ 0,
+ attributes);
if (status != GRUB_EFI_SUCCESS)
return 0;
@@ -128,12 +127,12 @@ grub_efi_set_text_mode (int on)
already in text mode. */
return 1;
- if (c->get_mode (c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
+ if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
return 0;
new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
if (mode != new_mode)
- if (c->set_mode (c, new_mode) != GRUB_EFI_SUCCESS)
+ if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS)
return 0;
return 1;
@@ -142,7 +141,7 @@ grub_efi_set_text_mode (int on)
void
grub_efi_stall (grub_efi_uintn_t microseconds)
{
- grub_efi_system_table->boot_services->stall (microseconds);
+ efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds);
}
grub_efi_loaded_image_t *
@@ -157,25 +156,24 @@ void
grub_exit (void)
{
grub_efi_fini ();
- grub_efi_system_table->boot_services->exit (grub_efi_image_handle,
- GRUB_EFI_SUCCESS,
- 0, 0);
+ efi_call_4 (grub_efi_system_table->boot_services->exit,
+ grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
}
void
grub_reboot (void)
{
grub_efi_fini ();
- grub_efi_system_table->runtime_services->
- reset_system (GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
}
void
grub_halt (void)
{
grub_efi_fini ();
- grub_efi_system_table->runtime_services->
- reset_system (GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
}
int
@@ -185,7 +183,7 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
grub_efi_status_t status;
b = grub_efi_system_table->boot_services;
- status = b->exit_boot_services (grub_efi_image_handle, map_key);
+ status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, map_key);
return status == GRUB_EFI_SUCCESS;
}
@@ -196,7 +194,7 @@ grub_get_rtc (void)
grub_efi_runtime_services_t *r;
r = grub_efi_system_table->runtime_services;
- if (r->get_time (&time, 0) != GRUB_EFI_SUCCESS)
+ if (efi_call_2 (r->get_time, &time, 0) != GRUB_EFI_SUCCESS)
/* What is possible in this case? */
return 0;
diff --git a/kern/efi/mm.c b/kern/efi/mm.c
index 9cd096d..94b8722 100644
--- a/kern/efi/mm.c
+++ b/kern/efi/mm.c
@@ -30,7 +30,7 @@
/* The size of a memory map obtained from the firmware. This must be
a multiplier of 4KB. */
-#define MEMORY_MAP_SIZE 0x1000
+#define MEMORY_MAP_SIZE 0x3000
/* Maintain the list of allocated pages. */
struct allocated_page
@@ -59,7 +59,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
grub_efi_status_t status;
grub_efi_boot_services_t *b;
-#if GRUB_CPU_SIZEOF_VOID_P < 8
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
/* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > 0xffffffff)
return 0;
@@ -79,7 +79,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
#endif
b = grub_efi_system_table->boot_services;
- status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address);
+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
if (status != GRUB_EFI_SUCCESS)
return 0;
@@ -88,7 +88,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
/* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */
address = 0xffffffff;
- status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address);
+ status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address);
grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS)
return 0;
@@ -135,7 +135,7 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
}
b = grub_efi_system_table->boot_services;
- b->free_pages (address, pages);
+ efi_call_2 (b->free_pages, address, pages);
}
/* Get the memory map as defined in the EFI spec. Return 1 if successful,
@@ -159,7 +159,7 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
descriptor_version = &version;
b = grub_efi_system_table->boot_services;
- status = b->get_memory_map (memory_map_size, memory_map, map_key,
+ status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key,
descriptor_size, descriptor_version);
if (status == GRUB_EFI_SUCCESS)
return 1;
diff --git a/kern/main.c b/kern/main.c
index 09de03a..776e8f3 100644
diff --git a/kern/partition.c b/kern/partition.c
index b9a0457..48b8ad5 100644
diff --git a/kern/term.c b/kern/term.c
index 4c45d71..07965b5 100644
--- a/kern/term.c
+++ b/kern/term.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
/* The list of terminals. */
static grub_term_t grub_term_list;
diff --git a/kern/x86_64/dl.c b/kern/x86_64/dl.c
new file mode 100755
index 0000000..bef3270
--- /dev/null
+++ b/kern/x86_64/dl.c
@@ -0,0 +1,121 @@
+/* dl-x86_64.c - arch-dependent part of loadable module support */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2005,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+/* Check if EHDR is a valid ELF header. */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+ Elf64_Ehdr *e = ehdr;
+
+ /* Check the magic numbers. */
+ if (e->e_ident[EI_CLASS] != ELFCLASS64
+ || e->e_ident[EI_DATA] != ELFDATA2LSB
+ || e->e_machine != EM_X86_64)
+ return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
+
+ return GRUB_ERR_NONE;
+}
+
+/* Relocate symbols. */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+ Elf64_Ehdr *e = ehdr;
+ Elf64_Shdr *s;
+ Elf64_Sym *symtab;
+ Elf64_Word entsize;
+ unsigned i;
+
+ /* Find a symbol table. */
+ for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_SYMTAB)
+ break;
+
+ if (i == e->e_shnum)
+ return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
+
+ symtab = (Elf64_Sym *) ((char *) e + s->sh_offset);
+ entsize = s->sh_entsize;
+
+ for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff);
+ i < e->e_shnum;
+ i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize))
+ if (s->sh_type == SHT_RELA)
+ {
+ grub_dl_segment_t seg;
+
+ /* Find the target segment. */
+ for (seg = mod->segment; seg; seg = seg->next)
+ if (seg->section == s->sh_info)
+ break;
+
+ if (seg)
+ {
+ Elf64_Rela *rel, *max;
+
+ for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset),
+ max = rel + s->sh_size / s->sh_entsize;
+ rel < max;
+ rel++)
+ {
+ Elf64_Word *addr32;
+ Elf64_Xword *addr64;
+ Elf64_Sym *sym;
+
+ if (seg->size < rel->r_offset)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "reloc offset is out of the segment");
+
+ addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset);
+ addr64 = (Elf64_Xword *) addr32;
+ sym = (Elf64_Sym *) ((char *) symtab
+ + entsize * ELF64_R_SYM (rel->r_info));
+
+ switch (ELF64_R_TYPE (rel->r_info))
+ {
+ case R_X86_64_64:
+ *addr64 = rel->r_addend + sym->st_value;
+ break;
+
+ case R_X86_64_PC32:
+ *addr32 = rel->r_addend + sym->st_value -
+ (Elf64_Xword) seg->addr - rel->r_offset;
+ break;
+
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ *addr32 = rel->r_addend + sym->st_value;
+ break;
+
+ default:
+ grub_fatal ("Unrecognized relocation: %d\n", ELF64_R_TYPE (rel->r_info));
+ }
+ }
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
diff --git a/kern/x86_64/efi/callwrap.S b/kern/x86_64/efi/callwrap.S
new file mode 100755
index 0000000..36e5509
--- /dev/null
+++ b/kern/x86_64/efi/callwrap.S
@@ -0,0 +1,96 @@
+/* callwrap.S - wrapper for x86_64 efi calls */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+
+/*
+ * x86_64 uses registry to pass parameters. Unfortuanately, gcc and efi use
+ * different call conversion, so we need to do some conversion.
+ *
+ * gcc:
+ * %rdi, %esi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
+ *
+ * efi:
+ * %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ...
+ *
+ */
+
+ .file "callwrap.S"
+ .text
+
+FUNCTION(efi_wrap_0)
+ subq $40, %rsp
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_1)
+ subq $40, %rsp
+ mov %rsi, %rcx
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_2)
+ subq $40, %rsp
+ mov %rsi, %rcx
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_3)
+ subq $40, %rsp
+ mov %rcx, %r8
+ mov %rsi, %rcx
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_4)
+ subq $40, %rsp
+ mov %r8, %r9
+ mov %rcx, %r8
+ mov %rsi, %rcx
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_5)
+ subq $40, %rsp
+ mov %r9, 32(%rsp)
+ mov %r8, %r9
+ mov %rcx, %r8
+ mov %rsi, %rcx
+ call *%rdi
+ addq $40, %rsp
+ ret
+
+FUNCTION(efi_wrap_6)
+ subq $56, %rsp
+ mov 56+8(%rsp), %rax
+ mov %rax, 40(%rsp)
+ mov %r9, (%rsp)
+ mov %r8, %r9
+ mov %rcx, %r8
+ mov %rsi, %rcx
+ call *%rdi
+ addq $56, %rsp
+ ret
diff --git a/kern/x86_64/efi/startup.S b/kern/x86_64/efi/startup.S
new file mode 100644
index 0000000..592f6a3
--- /dev/null
+++ b/kern/x86_64/efi/startup.S
@@ -0,0 +1,61 @@
+/* startup.S - bootstrap GRUB itself */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2006,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+
+ .file "startup.S"
+ .text
+ .globl start, _start
+start:
+_start:
+ jmp codestart
+
+ /*
+ * Compatibility version number
+ *
+ * These MUST be at byte offset 6 and 7 of the executable
+ * DO NOT MOVE !!!
+ */
+ . = EXT_C(start) + 0x6
+ .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+
+ /*
+ * This is a special data area 8 bytes from the beginning.
+ */
+
+ . = EXT_C(start) + 0x8
+
+VARIABLE(grub_prefix)
+ /* to be filled by grub-mkimage */
+
+ /*
+ * Leave some breathing room for the prefix.
+ */
+
+ . = EXT_C(start) + 0x50
+
+codestart:
+
+ movq %rcx, EXT_C(grub_efi_image_handle)
+ movq %rdx, EXT_C(grub_efi_system_table)
+
+ call EXT_C(grub_main)
+ ret
diff --git a/loader/efi/chainloader.c b/loader/efi/chainloader.c
index 19285d9..17a8c40 100644
--- a/loader/efi/chainloader.c
+++ b/loader/efi/chainloader.c
@@ -47,9 +47,9 @@ grub_chainloader_unload (void)
grub_efi_boot_services_t *b;
b = grub_efi_system_table->boot_services;
- b->unload_image (image_handle);
- b->free_pages (address, pages);
- grub_free (file_path);
+ efi_call_1 (b->unload_image, image_handle);
+ efi_call_2 (b->free_pages, address, pages);
+ efi_call_1 (grub_free, file_path);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
@@ -64,7 +64,7 @@ grub_chainloader_boot (void)
grub_efi_char16_t *exit_data;
b = grub_efi_system_table->boot_services;
- status = b->start_image (image_handle, &exit_data_size, &exit_data);
+ status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
if (status != GRUB_EFI_SUCCESS)
{
if (exit_data)
@@ -227,7 +227,7 @@ grub_chainloader_cmd (const char *filename)
size = grub_file_size (file);
pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
- status = b->allocate_pages (GRUB_EFI_ALLOCATE_ANY_PAGES,
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
GRUB_EFI_LOADER_CODE,
pages, &address);
if (status != GRUB_EFI_SUCCESS)
@@ -244,7 +244,7 @@ grub_chainloader_cmd (const char *filename)
goto fail;
}
- status = b->load_image (0, grub_efi_image_handle, file_path,
+ status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
(void *) ((grub_addr_t) address), size,
&image_handle);
if (status != GRUB_EFI_SUCCESS)
@@ -284,7 +284,7 @@ grub_chainloader_cmd (const char *filename)
grub_free (file_path);
if (address)
- b->free_pages (address, pages);
+ efi_call_2 (b->free_pages, address, pages);
grub_dl_unref (my_mod);
}
diff --git a/normal/x86_64/setjmp.S b/normal/x86_64/setjmp.S
new file mode 100644
index 0000000..2b6622b
--- /dev/null
+++ b/normal/x86_64/setjmp.S
@@ -0,0 +1,64 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+
+ .file "setjmp.S"
+
+ .text
+
+/*
+ * jmp_buf:
+ * rbx rbp r12 r13 r14 r15 rsp rip
+ * 0 8 16 24 32 40 48 56
+ */
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+ movq %rbx, 0(%rdi)
+ movq %rbp, 8(%rdi)
+ movq %r12, 16(%rdi)
+ movq %r13, 24(%rdi)
+ movq %r14, 32(%rdi)
+ movq %r15, 40(%rdi)
+ leaq 8(%rsp), %rax
+ movq %rax, 48(%rdi)
+ movq (%rsp), %rax
+ movq %rax, 56(%rdi)
+ movq $0, %rax
+ ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+ movq %rsi, %rax
+
+ movq 8(%rdi), %rbp
+
+ movq 48(%rdi), %rsp
+ pushq 56(%rdi)
+ movq 0(%rdi), %rbx
+ movq 16(%rdi), %r12
+ movq 24(%rdi), %r13
+ movq 32(%rdi), %r14
+ movq 40(%rdi), %r15
+
+ ret
diff --git a/term/efi/console.c b/term/efi/console.c
index af198e5..3e88b28 100644
--- a/term/efi/console.c
+++ b/term/efi/console.c
@@ -52,10 +52,10 @@ grub_console_putchar (grub_uint32_t c)
str[1] = 0;
/* Should this test be cached? */
- if (c > 0x7f && o->test_string (o, str) != GRUB_EFI_SUCCESS)
+ if (c > 0x7f && efi_call_2 (o->test_string, o, str) != GRUB_EFI_SUCCESS)
return;
- o->output_string (o, str);
+ efi_call_2 (o->output_string, o, str);
}
static grub_ssize_t
@@ -76,7 +76,7 @@ grub_console_checkkey (void)
return 1;
i = grub_efi_system_table->con_in;
- status = i->read_key_stroke (i, &key);
+ status = efi_call_2 (i->read_key_stroke, i, &key);
#if 1
switch (status)
{
@@ -169,7 +169,7 @@ grub_console_getkey (void)
do
{
- status = b->wait_for_event (1, &(i->wait_for_key), &index);
+ status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index);
if (status != GRUB_EFI_SUCCESS)
return -1;
@@ -189,7 +189,7 @@ grub_console_getwh (void)
grub_efi_uintn_t columns, rows;
o = grub_efi_system_table->con_out;
- if (o->query_mode (o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS)
+ if (efi_call_4 (o->query_mode, o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS)
{
/* Why does this fail? */
columns = 80;
@@ -214,7 +214,7 @@ grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y)
grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out;
- o->set_cursor_position (o, x, y);
+ efi_call_3 (o->set_cursor_position, o, x, y);
}
static void
@@ -225,9 +225,9 @@ grub_console_cls (void)
o = grub_efi_system_table->con_out;
orig_attr = o->mode->attribute;
- o->set_attributes (o, GRUB_EFI_BACKGROUND_BLACK);
- o->clear_screen (o);
- o->set_attributes (o, orig_attr);
+ efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK);
+ efi_call_1 (o->clear_screen, o);
+ efi_call_2 (o->set_attributes, o, orig_attr);
}
static void
@@ -239,13 +239,13 @@ grub_console_setcolorstate (grub_term_color_state state)
switch (state) {
case GRUB_TERM_COLOR_STANDARD:
- o->set_attributes (o, grub_console_standard_color);
+ efi_call_2 (o->set_attributes, o, grub_console_standard_color);
break;
case GRUB_TERM_COLOR_NORMAL:
- o->set_attributes (o, grub_console_normal_color);
+ efi_call_2 (o->set_attributes, o, grub_console_normal_color);
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
- o->set_attributes (o, grub_console_highlight_color);
+ efi_call_2 (o->set_attributes, o, grub_console_highlight_color);
break;
default:
break;
@@ -272,7 +272,7 @@ grub_console_setcursor (int on)
grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out;
- o->enable_cursor (o, on);
+ efi_call_2 (o->enable_cursor, o, on);
}
static struct grub_term grub_console_term =
diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c
index 57c1fc8..af765d5 100644
--- a/util/i386/efi/grub-mkimage.c
+++ b/util/i386/efi/grub-mkimage.c
@@ -31,16 +31,56 @@
#include
#include
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Half Elf_Half;
+typedef Elf32_Off Elf_Off;
+typedef Elf32_Section Elf_Section;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELF_R_INFO ELF32_R_INFO
+
+#define grub_le_to_cpu grub_le_to_cpu32
+
+#elif GRUB_TARGET_SIZEOF_VOID_P == 8
+
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+typedef Elf64_Half Elf_Half;
+typedef Elf64_Off Elf_Off;
+typedef Elf64_Section Elf_Section;
+typedef Elf64_Rel Elf_Rel;
+typedef Elf64_Rela Elf_Rela;
+
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELF_R_INFO ELF64_R_INFO
+
+#define grub_le_to_cpu grub_le_to_cpu64
+
+#endif
+
static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
-static inline Elf32_Addr
-align_address (Elf32_Addr addr, unsigned alignment)
+static inline Elf_Addr
+align_address (Elf_Addr addr, unsigned alignment)
{
return (addr + alignment - 1) & ~(alignment - 1);
}
-static inline Elf32_Addr
-align_pe32_section (Elf32_Addr addr)
+static inline Elf_Addr
+align_pe32_section (Elf_Addr addr)
{
return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT);
}
@@ -60,14 +100,15 @@ read_kernel_module (const char *dir, char *prefix, size_t *size)
if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
grub_util_error ("prefix too long");
- strcpy (kernel_image + 0x34 + GRUB_KERNEL_MACHINE_PREFIX, prefix);
+
+ //strcpy (kernel_image + 0x34 + GRUB_KERNEL_MACHINE_PREFIX, prefix);
return kernel_image;
}
/* Return if the ELF header is valid. */
static int
-check_elf_header (Elf32_Ehdr *e, size_t size)
+check_elf_header (Elf_Ehdr *e, size_t size)
{
if (size < sizeof (*e)
|| e->e_ident[EI_MAG0] != ELFMAG0
@@ -76,9 +117,11 @@ check_elf_header (Elf32_Ehdr *e, size_t size)
|| e->e_ident[EI_MAG3] != ELFMAG3
|| e->e_ident[EI_VERSION] != EV_CURRENT
|| e->e_version != grub_cpu_to_le32 (EV_CURRENT)
- || e->e_ident[EI_CLASS] != ELFCLASS32
+ || ((e->e_ident[EI_CLASS] != ELFCLASS32) &&
+ (e->e_ident[EI_CLASS] != ELFCLASS64))
|| e->e_ident[EI_DATA] != ELFDATA2LSB
- || e->e_machine != grub_cpu_to_le16 (EM_386))
+ || ((e->e_machine != grub_cpu_to_le16 (EM_386)) &&
+ (e->e_machine != grub_cpu_to_le16 (EM_X86_64))))
return 0;
return 1;
@@ -87,7 +130,7 @@ check_elf_header (Elf32_Ehdr *e, size_t size)
/* Return the starting address right after the header,
aligned by the section alignment. Allocate 4 section tables for
.text, .data, .reloc, and mods. */
-static Elf32_Addr
+static Elf_Addr
get_starting_section_address (void)
{
return align_pe32_section (sizeof (struct grub_pe32_header)
@@ -97,7 +140,7 @@ get_starting_section_address (void)
/* Determine if this section is a text section. Return false if this
section is not allocated. */
static int
-is_text_section (Elf32_Shdr *s)
+is_text_section (Elf_Shdr *s)
{
return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
== grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC));
@@ -107,7 +150,7 @@ is_text_section (Elf32_Shdr *s)
BSS is also a data section, since the converter initializes BSS
when producing PE32 to avoid a bug in EFI implementations. */
static int
-is_data_section (Elf32_Shdr *s)
+is_data_section (Elf_Shdr *s)
{
return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
&& ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR)));
@@ -116,14 +159,14 @@ is_data_section (Elf32_Shdr *s)
/* Locate section addresses by merging code sections and data sections
into .text and .data, respectively. Return the array of section
addresses. */
-static Elf32_Addr *
-locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
- Elf32_Half num_sections, const char *strtab)
+static Elf_Addr *
+locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
+ Elf_Half num_sections, const char *strtab)
{
int i;
- Elf32_Addr current_address;
- Elf32_Addr *section_addresses;
- Elf32_Shdr *s;
+ Elf_Addr current_address;
+ Elf_Addr *section_addresses;
+ Elf_Shdr *s;
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
@@ -133,10 +176,10 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
/* .text */
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_text_section (s))
{
- Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
+ Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
@@ -153,10 +196,10 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
/* .data */
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_data_section (s))
{
- Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
+ Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
@@ -172,16 +215,16 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
}
/* Return the symbol table section, if any. */
-static Elf32_Shdr *
-find_symtab_section (Elf32_Shdr *sections,
- Elf32_Half section_entsize, Elf32_Half num_sections)
+static Elf_Shdr *
+find_symtab_section (Elf_Shdr *sections,
+ Elf_Half section_entsize, Elf_Half num_sections)
{
int i;
- Elf32_Shdr *s;
+ Elf_Shdr *s;
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
return s;
@@ -190,12 +233,12 @@ find_symtab_section (Elf32_Shdr *sections,
/* Return the address of the string table. */
static const char *
-find_strtab (Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize)
+find_strtab (Elf_Ehdr *e, Elf_Shdr *sections, Elf_Half section_entsize)
{
- Elf32_Shdr *s;
+ Elf_Shdr *s;
char *strtab;
- s = (Elf32_Shdr *) ((char *) sections
+ s = (Elf_Shdr *) ((char *) sections
+ grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
return strtab;
@@ -203,21 +246,21 @@ find_strtab (Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize)
/* Relocate symbols; note that this function overwrites the symbol table.
Return the address of a start symbol. */
-static Elf32_Addr
-relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
- Elf32_Shdr *symtab_section, Elf32_Addr *section_addresses,
- Elf32_Half section_entsize, Elf32_Half num_sections)
+static Elf_Addr
+relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
+ Elf_Half section_entsize, Elf_Half num_sections)
{
- Elf32_Word symtab_size, sym_size, num_syms;
- Elf32_Off symtab_offset;
- Elf32_Addr start_address = 0;
- Elf32_Sym *sym;
- Elf32_Word i;
- Elf32_Shdr *strtab_section;
+ Elf_Word symtab_size, sym_size, num_syms;
+ Elf_Off symtab_offset;
+ Elf_Addr start_address = 0;
+ Elf_Sym *sym;
+ Elf_Word i;
+ Elf_Shdr *strtab_section;
const char *strtab;
strtab_section
- = (Elf32_Shdr *) ((char *) sections
+ = (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (symtab_section->sh_link)
* section_entsize));
strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset);
@@ -227,17 +270,21 @@ relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
num_syms = symtab_size / sym_size;
- for (i = 0, sym = (Elf32_Sym *) ((char *) e + symtab_offset);
+ for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
i < num_syms;
- i++, sym = (Elf32_Sym *) ((char *) sym + sym_size))
+ i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
{
- Elf32_Section index;
+ Elf_Section index;
const char *name;
name = strtab + grub_le_to_cpu32 (sym->st_name);
index = grub_le_to_cpu16 (sym->st_shndx);
- if (index == STN_UNDEF)
+ if (index == STN_ABS)
+ {
+ continue;
+ }
+ else if ((index == STN_UNDEF))
{
if (sym->st_name)
grub_util_error ("undefined symbol %s", name);
@@ -260,22 +307,22 @@ relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections,
}
/* Return the address of a symbol at the index I in the section S. */
-static Elf32_Addr
-get_symbol_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Word i)
+static Elf_Addr
+get_symbol_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i)
{
- Elf32_Sym *sym;
+ Elf_Sym *sym;
- sym = (Elf32_Sym *) ((char *) e
+ sym = (Elf_Sym *) ((char *) e
+ grub_le_to_cpu32 (s->sh_offset)
+ i * grub_le_to_cpu32 (s->sh_entsize));
return sym->st_value;
}
/* Return the address of a modified value. */
-static Elf32_Addr
-get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset)
+static Elf_Addr *
+get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
{
- return (Elf32_Addr) e + grub_le_to_cpu32 (s->sh_offset) + offset;
+ return (Elf_Addr *) ((char *) e + grub_le_to_cpu32 (s->sh_offset) + offset);
}
/* Deal with relocation information. This function relocates addresses
@@ -283,34 +330,35 @@ get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset)
addresses can be fully resolved. Absolute addresses must be relocated
again by a PE32 relocator when loaded. */
static void
-relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
- Elf32_Addr *section_addresses,
- Elf32_Half section_entsize, Elf32_Half num_sections,
+relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Addr *section_addresses,
+ Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
- Elf32_Half i;
- Elf32_Shdr *s;
+ Elf_Half i;
+ Elf_Shdr *s;
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
- if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
+ (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{
- Elf32_Rel *r;
- Elf32_Word rtab_size, r_size, num_rs;
- Elf32_Off rtab_offset;
- Elf32_Shdr *symtab_section;
- Elf32_Word target_section_index;
- Elf32_Addr target_section_addr;
- Elf32_Shdr *target_section;
- Elf32_Word j;
-
- symtab_section = (Elf32_Shdr *) ((char *) sections
+ Elf_Rela *r;
+ Elf_Word rtab_size, r_size, num_rs;
+ Elf_Off rtab_offset;
+ Elf_Shdr *symtab_section;
+ Elf_Word target_section_index;
+ Elf_Addr target_section_addr;
+ Elf_Shdr *target_section;
+ Elf_Word j;
+
+ symtab_section = (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (s->sh_link)
* section_entsize));
target_section_index = grub_le_to_cpu32 (s->sh_info);
target_section_addr = section_addresses[target_section_index];
- target_section = (Elf32_Shdr *) ((char *) sections
+ target_section = (Elf_Shdr *) ((char *) sections
+ (target_section_index
* section_entsize));
@@ -323,47 +371,84 @@ relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
rtab_offset = grub_le_to_cpu32 (s->sh_offset);
num_rs = rtab_size / r_size;
- for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
+ for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
j < num_rs;
- j++, r = (Elf32_Rel *) ((char *) r + r_size))
+ j++, r = (Elf_Rela *) ((char *) r + r_size))
{
- Elf32_Word info;
- Elf32_Addr offset;
- Elf32_Addr sym_addr;
- Elf32_Addr *target;
-
- offset = grub_le_to_cpu32 (r->r_offset);
- target = (Elf32_Addr *) get_target_address (e, target_section,
- offset);
- info = grub_le_to_cpu32 (r->r_info);
+ Elf_Addr info;
+ Elf_Addr offset;
+ Elf_Addr sym_addr;
+ Elf_Addr *target, *value;
+
+ offset = grub_le_to_cpu (r->r_offset);
+ target = get_target_address (e, target_section, offset);
+ info = grub_le_to_cpu (r->r_info);
sym_addr = get_symbol_address (e, symtab_section,
- ELF32_R_SYM (info));
+ ELF_R_SYM (info));
+
+ value = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
+ (Elf_Addr *) &r->r_addend : target;
- switch (ELF32_R_TYPE (info))
+ switch (ELF_R_TYPE (info))
{
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
case R_386_NONE:
break;
case R_386_32:
/* This is absolute. */
- *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
- + sym_addr);
+ *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
+ + sym_addr);
grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
*target, offset);
break;
case R_386_PC32:
/* This is relative. */
- *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target)
+ *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
+ sym_addr
- target_section_addr - offset);
grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
*target, offset);
break;
+#else
+
+ case R_X86_64_NONE:
+ break;
+
+ case R_X86_64_64:
+ *target = grub_cpu_to_le64 (grub_le_to_cpu64 (*value) + sym_addr);
+ grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
+ *target, offset);
+ break;
+
+ case R_X86_64_PC32:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
+ + sym_addr
+ - target_section_addr - offset);
+ grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
+ *t32, offset);
+ break;
+ }
+
+ case R_X86_64_32:
+ case R_X86_64_32S:
+ {
+ grub_uint32_t *t32 = (grub_uint32_t *) target;
+ *t32 = grub_cpu_to_le64 (grub_le_to_cpu64 (*value)
+ + sym_addr);
+ grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
+ *t32, offset);
+ break;
+ }
+
+#endif
default:
grub_util_error ("unknown relocation type %d",
- ELF32_R_TYPE (info));
+ ELF_R_TYPE (info));
break;
}
}
@@ -382,9 +467,9 @@ write_padding (FILE *out, size_t size)
/* Add a PE32's fixup entry for a relocation. Return the resulting address
after having written to the file OUT. */
-Elf32_Addr
+Elf_Addr
add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
- Elf32_Addr addr, int flush, Elf32_Addr current_address,
+ Elf_Addr addr, int flush, Elf_Addr current_address,
FILE *out)
{
struct grub_pe32_fixup_block *b = *block;
@@ -400,7 +485,7 @@ add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
{
/* Add as much padding as necessary to align the address
with a section boundary. */
- Elf32_Addr next_address;
+ Elf_Addr next_address;
unsigned padding_size;
size_t index;
@@ -473,10 +558,10 @@ add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type,
}
/* Write out zeros to make space for the header. */
-static Elf32_Addr
+static Elf_Addr
make_header_space (FILE *out)
{
- Elf32_Addr addr;
+ Elf_Addr addr;
addr = get_starting_section_address ();
write_padding (out, addr);
@@ -485,24 +570,24 @@ make_header_space (FILE *out)
}
/* Write text sections. */
-static Elf32_Addr
-write_text_sections (FILE *out, Elf32_Addr current_address,
- Elf32_Ehdr *e, Elf32_Shdr *sections,
- Elf32_Half section_entsize, Elf32_Half num_sections,
+static Elf_Addr
+write_text_sections (FILE *out, Elf_Addr current_address,
+ Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
- Elf32_Half i;
- Elf32_Shdr *s;
- Elf32_Addr addr;
+ Elf_Half i;
+ Elf_Shdr *s;
+ Elf_Addr addr;
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_text_section (s))
{
- Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
- Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
- Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
+ Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+ Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
+ Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
@@ -538,24 +623,24 @@ write_text_sections (FILE *out, Elf32_Addr current_address,
}
/* Write data sections. */
-static Elf32_Addr
-write_data_sections (FILE *out, Elf32_Addr current_address,
- Elf32_Ehdr *e, Elf32_Shdr *sections,
- Elf32_Half section_entsize, Elf32_Half num_sections,
+static Elf_Addr
+write_data_sections (FILE *out, Elf_Addr current_address,
+ Elf_Ehdr *e, Elf_Shdr *sections,
+ Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
- Elf32_Half i;
- Elf32_Shdr *s;
- Elf32_Addr addr;
+ Elf_Half i;
+ Elf_Shdr *s;
+ Elf_Addr addr;
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
if (is_data_section (s))
{
- Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign);
- Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset);
- Elf32_Word size = grub_le_to_cpu32 (s->sh_size);
+ Elf_Word align = grub_le_to_cpu32 (s->sh_addralign);
+ Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
+ Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align)
@@ -594,15 +679,15 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
}
/* Write modules. */
-static Elf32_Addr
-make_mods_section (FILE *out, Elf32_Addr current_address,
+static Elf_Addr
+make_mods_section (FILE *out, Elf_Addr current_address,
const char *dir, char *mods[])
{
struct grub_util_path_list *path_list;
grub_size_t total_module_size;
struct grub_util_path_list *p;
struct grub_module_info modinfo;
- Elf32_Addr addr;
+ Elf_Addr addr;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
@@ -666,26 +751,27 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
}
/* Make a .reloc section. */
-static Elf32_Addr
-make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
- Elf32_Addr *section_addresses, Elf32_Shdr *sections,
- Elf32_Half section_entsize, Elf32_Half num_sections,
+static Elf_Addr
+make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
+ Elf_Addr *section_addresses, Elf_Shdr *sections,
+ Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab)
{
- Elf32_Half i;
- Elf32_Shdr *s;
+ Elf_Half i;
+ Elf_Shdr *s;
struct grub_pe32_fixup_block *fixup_block = 0;
for (i = 0, s = sections;
i < num_sections;
- i++, s = (Elf32_Shdr *) ((char *) s + section_entsize))
- if (s->sh_type == grub_cpu_to_le32 (SHT_REL))
+ i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+ if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
+ (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{
- Elf32_Rel *r;
- Elf32_Word rtab_size, r_size, num_rs;
- Elf32_Off rtab_offset;
- Elf32_Addr section_address;
- Elf32_Word j;
+ Elf_Rel *r;
+ Elf_Word rtab_size, r_size, num_rs;
+ Elf_Off rtab_offset;
+ Elf_Addr section_address;
+ Elf_Word j;
grub_util_info ("translating the relocation section %s",
strtab + grub_le_to_cpu32 (s->sh_name));
@@ -697,20 +783,21 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
- for (j = 0, r = (Elf32_Rel *) ((char *) e + rtab_offset);
+ for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
j < num_rs;
- j++, r = (Elf32_Rel *) ((char *) r + r_size))
+ j++, r = (Elf_Rel *) ((char *) r + r_size))
{
- Elf32_Word info;
- Elf32_Addr offset;
+ Elf_Addr info;
+ Elf_Addr offset;
offset = grub_le_to_cpu32 (r->r_offset);
info = grub_le_to_cpu32 (r->r_info);
/* Necessary to relocate only absolute addresses. */
- if (ELF32_R_TYPE (info) == R_386_32)
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+ if (ELF_R_TYPE (info) == R_386_32)
{
- Elf32_Addr addr;
+ Elf_Addr addr;
addr = section_address + offset;
grub_util_info ("adding a relocation entry for 0x%x", addr);
@@ -719,6 +806,21 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
addr, 0, current_address,
out);
}
+#else
+ if ((ELF_R_TYPE (info) == R_X86_64_64) ||
+ (ELF_R_TYPE (info) == R_X86_64_32) ||
+ (ELF_R_TYPE (info) == R_X86_64_32S))
+ {
+ Elf_Addr addr;
+
+ addr = section_address + offset;
+ grub_util_info ("adding a relocation entry for 0x%llx", addr);
+ current_address = add_fixup_entry (&fixup_block,
+ GRUB_PE32_REL_BASED_HIGHLOW,
+ addr, 0, current_address,
+ out);
+ }
+#endif
}
}
@@ -730,9 +832,9 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
/* Create the header. */
static void
-make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
- Elf32_Addr mods_address, Elf32_Addr reloc_address,
- Elf32_Addr end_address, Elf32_Addr start_address)
+make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
+ Elf_Addr mods_address, Elf_Addr reloc_address,
+ Elf_Addr end_address, Elf_Addr start_address)
{
struct grub_pe32_header header;
struct grub_pe32_coff_header *c;
@@ -747,14 +849,22 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
/* The COFF file header. */
c = &header.coff_header;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386);
+#else
+ c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_X86_64);
+#endif
+
c->num_sections = grub_cpu_to_le16 (4);
c->time = grub_cpu_to_le32 (time (0));
c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
| GRUB_PE32_LINE_NUMS_STRIPPED
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+ | GRUB_PE32_32BIT_MACHINE
+#endif
| GRUB_PE32_LOCAL_SYMS_STRIPPED
- | GRUB_PE32_32BIT_MACHINE);
+ | GRUB_PE32_DEBUG_STRIPPED);
/* The PE Optional header. */
o = &header.optional_header;
@@ -764,7 +874,9 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
o->bss_size = 0;
o->entry_addr = grub_cpu_to_le32 (start_address);
o->code_base = grub_cpu_to_le32 (text_address);
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
o->data_base = grub_cpu_to_le32 (data_address);
+#endif
o->image_base = 0;
o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
@@ -847,30 +959,31 @@ convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
char *kernel_image;
size_t kernel_size;
const char *strtab;
- Elf32_Ehdr *e;
- Elf32_Shdr *sections;
- Elf32_Off section_offset;
- Elf32_Half section_entsize;
- Elf32_Half num_sections;
- Elf32_Addr *section_addresses;
- Elf32_Shdr *symtab_section;
- Elf32_Addr start_address;
- Elf32_Addr text_address, data_address, reloc_address, mods_address;
- Elf32_Addr end_address;
+ Elf_Ehdr *e;
+ Elf_Shdr *sections;
+ Elf_Off section_offset;
+ Elf_Half section_entsize;
+ Elf_Half num_sections;
+ Elf_Addr *section_addresses;
+ Elf_Shdr *symtab_section;
+ Elf_Addr start_address;
+ Elf_Addr text_address, data_address, reloc_address, mods_address;
+ Elf_Addr end_address;
/* Get the kernel image and check the format. */
kernel_image = read_kernel_module (dir, prefix, &kernel_size);
- e = (Elf32_Ehdr *) kernel_image;
+ e = (Elf_Ehdr *) kernel_image;
if (! check_elf_header (e, kernel_size))
grub_util_error ("invalid ELF header");
section_offset = grub_cpu_to_le32 (e->e_shoff);
section_entsize = grub_cpu_to_le16 (e->e_shentsize);
num_sections = grub_cpu_to_le16 (e->e_shnum);
+
if (kernel_size < section_offset + section_entsize * num_sections)
grub_util_error ("invalid ELF format");
- sections = (Elf32_Shdr *) (kernel_image + section_offset);
+ sections = (Elf_Shdr *) (kernel_image + section_offset);
strtab = find_strtab (e, sections, section_entsize);
/* Relocate sections then symbols in the virtual address space. */