All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] New x86_64 EFI patch
@ 2008-06-20 17:04 Bean
  2008-06-21 17:04 ` Bean
  2008-07-03 18:11 ` Marco Gerards
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-06-20 17:04 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 531 bytes --]

Hi,

This new patch add the following function to the original x86_64 EFI patch:

1, Fix menu drawing problem
It maps the unicode char to EFI char so that the rectangle box is
showed properly

2, Handle command line option for chainloader command

3, Add new command appleloader
The command is used to enable bios boot in apple's bootcamp, for example

boot from legacy mbr:
appleloader HD
boot

boot from legacy cd:
appleloader CD
boot

boot from usb:
appleloader USB
boot

The usb booting may not work in some machine.

-- 
Bean

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: efi_4.diff --]
[-- Type: text/x-diff; name=efi_4.diff, Size: 116924 bytes --]

diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 311b6ab..99bb0d4 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -74,8 +74,8 @@ sbin_SCRIPTS = grub-install
 grub_install_SOURCES = util/i386/efi/grub-install.in
 
 # Modules.
-pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
-	_linux.mod linux.mod cpuid.mod halt.mod reboot.mod
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+	_linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -123,6 +123,11 @@ chain_mod_SOURCES = loader/efi/chainloader_normal.c
 chain_mod_CFLAGS = $(COMMON_CFLAGS)
 chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For _linux.mod.
 _linux_mod_SOURCES = loader/i386/efi/linux.c
 _linux_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -148,4 +153,14 @@ reboot_mod_SOURCES = commands/reboot.c
 reboot_mod_CFLAGS = $(COMMON_CFLAGS)
 reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
new file mode 100644
index 0000000..149e726
--- /dev/null
+++ b/conf/x86_64-efi.rmk
@@ -0,0 +1,169 @@
+# -*- 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 appleldr.mod \
+	cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.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 appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_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)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_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/chainloader.h b/include/grub/efi/chainloader.h
index 470132b..d5c11e3 100644
--- a/include/grub/efi/chainloader.h
+++ b/include/grub/efi/chainloader.h
@@ -19,6 +19,6 @@
 #ifndef GRUB_EFI_CHAINLOADER_HEADER
 #define GRUB_EFI_CHAINLOADER_HEADER	1
 
-void grub_chainloader_cmd (const char *filename);
+void grub_rescue_cmd_chainloader (int argc, char *argv[]);
 
 #endif /* ! GRUB_EFI_CHAINLOADER_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/efi/uga_draw.h b/include/grub/efi/uga_draw.h
new file mode 100755
index 0000000..9350430
--- /dev/null
+++ b/include/grub/efi/uga_draw.h
@@ -0,0 +1,76 @@
+/* uga_draw.h - definitions of the uga draw protocol */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+/* The console control protocol is not a part of the EFI spec,
+   but defined in Intel's Sample Implementation.  */
+
+#ifndef GRUB_EFI_UGA_DRAW_HEADER
+#define GRUB_EFI_UGA_DRAW_HEADER	1
+
+#define GRUB_EFI_UGA_DRAW_GUID \
+  { 0x982c298b, 0xf4fa, 0x41cb, { 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 }}
+
+enum grub_efi_uga_blt_operation
+{
+  GRUB_EFI_UGA_VIDEO_FILL,
+  GRUB_EFI_UGA_VIDEO_TO_BLT,
+  GRUB_EFI_UGA_BLT_TO_VIDEO,
+  GRUB_EFI_UGA_VIDEO_TO_VIDEO,
+  GRUB_EFI_UGA_GLT_MAX
+};
+
+struct grub_efi_uga_pixel
+{
+  grub_uint8_t Blue;
+  grub_uint8_t Green;
+  grub_uint8_t Red;
+  grub_uint8_t Reserved;
+};
+
+struct grub_efi_uga_draw_protocol
+{
+  grub_efi_status_t
+  (*get_mode) (struct grub_efi_uga_draw_protocol *this,
+	       grub_uint32_t *width,
+	       grub_uint32_t *height,
+	       grub_uint32_t *depth,
+	       grub_uint32_t *refresh_rate);
+
+  grub_efi_status_t
+  (*set_mode) (struct grub_efi_uga_draw_protocol *this,
+	       grub_uint32_t width,
+	       grub_uint32_t height,
+	       grub_uint32_t depth,
+	       grub_uint32_t refresh_rate);
+
+  grub_efi_status_t
+  (*blt) (struct grub_efi_uga_draw_protocol *this,
+	  struct grub_efi_uga_pixel *blt_buffer,
+	  enum grub_efi_uga_blt_operation blt_operation,
+	  grub_efi_uintn_t src_x,
+	  grub_efi_uintn_t src_y,
+	  grub_efi_uintn_t dest_x,
+	  grub_efi_uintn_t dest_y,
+	  grub_efi_uintn_t width,
+	  grub_efi_uintn_t height,
+	  grub_efi_uintn_t delta);
+};
+typedef struct grub_efi_uga_draw_protocol grub_efi_uga_draw_protocol_t;
+
+#endif /* ! GRUB_EFI_UGA_DRAW_HEADER */
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/i386/efi/pci.h b/include/grub/i386/efi/pci.h
new file mode 100755
index 0000000..8480fd7
--- /dev/null
+++ b/include/grub/i386/efi/pci.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/pc/pci.h>
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
old mode 100644
new mode 100755
index 7a8e006..7ea75fe
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -44,14 +44,44 @@
 #define GRUB_LINUX_SETUP_MOVE_SIZE	0x9100
 #define GRUB_LINUX_CL_MAGIC		0xA33F
 
+#ifdef __x86_64__
+
 #define GRUB_LINUX_EFI_SIGNATURE	\
-  ('E' << 24 | 'F' << 16 | 'I' << 8 | 'L')
+  ('4' << 24 | '6' << 16 | 'L' << 8 | 'E')
+
+#else
+
+#define GRUB_LINUX_EFI_SIGNATURE	\
+  ('2' << 24 | '3' << 16 | 'L' << 8 | 'E')
+
+#endif
+
+#define GRUB_LINUX_EFI_SIGNATURE_0204	\
+  ('L' << 24 | 'I' << 16 | 'F' << 8 | 'E')
 
 #define GRUB_LINUX_OFW_SIGNATURE	\
   (' ' << 24 | 'W' << 16 | 'F' << 8 | 'O')
 
 #ifndef ASM_FILE
 
+#define GRUB_E820_RAM        1
+#define GRUB_E820_RESERVED   2
+#define GRUB_E820_ACPI       3
+#define GRUB_E820_NVS        4
+#define GRUB_E820_EXEC_CODE  5
+
+#define GRUB_E820_MAX_ENTRY  128
+
+struct grub_e820_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t size;
+  grub_uint32_t type;
+} __attribute__((packed));
+
+#define GRUB_VIDEO_TYPE_VLFB	0x23    /* VESA VGA in graphic mode     */
+#define GRUB_VIDEO_TYPE_EFI	0x70
+
 /* For the Linux/i386 boot protocol version 2.03.  */
 struct linux_kernel_header
 { 
@@ -67,6 +97,7 @@ struct linux_kernel_header
   grub_uint16_t vid_mode;		/* Video mode control */
   grub_uint16_t root_dev;		/* Default root device number */
   grub_uint16_t boot_flag;		/* 0xAA55 magic number */
+
   grub_uint16_t jump;			/* Jump instruction */
   grub_uint32_t header;			/* Magic signature "HdrS" */
   grub_uint16_t version;		/* Boot protocol version supported */
@@ -84,6 +115,13 @@ struct linux_kernel_header
   grub_uint16_t pad1;			/* Unused */
   char *cmd_line_ptr;			/* Points to the kernel command line */
   grub_uint32_t initrd_addr_max;        /* Highest address for initrd */
+
+  grub_uint32_t kernel_alignment;
+  grub_uint8_t relocatable_kernel;
+  grub_uint8_t pad2[3];
+  grub_uint32_t hardware_subarch;
+  grub_uint64_t hardware_subarch_data;
+  grub_uint32_t oo;
 } __attribute__ ((packed));
 
 /* Boot parameters for Linux based on 2.6.12. This is used by the setup
@@ -164,26 +202,65 @@ struct linux_kernel_params
   grub_uint32_t ofw_cif_handler;	/* b8 */
   grub_uint32_t ofw_idt;		/* bc */
 
-  grub_uint8_t padding7[0x1c0 - 0xc0];
-  
-  grub_uint32_t efi_signature;		/* 1c0 */
-  grub_uint32_t efi_system_table;	/* 1c4 */
-  grub_uint32_t efi_mem_desc_size;	/* 1c8 */
-  grub_uint32_t efi_mem_desc_version;	/* 1cc */
-  grub_uint32_t efi_mmap;		/* 1d0 */
-  grub_uint32_t efi_mmap_size;		/* 1d4 */
-  
-  grub_uint8_t padding8[0x1e0 - 0x1d8];
+  grub_uint8_t padding7[0x1b8 - 0xc0];
+
+  union
+    {
+      struct
+        {
+          grub_uint32_t efi_system_table;	/* 1b8 */
+          grub_uint32_t padding7_1;		/* 1bc */
+          grub_uint32_t efi_signature;		/* 1c0 */
+          grub_uint32_t efi_mem_desc_size;	/* 1c4 */
+          grub_uint32_t efi_mem_desc_version;	/* 1c8 */
+          grub_uint32_t efi_mmap_size;		/* 1cc */
+          grub_uint32_t efi_mmap;		/* 1d0 */
+        } v0204;
+      struct
+        {
+          grub_uint32_t padding7_1;		/* 1b8 */
+          grub_uint32_t padding7_2;		/* 1bc */
+          grub_uint32_t efi_signature;		/* 1c0 */
+          grub_uint32_t efi_system_table;	/* 1c4 */
+          grub_uint32_t efi_mem_desc_size;	/* 1c8 */
+          grub_uint32_t efi_mem_desc_version;	/* 1cc */
+          grub_uint32_t efi_mmap;		/* 1d0 */
+          grub_uint32_t efi_mmap_size;		/* 1d4 */
+          grub_uint32_t efi_system_table_hi;	/* 1d8 */
+          grub_uint32_t efi_mmap_hi;		/* 1dc */
+        } v0206;
+    };
   
   grub_uint32_t alt_mem;		/* 1e0 */
   
-  grub_uint8_t padding9[0x1e8 - 0x1e4];
+  grub_uint8_t padding8[0x1e8 - 0x1e4];
   
   grub_uint32_t mmap_size;		/* 1e8 */
 
-  grub_uint8_t padding10[0x1ff - 0x1ec];
+  grub_uint8_t padding9[0x1ff - 0x1ec];
   
   grub_uint8_t ps_mouse;		/* 1ff */
+
+  grub_uint16_t jump;			/* Jump instruction */
+  grub_uint32_t header;			/* Magic signature "HdrS" */
+  grub_uint16_t version;		/* Boot protocol version supported */
+  grub_uint32_t realmode_swtch;		/* Boot loader hook */
+  grub_uint16_t start_sys;		/* The load-low segment (obsolete) */
+  grub_uint16_t kernel_version;		/* Points to kernel version string */
+  grub_uint8_t type_of_loader;		/* Boot loader identifier */
+  grub_uint8_t loadflags;		/* Boot protocol option flags */
+  grub_uint16_t setup_move_size;	/* Move to high memory size */
+  grub_uint32_t code32_start;		/* Boot loader hook */
+  grub_uint32_t ramdisk_image;		/* initrd load address */
+  grub_uint32_t ramdisk_size;		/* initrd size */
+  grub_uint32_t bootsect_kludge;	/* obsolete */
+  grub_uint16_t heap_end_ptr;		/* Free memory after setup end */
+  grub_uint16_t pad1;			/* Unused */
+  grub_uint32_t cmd_line_ptr;		/* Points to the kernel command line */
+
+  grub_uint8_t pad2[164];		/* 22c */
+  struct grub_e820_mmap e820_map[GRUB_E820_MAX_ENTRY];	/* 2d0 */
+
 } __attribute__ ((packed));
 #endif /* ! ASM_FILE */
 
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/pci.h b/include/grub/pci.h
index 7108886..abc5c90 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -22,6 +22,19 @@
 #include <grub/types.h>
 #include <grub/symbol.h>
 
+#define  GRUB_PCI_ADDR_SPACE_MASK	0x01
+#define  GRUB_PCI_ADDR_SPACE_MEMORY	0x00
+#define  GRUB_PCI_ADDR_SPACE_IO		0x01
+
+#define  GRUB_PCI_ADDR_MEM_TYPE_MASK	0x06
+#define  GRUB_PCI_ADDR_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  GRUB_PCI_ADDR_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
+#define  GRUB_PCI_ADDR_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  GRUB_PCI_ADDR_MEM_PREFETCH	0x08	/* prefetchable */
+
+#define  GRUB_PCI_ADDR_MEM_MASK		~0xf
+#define  GRUB_PCI_ADDR_IO_MASK		~0x03
+
 typedef grub_uint32_t grub_pci_id_t;
 typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
 				       grub_pci_id_t pciid);
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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/pci.h b/include/grub/x86_64/efi/pci.h
new file mode 100755
index 0000000..8480fd7
--- /dev/null
+++ b/include/grub/x86_64/efi/pci.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/pc/pci.h>
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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER	1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/x86_64/linux.h b/include/grub/x86_64/linux.h
new file mode 100644
index 0000000..19ea936
--- /dev/null
+++ b/include/grub/x86_64/linux.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/linux.h>
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <grub/env.h>
 #include <grub/cache.h>
 
-#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..5098ccd 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;
@@ -218,7 +218,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
     {
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-#if GRUB_CPU_SIZEOF_VOID_P < 8
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
 	  && desc->physical_start <= 0xffffffff
 #endif
 	  && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
@@ -234,7 +234,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
 	      desc->physical_start = 0x100000;
 	    }
 	  
-#if GRUB_CPU_SIZEOF_VOID_P < 8
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
 	  if (BYTES_TO_PAGES (filtered_desc->physical_start)
 	      + filtered_desc->num_pages
 	      > BYTES_TO_PAGES (0x100000000LL))
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 <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/env.h>
+#include <grub/efi/efi.h>
 
 /* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+        .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/appleloader.c b/loader/efi/appleloader.c
new file mode 100755
index 0000000..910a13d
--- /dev/null
+++ b/loader/efi/appleloader.c
@@ -0,0 +1,208 @@
+/* appleloader.c - apple legacy boot loader.  */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+static grub_dl_t my_mod;
+
+static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
+
+static grub_err_t
+grub_appleloader_unload (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_1 (b->unload_image, image_handle);
+
+  grub_free (cmdline);
+  cmdline = 0;
+
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_appleloader_boot (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_3 (b->start_image, image_handle, 0, 0);
+
+  grub_appleloader_unload ();
+
+  return grub_errno;
+}
+
+/* early 2006 Core Duo / Core Solo models  */
+static grub_uint8_t devpath_1[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2006 Mac Pro (and probably other Core 2 models)  */
+static grub_uint8_t devpath_2[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2007 MBP ("Santa Rosa" based models)  */
+static grub_uint8_t devpath_3[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* early-2008 MBA  */
+static grub_uint8_t devpath_4[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+struct devdata
+{
+  char *model;
+  grub_efi_device_path_t *devpath;
+};
+
+struct devdata devs[] =
+{
+  {"Core Duo/Solo", (grub_efi_device_path_t *) devpath_1},
+  {"Mac Pro", (grub_efi_device_path_t *) devpath_2},
+  {"MBP", (grub_efi_device_path_t *) devpath_3},
+  {"MBA", (grub_efi_device_path_t *) devpath_4},
+  {NULL, NULL},
+};
+
+static grub_err_t
+grub_cmd_appleloader (struct grub_arg_list *state __attribute__ ((unused)),
+                      int argc, char *argv[])
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_loaded_image_t *loaded_image;
+  struct devdata *pdev;
+
+  grub_dl_ref (my_mod);
+
+  /* Initialize some global variables.  */
+  image_handle = 0;
+
+  b = grub_efi_system_table->boot_services;
+
+  for (pdev = devs ; pdev->devpath ; pdev++)
+    if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
+                    NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
+      break;
+
+  if (! pdev->devpath)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "can't find model");
+      goto fail;
+    }
+
+  grub_printf ("Model : %s\n", pdev->model);
+
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  if (! loaded_image)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+      goto fail;
+    }
+
+  if (argc > 0)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 0, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 0; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
+  grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
+
+  return 0;
+
+ fail:
+
+  grub_dl_unref (my_mod);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(appleloader)
+{
+  grub_register_command ("appleloader", grub_cmd_appleloader,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "appleloader [OPTS]",
+			 "Boot legacy system.", 0);
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(appleloader)
+{
+  grub_unregister_command ("appleloader");
+}
diff --git a/loader/efi/chainloader.c b/loader/efi/chainloader.c
index 19285d9..fbb7aac 100644
--- a/loader/efi/chainloader.c
+++ b/loader/efi/chainloader.c
@@ -40,6 +40,7 @@ static grub_efi_physical_address_t address;
 static grub_efi_uintn_t pages;
 static grub_efi_device_path_t *file_path;
 static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
 
 static grub_err_t
 grub_chainloader_unload (void)
@@ -47,9 +48,12 @@ 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);
+  efi_call_1 (b->unload_image, image_handle);
+  efi_call_2 (b->free_pages, address, pages);
+
   grub_free (file_path);
+  grub_free (cmdline);
+  cmdline = 0;
   
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
@@ -64,7 +68,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)
@@ -86,7 +90,7 @@ grub_chainloader_boot (void)
     }
 
   if (exit_data)
-    b->free_pool (exit_data);
+    efi_call_1 (b->free_pool, exit_data);
 
   grub_chainloader_unload ();
   
@@ -175,7 +179,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
 }
 
 void
-grub_chainloader_cmd (const char *filename)
+grub_rescue_cmd_chainloader (int argc, char *argv[])
 {
   grub_file_t file = 0;
   grub_ssize_t size;
@@ -185,6 +189,14 @@ grub_chainloader_cmd (const char *filename)
   grub_device_t dev = 0;
   grub_efi_device_path_t *dp = 0;
   grub_efi_loaded_image_t *loaded_image;
+  char *filename;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  filename = argv[0];
   
   grub_dl_ref (my_mod);
 
@@ -227,7 +239,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 +256,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)
@@ -269,6 +281,36 @@ grub_chainloader_cmd (const char *filename)
   loaded_image->device_handle = dev_handle;
   
   grub_file_close (file);
+
+  if (argc > 1)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 1, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 1; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
   grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
   return;
   
@@ -284,20 +326,11 @@ 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);
 }
 
-static void
-grub_rescue_cmd_chainloader (int argc, char *argv[])
-{
-  if (argc == 0)
-    grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
-  else
-    grub_chainloader_cmd (argv[0]);
-}
-
 static const char loader_name[] = "chainloader";
 
 GRUB_MOD_INIT(chainloader)
diff --git a/loader/efi/chainloader_normal.c b/loader/efi/chainloader_normal.c
index 2ea3368..455669e 100644
--- a/loader/efi/chainloader_normal.c
+++ b/loader/efi/chainloader_normal.c
@@ -29,7 +29,7 @@ chainloader_command (struct grub_arg_list *state __attribute__ ((unused)),
   if (argc == 0)
     grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
   else
-    grub_chainloader_cmd (args[0]);
+    grub_rescue_cmd_chainloader (argc, args);
   return grub_errno;
 }
 
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index ee3fb99..d6e285f 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -30,6 +30,8 @@
 #include <grub/cpu/linux.h>
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
+#include <grub/efi/uga_draw.h>
+#include <grub/pci.h>
 
 #define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
   ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
@@ -60,29 +62,25 @@ static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
 
 struct gdt_descriptor
 {
-  grub_uint16_t dummy;
   grub_uint16_t limit;
-  grub_uint32_t base;
-} __attribute__ ((aligned(4), packed));
+  void *base;
+} __attribute__ ((packed));
 
 static struct gdt_descriptor gdt_desc =
   {
-    0,
-    sizeof (gdt) - 1,
-    (grub_addr_t) gdt
+    sizeof (gdt),
+    gdt
   };
 
 struct idt_descriptor
 {
-  grub_uint16_t dummy;
   grub_uint16_t limit;
-  grub_uint32_t base;
-} __attribute__ ((aligned(4)));
+  void *base;
+} __attribute__ ((packed));
 
 static struct idt_descriptor idt_desc =
   {
     0,
-    0,
     0
   };
 
@@ -156,24 +154,28 @@ free_pages (void)
 /* Allocate pages for the real mode code and the protected mode code
    for linux as well as a memory map buffer.  */
 static int
-allocate_pages (grub_size_t real_size, grub_size_t prot_size)
+allocate_pages (grub_size_t prot_size)
 {
   grub_efi_uintn_t desc_size;
   grub_efi_memory_descriptor_t *mmap, *mmap_end;
   grub_efi_uintn_t mmap_size, tmp_mmap_size;
   grub_efi_memory_descriptor_t *desc;
+  grub_size_t real_size;
   
   /* Make sure that each size is aligned to a page boundary.  */
-  real_size = page_align (real_size + GRUB_DISK_SECTOR_SIZE);
+  real_size = page_align (sizeof (struct linux_kernel_params));
   prot_size = page_align (prot_size);
   mmap_size = find_mmap_size ();
 
+  if (real_size + mmap_size > GRUB_LINUX_CL_OFFSET)
+    grub_fatal ("Memory map too large");
+
   grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
-		real_size, prot_size, mmap_size);
+		(unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
   
   /* Calculate the number of pages; Combine the real mode code with
      the memory map buffer for simplicity.  */
-  real_mode_pages = ((real_size + mmap_size) >> 12);
+  real_mode_pages = (page_align (GRUB_LINUX_CL_END_OFFSET + 1) >> 12);
   prot_mode_pages = (prot_size >> 12);
   
   /* Initialize the memory pointers with NULL for convenience.  */
@@ -200,31 +202,20 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
       /* Probably it is better to put the real mode code in the traditional
 	 space for safety.  */
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-	  && desc->physical_start <= 0x90000
+	  && desc->physical_start < 0xA0000
 	  && desc->num_pages >= real_mode_pages)
 	{
-	  grub_efi_physical_address_t physical_end;
-	  grub_efi_physical_address_t addr;
+          grub_efi_physical_address_t addr;
 	  
-	  physical_end = desc->physical_start + (desc->num_pages << 12);
-	  if (physical_end > 0x90000)
-	    physical_end = 0x90000;
-
-	  grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
-			(unsigned) desc->physical_start,
-			(unsigned) physical_end);
-	  addr = physical_end - real_size - mmap_size;
-	  if (addr < 0x10000)
-	    continue;
-
-	  grub_dprintf ("linux", "trying to allocate %u pages at %x\n",
-			real_mode_pages, (unsigned) addr);
-	  real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
-	  if (! real_mode_mem)
-	    grub_fatal ("cannot allocate pages");
-	  
-	  desc->num_pages -= real_mode_pages;
-	  break;
+	  addr = desc->physical_start + ((desc->num_pages - real_mode_pages) << 12);
+
+          if (addr > 0x90000)
+            addr = 0x90000;
+
+          /* There could be multiple ranges that means the condition,
+           * use the highest one. */
+          if (addr > (grub_efi_physical_address_t) real_mode_mem)
+            real_mode_mem = (void *) addr;
 	}
     }
 
@@ -233,6 +224,12 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
       goto fail;
     }
+  else
+    {
+      real_mode_mem = grub_efi_allocate_pages (real_mode_mem, real_mode_pages);
+      if (! real_mode_mem)
+        grub_fatal ("cannot allocate pages");
+    }
 
   mmap_buf = (void *) ((char *) real_mode_mem + real_size);
 	      
@@ -246,6 +243,11 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
       goto fail;
     }
 
+  grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
+                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
+                (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
+                (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+
   grub_free (mmap);
   return 1;
 
@@ -255,56 +257,193 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
   return 0;
 }
 
+static void
+grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
+                      grub_uint64_t start, grub_uint64_t size,
+                      grub_uint32_t type)
+{
+  int n = *e820_num;
+
+  if (n >= GRUB_E820_MAX_ENTRY)
+    grub_fatal ("Too many e820 memory map entries");
+
+  if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
+      (e820_map[n - 1].type == type))
+      e820_map[n - 1].size += size;
+  else
+    {
+      e820_map[n].addr = start;
+      e820_map[n].size = size;
+      e820_map[n].type = type;
+      (*e820_num)++;
+    }
+}
+
+#ifdef __x86_64__
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+void *jump_start;
+#else
+grub_uint32_t kernel_entry;
+#endif
+
 static grub_err_t
 grub_linux_boot (void)
 {
-  struct linux_kernel_header *lh;
   struct linux_kernel_params *params;
   grub_efi_uintn_t mmap_size;
   grub_efi_uintn_t map_key;
   grub_efi_uintn_t desc_size;
   grub_efi_uint32_t desc_version;
+  grub_efi_memory_descriptor_t *desc;
+  int e820_num;
   
-  lh = real_mode_mem;
   params = real_mode_mem;
 
   grub_dprintf ("linux", "code32_start = %x, idt_desc = %x, gdt_desc = %x\n",
-		(unsigned) lh->code32_start, (grub_addr_t) &(idt_desc.limit),
+		(unsigned) params->code32_start, (grub_addr_t) &(idt_desc.limit),
 		(grub_addr_t) &(gdt_desc.limit));
   grub_dprintf ("linux", "idt = %x:%x, gdt = %x:%x\n",
 		(unsigned) idt_desc.limit, (unsigned) idt_desc.base,
 		(unsigned) gdt_desc.limit, (unsigned) gdt_desc.base);
+
   mmap_size = find_mmap_size ();
   if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
 			       &desc_size, &desc_version) <= 0)
     grub_fatal ("cannot get memory map");
 
+  e820_num = 0;
+  for (desc = mmap_buf;
+       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      switch (desc->type)
+        {
+        case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_ACPI);
+          break;
+
+        case GRUB_EFI_ACPI_MEMORY_NVS:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_NVS);
+          break;
+
+        case GRUB_EFI_RUNTIME_SERVICES_CODE:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_EXEC_CODE);
+          break;
+
+        case GRUB_EFI_LOADER_CODE:
+        case GRUB_EFI_LOADER_DATA:
+        case GRUB_EFI_BOOT_SERVICES_CODE:
+        case GRUB_EFI_BOOT_SERVICES_DATA:
+        case GRUB_EFI_CONVENTIONAL_MEMORY:
+          {
+            grub_uint64_t start, size, end;
+
+            start = desc->physical_start;
+            size = desc->num_pages << 12;
+            end = start + size;
+
+            /* Skip A0000 - 100000 region.  */
+            if ((start < 0x100000ULL) && (end > 0xA0000ULL))
+              {
+                if (start < 0xA0000ULL)
+                  {
+                    grub_e820_add_region (params->e820_map, &e820_num,
+                                          start,
+                                          0xA0000ULL - start,
+                                          GRUB_E820_RAM);
+                  }
+
+                if (end <= 0x100000ULL)
+                  continue;
+
+                start = 0x100000ULL;
+                size = end - start;
+              }
+
+            grub_e820_add_region (params->e820_map, &e820_num,
+                                  start, size, GRUB_E820_RAM);
+            break;
+          }
+
+        default:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_RESERVED);
+        }
+    }
+
+  params->mmap_size = e820_num;
+
   if (! grub_efi_exit_boot_services (map_key))
-    grub_fatal ("cannot exit boot services");
+     grub_fatal ("cannot exit boot services");
 
   /* Note that no boot services are available from here.  */
 
+  /* Pass EFI parameters.  */
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_mem_desc_size = desc_size;
+      params->v0206.efi_mem_desc_version = desc_version;
+      params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0206.efi_mmap_size = mmap_size;
+#ifdef __x86_64__
+      params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_mem_desc_size = desc_size;
+      params->v0204.efi_mem_desc_version = desc_version;
+      params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0204.efi_mmap_size = mmap_size;
+    }
+
   /* Hardware interrupts are not safe any longer.  */
   asm volatile ("cli" : : );
   
-  /* Pass EFI parameters.  */
-  params->efi_mem_desc_size = desc_size;
-  params->efi_mem_desc_version = desc_version;
-  params->efi_mmap = (grub_addr_t) mmap_buf;
-  params->efi_mmap_size = mmap_size;
+#ifdef __x86_64__
+
+  jumpvector.kernel_entry = params->code32_start;
+  jumpvector.kernel_cs = 0x10;
+  jump_start = (void *) &jumpvector;
+
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
+  asm volatile ( "mov %0, %%rcx" : : "m" (jump_start));
+
+  asm volatile ( "ljmp *(%%rcx)" : :);
+
+#else
+
+  kernel_entry = params->code32_start;
 
   /* Pass parameters.  */
   asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
-  asm volatile ("movl %0, %%ecx" : : "m" (lh->code32_start));
+  asm volatile ("movl %0, %%ecx" : : "m" (kernel_entry));
   asm volatile ("xorl %%ebx, %%ebx" : : );
 
-  /* Load the IDT and the GDT for the bootstrap.  */
-  asm volatile ("lidt %0" : : "m" (idt_desc.limit));
-  asm volatile ("lgdt %0" : : "m" (gdt_desc.limit));
-
   /* Enter Linux.  */
   asm volatile ("jmp *%%ecx" : : );
   
+#endif
+
   /* Never reach here.  */
   return GRUB_ERR_NONE;
 }
@@ -318,6 +457,111 @@ grub_linux_unload (void)
   return GRUB_ERR_NONE;
 }
 
+grub_uint64_t video_base;
+
+static int
+grub_find_video_card (int bus, int dev, int func,
+                      grub_pci_id_t pciid __attribute__ ((unused)))
+{
+  grub_pci_address_t addr;
+
+  addr = grub_pci_make_address (bus, dev, func, 2);
+
+  if (grub_pci_read (addr) >> 24 == 0x3)
+    {
+      int i;
+
+      addr = grub_pci_make_address (bus, dev, func, 4);
+      for (i = 0; i < 6; i++, addr += 4)
+        {
+          grub_uint32_t base, type;
+
+          base = grub_pci_read (addr);
+
+          if ((base == 0) || (base == 0xffffffff) ||
+              (base & GRUB_PCI_ADDR_SPACE_IO))
+            continue;
+
+          type = base & GRUB_PCI_ADDR_MEM_TYPE_MASK;
+          if (! (addr & GRUB_PCI_ADDR_MEM_PREFETCH))
+            {
+              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+                {
+                  i++;
+                  addr +=4 ;
+                }
+              continue;
+            }
+
+          base &= GRUB_PCI_ADDR_MEM_MASK;
+          if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+            {
+              if (i == 5)
+                break;
+
+              video_base = grub_pci_read (addr + 4);
+              video_base <<= 32;
+            }
+
+          video_base |= base;
+
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
+static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
+
+static int
+grub_linux_setup_video (struct linux_kernel_params *params)
+{
+  grub_efi_uga_draw_protocol_t *c;
+  grub_uint32_t width, height, depth, rate;
+
+  c = grub_efi_locate_protocol (&uga_draw_guid, 0);
+  if (! c)
+    return 1;
+
+  if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
+    return 1;
+
+  grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate);
+
+  video_base = 0;
+  grub_pci_iterate (grub_find_video_card);
+
+  if (! video_base)
+    {
+      grub_printf ("Can\'t find frame buffer address\n");
+      return 1;
+    }
+
+  grub_printf ("Video frame buffer: %llx\n", video_base);
+
+  params->lfb_width = width;
+  params->lfb_height = height;
+  params->lfb_depth = depth;
+
+  /* FIXME: shouldn't use fixed value.  */
+  params->lfb_line_len = 8192;
+
+  params->lfb_base = video_base;
+  params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
+
+  params->red_mask_size = 8;
+  params->red_field_pos = 16;
+  params->green_mask_size = 8;
+  params->green_field_pos = 8;
+  params->blue_mask_size = 8;
+  params->blue_field_pos = 0;
+  params->reserved_mask_size = 8;
+  params->reserved_field_pos = 24;
+
+  return 0;
+}
+
 void
 grub_rescue_cmd_linux (int argc, char *argv[])
 {
@@ -329,6 +573,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   grub_ssize_t len;
   int i;
   char *dest;
+  int video_type;
 
   grub_dl_ref (my_mod);
   
@@ -384,19 +629,25 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
   prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
   
-  if (! allocate_pages (real_size, prot_size))
+  if (! allocate_pages (prot_size))
     goto fail;
   
+  params = (struct linux_kernel_params *) real_mode_mem;
+  grub_memset (params, 0, sizeof (struct linux_kernel_params));
+  grub_memcpy (&params->jump, &lh.jump,
+               (char *) &lh.ramdisk_image - (char *) &lh.jump);
+
   /* XXX Linux assumes that only elilo can boot Linux on EFI!!!  */
-  lh.type_of_loader = 0x50;
+  params->type_of_loader = 0x50;
 
-  lh.cl_magic = GRUB_LINUX_CL_MAGIC;
-  lh.cl_offset = GRUB_LINUX_CL_END_OFFSET;
-  lh.cmd_line_ptr = (char *) real_mode_mem + GRUB_LINUX_CL_OFFSET;
-  lh.ramdisk_image = 0;
-  lh.ramdisk_size = 0;
+  params->cl_magic = GRUB_LINUX_CL_MAGIC;
+  params->cl_offset = GRUB_LINUX_CL_OFFSET;
+  params->cmd_line_ptr = (grub_uint32_t) real_mode_mem + GRUB_LINUX_CL_OFFSET;
+  params->ramdisk_image = 0;
+  params->ramdisk_size = 0;
 
-  params = (struct linux_kernel_params *) &lh;
+  params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
+  params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
 
   /* These are not needed to be precise, because Linux uses these values
      only to raise an error when the decompression code cannot find good
@@ -414,6 +665,23 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   params->have_vga = 0;
   params->font_size = 16; /* XXX */
 
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
+      params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+#ifdef __x86_64__
+      params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
+      params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+    }
+
+#if 0
+  /* The structure is zeroed already.  */
+
   /* No VBE on EFI.  */
   params->lfb_width = 0;
   params->lfb_height = 0;
@@ -457,10 +725,6 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   /* No MCA on EFI.  */
   params->rom_config_len = 0;
 
-  params->efi_signature = GRUB_LINUX_EFI_SIGNATURE; /* XXX not used */
-  params->efi_system_table = (grub_addr_t) grub_efi_system_table;
-  /* The other EFI parameters are filled when booting.  */
-
   /* No need to fake the BIOS's memory map.  */
   params->mmap_size = 0;
 
@@ -478,22 +742,19 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   grub_memset (params->padding8, 0, sizeof (params->padding8));
   grub_memset (params->padding9, 0, sizeof (params->padding9));
   
-  /* Put the real mode code at the real location.  */
-  grub_memmove (real_mode_mem, &lh, sizeof (lh));
+#endif
 
-  len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
-  if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
-    {
-      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
-      goto fail;
-    }
+  /* The other EFI parameters are filled when booting.  */
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
 
   /* XXX there is no way to know if the kernel really supports EFI.  */
   grub_printf ("   [Linux-EFI, setup=0x%x, size=0x%x]\n",
-	       real_size, prot_size);
+	       (unsigned) real_size, (unsigned) prot_size);
 
   /* Detect explicitly specified memory size, if any.  */
   linux_mem_size = 0;
+  video_type = 0;
   for (i = 1; i < argc; i++)
     if (grub_memcmp (argv[i], "mem=", 4) == 0)
       {
@@ -529,6 +790,19 @@ grub_rescue_cmd_linux (int argc, char *argv[])
 	      linux_mem_size <<= shift;
 	  }
       }
+    else if (grub_memcmp (argv[i], "video=", 6) == 0)
+      {
+        if (grub_memcmp (&argv[i][6], "vesafb", 6) == 0)
+          video_type = GRUB_VIDEO_TYPE_VLFB;
+        else if (grub_memcmp (&argv[i][6], "efifb", 5) == 0)
+          video_type = GRUB_VIDEO_TYPE_EFI;
+      }
+
+  if (video_type)
+    {
+      if (!  grub_linux_setup_video (params))
+        params->have_vga = video_type;
+    }
 
   /* Specify the boot file.  */
   dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
@@ -601,7 +875,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
 
   lh = (struct linux_kernel_header *) real_mode_mem;
   
-  addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+  addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
   if (linux_mem_size != 0 && linux_mem_size < addr_max)
     addr_max = linux_mem_size;
   
@@ -612,7 +886,8 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
   addr_max -= 0x10000;
 
   /* Usually, the compression ratio is about 50%.  */
-  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12);
+  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+             + page_align (size);
   
   /* Find the highest address to put the initrd.  */
   mmap_size = find_mmap_size ();
@@ -625,8 +900,6 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
     {
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-	  && desc->physical_start >= addr_min
-	  && desc->physical_start + size < addr_max
 	  && desc->num_pages >= initrd_pages)
 	{
 	  grub_efi_physical_address_t physical_end;
@@ -635,6 +908,9 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
 	  if (physical_end > addr_max)
 	    physical_end = addr_max;
 
+          if (physical_end < addr_min)
+            continue;
+
 	  if (physical_end > addr)
 	    addr = physical_end - page_align (size);
 	}
@@ -657,7 +933,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
     }
 
   grub_printf ("   [Initrd, addr=0x%x, size=0x%x]\n",
-	       addr, size);
+	       (unsigned) addr, (unsigned) size);
   
   lh->ramdisk_image = addr;
   lh->ramdisk_size = size;
diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c
index bc4567e..290d7b9 100644
--- a/loader/i386/ieee1275/linux.c
+++ b/loader/i386/ieee1275/linux.c
@@ -85,6 +85,49 @@ grub_set_bootpath (void)
 
 }
 
+static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
+  {
+    /* NULL.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Reserved.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Code segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
+    /* Data segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+  };
+
+struct gdt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct gdt_descriptor gdt_desc =
+  {
+    sizeof (gdt),
+    gdt
+  };
+
+struct idt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct idt_descriptor idt_desc =
+  {
+    0,
+    0
+  };
+
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+void *jump_start;
+
 static grub_err_t
 grub_linux_boot (void)
 {
@@ -137,11 +180,33 @@ grub_linux_boot (void)
   prot_code = (char *) GRUB_OFW_LINUX_KERNEL_ADDR;
   grub_memcpy (prot_code, kernel_addr, kernel_size);
 
+  jumpvector.kernel_entry = params->code32_start;
+  jumpvector.kernel_cs = 0x10;
+  jump_start = (void *) &jumpvector;
+
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+  asm volatile ("movl %0, %%esi" : : "m" (params));
+  asm volatile ("movl %0, %%ecx" : : "m" (prot_code));
+  asm volatile ("xorl %%ebx, %%ebx" : : );
+
+  asm volatile ( "mov $24, %%ax" : : );
+  asm volatile ( "mov %%ax, %%ds" : : );
+  asm volatile ( "mov %%ax, %%ss" : : );
+  asm volatile ( "mov %%esi, %%esp" : : );
+
+  /* Enter Linux.  */
+  asm volatile ( "ljmp *(%%ecx)" : :);
+
+#if 0
   asm volatile ("movl %0, %%esi" : : "m" (params));
   asm volatile ("movl %%esi, %%esp" : : );
   asm volatile ("movl %0, %%ecx" : : "m" (prot_code));
   asm volatile ("xorl %%ebx, %%ebx" : : );
   asm volatile ("jmp *%%ecx" : : );
+#endif
 
   return GRUB_ERR_NONE;
 }
diff --git a/normal/x86_64/setjmp.S b/normal/x86_64/setjmp.S
new file mode 100644
index 0000000..4c8d4b3
--- /dev/null
+++ b/normal/x86_64/setjmp.S
@@ -0,0 +1,60 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+	.file	"setjmp.S"
+
+	.text
+
+/*
+ *  jmp_buf:
+ *   rbx rsp rbp r12 r13 r14 r15 rip
+ *   0   8   16  24  32  40  48  56
+ */
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+	pop	%rsi		/* Return address, and adjust the stack */
+	xorq	%rax, %rax
+	movq	%rbx, 0(%rdi)	/* RBX */
+	movq	%rsp, 8(%rdi)   /* RSP */
+	push	%rsi
+	movq	%rbp, 16(%rdi)	/* RBP */
+	movq	%r12, 24(%rdi)	/* R12 */
+	movq	%r13, 32(%rdi)	/* R13 */
+	movq	%r14, 40(%rdi)	/* R14 */
+	movq	%r15, 48(%rdi)	/* R15 */
+	movq	%rsi, 56(%rdi)	/* RSI */
+	ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+	movl	%esi, %eax
+	movq	(%rdi), %rbx
+	movq	8(%rdi), %rsp
+	movq	16(%rdi), %rbp
+	movq	24(%rdi), %r12
+	movq    32(%rdi), %r13
+	movq    40(%rdi), %r14
+	movq    48(%rdi), %r15
+	jmp	*56(%rdi)
diff --git a/term/efi/console.c b/term/efi/console.c
index af198e5..e5c02ad 100644
--- a/term/efi/console.c
+++ b/term/efi/console.c
@@ -36,6 +36,54 @@ grub_console_highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK,
 
 static int read_key = -1;
 
+static grub_uint32_t
+map_char (grub_uint32_t c)
+{
+  if (c > 0x7f)
+    {
+      /* Map some unicode characters to the EFI character.  */
+      switch (c)
+	{
+	case 0x2190:	/* left arrow */
+	  c = 0x25c4;
+	  break;
+	case 0x2191:	/* up arrow */
+	  c = 0x25b2;
+	  break;
+	case 0x2192:	/* right arrow */
+	  c = 0x25ba;
+	  break;
+	case 0x2193:	/* down arrow */
+	  c = 0x25bc;
+	  break;
+	case 0x2501:	/* horizontal line */
+	  c = 0x2500;
+	  break;
+	case 0x2503:	/* vertical line */
+	  c = 0x2502;
+	  break;
+	case 0x250F:	/* upper-left corner */
+	  c = 0x250c;
+	  break;
+	case 0x2513:	/* upper-right corner */
+	  c = 0x2510;
+	  break;
+	case 0x2517:	/* lower-left corner */
+	  c = 0x2514;
+	  break;
+	case 0x251B:	/* lower-right corner */
+	  c = 0x2518;
+	  break;
+
+	default:
+	  c = '?';
+	  break;
+	}
+    }
+
+  return c;
+}
+
 static void
 grub_console_putchar (grub_uint32_t c)
 {
@@ -48,14 +96,14 @@ grub_console_putchar (grub_uint32_t c)
   if (c > 0xffff)
     c = '?';
 
-  str[0] = (grub_efi_char16_t)  (c & 0xffff);
+  str[0] = (grub_efi_char16_t)  map_char (c & 0xffff);
   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,8 +124,8 @@ grub_console_checkkey (void)
     return 1;
 
   i = grub_efi_system_table->con_in;
-  status = i->read_key_stroke (i, &key);
-#if 1
+  status = efi_call_2 (i->read_key_stroke, i, &key);
+#if 0
   switch (status)
     {
     case GRUB_EFI_SUCCESS:
@@ -169,9 +217,9 @@ 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;
+	return -1;
       
       grub_console_checkkey ();
     }
@@ -189,7 +237,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 +262,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 +273,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 +287,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 +320,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..9bd4264 100644
--- a/util/i386/efi/grub-mkimage.c
+++ b/util/i386/efi/grub-mkimage.c
@@ -31,16 +31,56 @@
 #include <grub/efi/pe32.h>
 #include <grub/machine/kernel.h>
 
+#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 + sizeof (Elf_Ehdr) + 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.  */

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-20 17:04 [PATCH] New x86_64 EFI patch Bean
@ 2008-06-21 17:04 ` Bean
  2008-06-23 11:58   ` Isaac Dupree
  2008-06-24 12:52   ` Isaac Dupree
  2008-07-03 18:11 ` Marco Gerards
  1 sibling, 2 replies; 45+ messages in thread
From: Bean @ 2008-06-21 17:04 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 802 bytes --]

On Sat, Jun 21, 2008 at 1:04 AM, Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> This new patch add the following function to the original x86_64 EFI patch:
>
> 1, Fix menu drawing problem
> It maps the unicode char to EFI char so that the rectangle box is
> showed properly
>
> 2, Handle command line option for chainloader command
>
> 3, Add new command appleloader
> The command is used to enable bios boot in apple's bootcamp, for example
>
> boot from legacy mbr:
> appleloader HD
> boot
>
> boot from legacy cd:
> appleloader CD
> boot
>
> boot from usb:
> appleloader USB
> boot
>
> The usb booting may not work in some machine.

Hi,

I also fix a few problem in the linux loader, now it can load both 686
and x86_64 kernel from 64-bit EFI firmware.

Would someone test it in 32-bit EFI ?

-- 
Bean

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: efi_5.diff --]
[-- Type: text/x-diff; name=efi_5.diff, Size: 117014 bytes --]

diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 311b6ab..99bb0d4 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -74,8 +74,8 @@ sbin_SCRIPTS = grub-install
 grub_install_SOURCES = util/i386/efi/grub-install.in
 
 # Modules.
-pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
-	_linux.mod linux.mod cpuid.mod halt.mod reboot.mod
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
+	_linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
 
 # For kernel.mod.
 kernel_mod_EXPORTS = no
@@ -123,6 +123,11 @@ chain_mod_SOURCES = loader/efi/chainloader_normal.c
 chain_mod_CFLAGS = $(COMMON_CFLAGS)
 chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For _linux.mod.
 _linux_mod_SOURCES = loader/i386/efi/linux.c
 _linux_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -148,4 +153,14 @@ reboot_mod_SOURCES = commands/reboot.c
 reboot_mod_CFLAGS = $(COMMON_CFLAGS)
 reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 include $(srcdir)/conf/common.mk
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
new file mode 100644
index 0000000..daa416c
--- /dev/null
+++ b/conf/x86_64-efi.rmk
@@ -0,0 +1,169 @@
+# -*- 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 appleldr.mod \
+	cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.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 machine/loader.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 appleldr.mod.
+appleldr_mod_SOURCES = loader/efi/appleloader.c
+appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
+appleldr_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)
+
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_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/chainloader.h b/include/grub/efi/chainloader.h
index 470132b..d5c11e3 100644
--- a/include/grub/efi/chainloader.h
+++ b/include/grub/efi/chainloader.h
@@ -19,6 +19,6 @@
 #ifndef GRUB_EFI_CHAINLOADER_HEADER
 #define GRUB_EFI_CHAINLOADER_HEADER	1
 
-void grub_chainloader_cmd (const char *filename);
+void grub_rescue_cmd_chainloader (int argc, char *argv[]);
 
 #endif /* ! GRUB_EFI_CHAINLOADER_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/efi/uga_draw.h b/include/grub/efi/uga_draw.h
new file mode 100755
index 0000000..9350430
--- /dev/null
+++ b/include/grub/efi/uga_draw.h
@@ -0,0 +1,76 @@
+/* uga_draw.h - definitions of the uga draw protocol */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+/* The console control protocol is not a part of the EFI spec,
+   but defined in Intel's Sample Implementation.  */
+
+#ifndef GRUB_EFI_UGA_DRAW_HEADER
+#define GRUB_EFI_UGA_DRAW_HEADER	1
+
+#define GRUB_EFI_UGA_DRAW_GUID \
+  { 0x982c298b, 0xf4fa, 0x41cb, { 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 }}
+
+enum grub_efi_uga_blt_operation
+{
+  GRUB_EFI_UGA_VIDEO_FILL,
+  GRUB_EFI_UGA_VIDEO_TO_BLT,
+  GRUB_EFI_UGA_BLT_TO_VIDEO,
+  GRUB_EFI_UGA_VIDEO_TO_VIDEO,
+  GRUB_EFI_UGA_GLT_MAX
+};
+
+struct grub_efi_uga_pixel
+{
+  grub_uint8_t Blue;
+  grub_uint8_t Green;
+  grub_uint8_t Red;
+  grub_uint8_t Reserved;
+};
+
+struct grub_efi_uga_draw_protocol
+{
+  grub_efi_status_t
+  (*get_mode) (struct grub_efi_uga_draw_protocol *this,
+	       grub_uint32_t *width,
+	       grub_uint32_t *height,
+	       grub_uint32_t *depth,
+	       grub_uint32_t *refresh_rate);
+
+  grub_efi_status_t
+  (*set_mode) (struct grub_efi_uga_draw_protocol *this,
+	       grub_uint32_t width,
+	       grub_uint32_t height,
+	       grub_uint32_t depth,
+	       grub_uint32_t refresh_rate);
+
+  grub_efi_status_t
+  (*blt) (struct grub_efi_uga_draw_protocol *this,
+	  struct grub_efi_uga_pixel *blt_buffer,
+	  enum grub_efi_uga_blt_operation blt_operation,
+	  grub_efi_uintn_t src_x,
+	  grub_efi_uintn_t src_y,
+	  grub_efi_uintn_t dest_x,
+	  grub_efi_uintn_t dest_y,
+	  grub_efi_uintn_t width,
+	  grub_efi_uintn_t height,
+	  grub_efi_uintn_t delta);
+};
+typedef struct grub_efi_uga_draw_protocol grub_efi_uga_draw_protocol_t;
+
+#endif /* ! GRUB_EFI_UGA_DRAW_HEADER */
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/i386/efi/pci.h b/include/grub/i386/efi/pci.h
new file mode 100755
index 0000000..8480fd7
--- /dev/null
+++ b/include/grub/i386/efi/pci.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/pc/pci.h>
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
old mode 100644
new mode 100755
index 7a8e006..505fb8a
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -44,14 +44,44 @@
 #define GRUB_LINUX_SETUP_MOVE_SIZE	0x9100
 #define GRUB_LINUX_CL_MAGIC		0xA33F
 
+#ifdef __x86_64__
+
 #define GRUB_LINUX_EFI_SIGNATURE	\
-  ('E' << 24 | 'F' << 16 | 'I' << 8 | 'L')
+  ('4' << 24 | '6' << 16 | 'L' << 8 | 'E')
+
+#else
+
+#define GRUB_LINUX_EFI_SIGNATURE	\
+  ('2' << 24 | '3' << 16 | 'L' << 8 | 'E')
+
+#endif
+
+#define GRUB_LINUX_EFI_SIGNATURE_0204	\
+  ('L' << 24 | 'I' << 16 | 'F' << 8 | 'E')
 
 #define GRUB_LINUX_OFW_SIGNATURE	\
   (' ' << 24 | 'W' << 16 | 'F' << 8 | 'O')
 
 #ifndef ASM_FILE
 
+#define GRUB_E820_RAM        1
+#define GRUB_E820_RESERVED   2
+#define GRUB_E820_ACPI       3
+#define GRUB_E820_NVS        4
+#define GRUB_E820_EXEC_CODE  5
+
+#define GRUB_E820_MAX_ENTRY  128
+
+struct grub_e820_mmap
+{
+  grub_uint64_t addr;
+  grub_uint64_t size;
+  grub_uint32_t type;
+} __attribute__((packed));
+
+#define GRUB_VIDEO_TYPE_VLFB	0x23    /* VESA VGA in graphic mode     */
+#define GRUB_VIDEO_TYPE_EFI	0x70
+
 /* For the Linux/i386 boot protocol version 2.03.  */
 struct linux_kernel_header
 { 
@@ -67,6 +97,7 @@ struct linux_kernel_header
   grub_uint16_t vid_mode;		/* Video mode control */
   grub_uint16_t root_dev;		/* Default root device number */
   grub_uint16_t boot_flag;		/* 0xAA55 magic number */
+
   grub_uint16_t jump;			/* Jump instruction */
   grub_uint32_t header;			/* Magic signature "HdrS" */
   grub_uint16_t version;		/* Boot protocol version supported */
@@ -164,26 +195,74 @@ struct linux_kernel_params
   grub_uint32_t ofw_cif_handler;	/* b8 */
   grub_uint32_t ofw_idt;		/* bc */
 
-  grub_uint8_t padding7[0x1c0 - 0xc0];
-  
-  grub_uint32_t efi_signature;		/* 1c0 */
-  grub_uint32_t efi_system_table;	/* 1c4 */
-  grub_uint32_t efi_mem_desc_size;	/* 1c8 */
-  grub_uint32_t efi_mem_desc_version;	/* 1cc */
-  grub_uint32_t efi_mmap;		/* 1d0 */
-  grub_uint32_t efi_mmap_size;		/* 1d4 */
-  
-  grub_uint8_t padding8[0x1e0 - 0x1d8];
+  grub_uint8_t padding7[0x1b8 - 0xc0];
+
+  union
+    {
+      struct
+        {
+          grub_uint32_t efi_system_table;	/* 1b8 */
+          grub_uint32_t padding7_1;		/* 1bc */
+          grub_uint32_t efi_signature;		/* 1c0 */
+          grub_uint32_t efi_mem_desc_size;	/* 1c4 */
+          grub_uint32_t efi_mem_desc_version;	/* 1c8 */
+          grub_uint32_t efi_mmap_size;		/* 1cc */
+          grub_uint32_t efi_mmap;		/* 1d0 */
+        } v0204;
+      struct
+        {
+          grub_uint32_t padding7_1;		/* 1b8 */
+          grub_uint32_t padding7_2;		/* 1bc */
+          grub_uint32_t efi_signature;		/* 1c0 */
+          grub_uint32_t efi_system_table;	/* 1c4 */
+          grub_uint32_t efi_mem_desc_size;	/* 1c8 */
+          grub_uint32_t efi_mem_desc_version;	/* 1cc */
+          grub_uint32_t efi_mmap;		/* 1d0 */
+          grub_uint32_t efi_mmap_size;		/* 1d4 */
+          grub_uint32_t efi_system_table_hi;	/* 1d8 */
+          grub_uint32_t efi_mmap_hi;		/* 1dc */
+        } v0206;
+    };
   
   grub_uint32_t alt_mem;		/* 1e0 */
   
-  grub_uint8_t padding9[0x1e8 - 0x1e4];
+  grub_uint8_t padding8[0x1e8 - 0x1e4];
   
   grub_uint32_t mmap_size;		/* 1e8 */
 
-  grub_uint8_t padding10[0x1ff - 0x1ec];
+  grub_uint8_t padding9[0x1f1 - 0x1ec];
+
+  grub_uint8_t setup_sects;		/* The size of the setup in sectors */
+  grub_uint16_t root_flags;		/* If the root is mounted readonly */
+  grub_uint16_t syssize;		/* obsolete */
+  grub_uint16_t swap_dev;		/* obsolete */
+  grub_uint16_t ram_size;		/* obsolete */
+  grub_uint16_t vid_mode;		/* Video mode control */
+  grub_uint16_t root_dev;		/* Default root device number */
   
+  grub_uint8_t padding10;		/* 1fe */
   grub_uint8_t ps_mouse;		/* 1ff */
+
+  grub_uint16_t jump;			/* Jump instruction */
+  grub_uint32_t header;			/* Magic signature "HdrS" */
+  grub_uint16_t version;		/* Boot protocol version supported */
+  grub_uint32_t realmode_swtch;		/* Boot loader hook */
+  grub_uint16_t start_sys;		/* The load-low segment (obsolete) */
+  grub_uint16_t kernel_version;		/* Points to kernel version string */
+  grub_uint8_t type_of_loader;		/* Boot loader identifier */
+  grub_uint8_t loadflags;		/* Boot protocol option flags */
+  grub_uint16_t setup_move_size;	/* Move to high memory size */
+  grub_uint32_t code32_start;		/* Boot loader hook */
+  grub_uint32_t ramdisk_image;		/* initrd load address */
+  grub_uint32_t ramdisk_size;		/* initrd size */
+  grub_uint32_t bootsect_kludge;	/* obsolete */
+  grub_uint16_t heap_end_ptr;		/* Free memory after setup end */
+  grub_uint16_t pad1;			/* Unused */
+  grub_uint32_t cmd_line_ptr;		/* Points to the kernel command line */
+
+  grub_uint8_t pad2[164];		/* 22c */
+  struct grub_e820_mmap e820_map[GRUB_E820_MAX_ENTRY];	/* 2d0 */
+
 } __attribute__ ((packed));
 #endif /* ! ASM_FILE */
 
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/pci.h b/include/grub/pci.h
index 7108886..abc5c90 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -22,6 +22,19 @@
 #include <grub/types.h>
 #include <grub/symbol.h>
 
+#define  GRUB_PCI_ADDR_SPACE_MASK	0x01
+#define  GRUB_PCI_ADDR_SPACE_MEMORY	0x00
+#define  GRUB_PCI_ADDR_SPACE_IO		0x01
+
+#define  GRUB_PCI_ADDR_MEM_TYPE_MASK	0x06
+#define  GRUB_PCI_ADDR_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  GRUB_PCI_ADDR_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
+#define  GRUB_PCI_ADDR_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  GRUB_PCI_ADDR_MEM_PREFETCH	0x08	/* prefetchable */
+
+#define  GRUB_PCI_ADDR_MEM_MASK		~0xf
+#define  GRUB_PCI_ADDR_IO_MASK		~0x03
+
 typedef grub_uint32_t grub_pci_id_t;
 typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
 				       grub_pci_id_t pciid);
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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..4368a82
--- /dev/null
+++ b/include/grub/x86_64/efi/loader.h
@@ -0,0 +1,32 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_LOADER_MACHINE_HEADER
+#define GRUB_LOADER_MACHINE_HEADER	1
+
+#include <grub/types.h>
+#include <grub/symbol.h>
+
+/* 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[]);
+
+void EXPORT_FUNC(grub_linux_real_boot) (void);
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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/pci.h b/include/grub/x86_64/efi/pci.h
new file mode 100755
index 0000000..8480fd7
--- /dev/null
+++ b/include/grub/x86_64/efi/pci.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/pc/pci.h>
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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_MACHINE_TIME_HEADER
+#define GRUB_MACHINE_TIME_HEADER	1
+
+#include <grub/efi/time.h>
+
+#endif /* ! GRUB_MACHINE_TIME_HEADER */
diff --git a/include/grub/x86_64/linux.h b/include/grub/x86_64/linux.h
new file mode 100644
index 0000000..19ea936
--- /dev/null
+++ b/include/grub/x86_64/linux.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/i386/linux.h>
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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <grub/env.h>
 #include <grub/cache.h>
 
-#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..5098ccd 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;
@@ -218,7 +218,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
     {
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-#if GRUB_CPU_SIZEOF_VOID_P < 8
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
 	  && desc->physical_start <= 0xffffffff
 #endif
 	  && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000
@@ -234,7 +234,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
 	      desc->physical_start = 0x100000;
 	    }
 	  
-#if GRUB_CPU_SIZEOF_VOID_P < 8
+#if GRUB_TARGET_SIZEOF_VOID_P < 8
 	  if (BYTES_TO_PAGES (filtered_desc->physical_start)
 	      + filtered_desc->num_pages
 	      > BYTES_TO_PAGES (0x100000000LL))
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 <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/env.h>
+#include <grub/efi/efi.h>
 
 /* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+/*
+ * 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..59629b4
--- /dev/null
+++ b/kern/x86_64/efi/startup.S
@@ -0,0 +1,87 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/symbol.h>
+#include <grub/boot.h>
+
+        .file   "startup.S"
+        .text
+        .globl  start, _start
+        .code64
+
+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
+
+	.code32
+
+FUNCTION(grub_linux_real_boot)
+        /* Turn off PG bit in CR0 and set CR3 to zero.  */
+        movl    %cr0, %eax
+        andl    $0x7FFFFFFF, %eax
+        movl    %eax, %cr0
+
+        /* Setup EFER (Extended Feature Enable Register).  */
+        movl    $0xc0000080, %ecx
+        rdmsr
+
+        /* Disable Long Mode.  */
+        andl    $0xFFFFFEFF, %eax
+
+        /* Make changes effective.  */
+        wrmsr
+
+        /* Disable PAE.  */
+        xorl    %eax, %eax
+        movl    %eax, %cr4
+
+      	jmp     *%ebx
diff --git a/loader/efi/appleloader.c b/loader/efi/appleloader.c
new file mode 100755
index 0000000..910a13d
--- /dev/null
+++ b/loader/efi/appleloader.c
@@ -0,0 +1,208 @@
+/* appleloader.c - apple legacy boot loader.  */
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/loader.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+static grub_dl_t my_mod;
+
+static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
+
+static grub_err_t
+grub_appleloader_unload (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_1 (b->unload_image, image_handle);
+
+  grub_free (cmdline);
+  cmdline = 0;
+
+  grub_dl_unref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_appleloader_boot (void)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  efi_call_3 (b->start_image, image_handle, 0, 0);
+
+  grub_appleloader_unload ();
+
+  return grub_errno;
+}
+
+/* early 2006 Core Duo / Core Solo models  */
+static grub_uint8_t devpath_1[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2006 Mac Pro (and probably other Core 2 models)  */
+static grub_uint8_t devpath_2[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* mid-2007 MBP ("Santa Rosa" based models)  */
+static grub_uint8_t devpath_3[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+/* early-2008 MBA  */
+static grub_uint8_t devpath_4[] =
+{
+  0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
+  0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
+  0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
+};
+
+struct devdata
+{
+  char *model;
+  grub_efi_device_path_t *devpath;
+};
+
+struct devdata devs[] =
+{
+  {"Core Duo/Solo", (grub_efi_device_path_t *) devpath_1},
+  {"Mac Pro", (grub_efi_device_path_t *) devpath_2},
+  {"MBP", (grub_efi_device_path_t *) devpath_3},
+  {"MBA", (grub_efi_device_path_t *) devpath_4},
+  {NULL, NULL},
+};
+
+static grub_err_t
+grub_cmd_appleloader (struct grub_arg_list *state __attribute__ ((unused)),
+                      int argc, char *argv[])
+{
+  grub_efi_boot_services_t *b;
+  grub_efi_loaded_image_t *loaded_image;
+  struct devdata *pdev;
+
+  grub_dl_ref (my_mod);
+
+  /* Initialize some global variables.  */
+  image_handle = 0;
+
+  b = grub_efi_system_table->boot_services;
+
+  for (pdev = devs ; pdev->devpath ; pdev++)
+    if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
+                    NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
+      break;
+
+  if (! pdev->devpath)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "can't find model");
+      goto fail;
+    }
+
+  grub_printf ("Model : %s\n", pdev->model);
+
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  if (! loaded_image)
+    {
+      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
+      goto fail;
+    }
+
+  if (argc > 0)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 0, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 0; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
+  grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
+
+  return 0;
+
+ fail:
+
+  grub_dl_unref (my_mod);
+  return grub_errno;
+}
+
+GRUB_MOD_INIT(appleloader)
+{
+  grub_register_command ("appleloader", grub_cmd_appleloader,
+			 GRUB_COMMAND_FLAG_BOTH,
+			 "appleloader [OPTS]",
+			 "Boot legacy system.", 0);
+
+  my_mod = mod;
+}
+
+GRUB_MOD_FINI(appleloader)
+{
+  grub_unregister_command ("appleloader");
+}
diff --git a/loader/efi/chainloader.c b/loader/efi/chainloader.c
index 19285d9..fbb7aac 100644
--- a/loader/efi/chainloader.c
+++ b/loader/efi/chainloader.c
@@ -40,6 +40,7 @@ static grub_efi_physical_address_t address;
 static grub_efi_uintn_t pages;
 static grub_efi_device_path_t *file_path;
 static grub_efi_handle_t image_handle;
+static grub_efi_char16_t *cmdline;
 
 static grub_err_t
 grub_chainloader_unload (void)
@@ -47,9 +48,12 @@ 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);
+  efi_call_1 (b->unload_image, image_handle);
+  efi_call_2 (b->free_pages, address, pages);
+
   grub_free (file_path);
+  grub_free (cmdline);
+  cmdline = 0;
   
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
@@ -64,7 +68,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)
@@ -86,7 +90,7 @@ grub_chainloader_boot (void)
     }
 
   if (exit_data)
-    b->free_pool (exit_data);
+    efi_call_1 (b->free_pool, exit_data);
 
   grub_chainloader_unload ();
   
@@ -175,7 +179,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
 }
 
 void
-grub_chainloader_cmd (const char *filename)
+grub_rescue_cmd_chainloader (int argc, char *argv[])
 {
   grub_file_t file = 0;
   grub_ssize_t size;
@@ -185,6 +189,14 @@ grub_chainloader_cmd (const char *filename)
   grub_device_t dev = 0;
   grub_efi_device_path_t *dp = 0;
   grub_efi_loaded_image_t *loaded_image;
+  char *filename;
+
+  if (argc == 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  filename = argv[0];
   
   grub_dl_ref (my_mod);
 
@@ -227,7 +239,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 +256,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)
@@ -269,6 +281,36 @@ grub_chainloader_cmd (const char *filename)
   loaded_image->device_handle = dev_handle;
   
   grub_file_close (file);
+
+  if (argc > 1)
+    {
+      int i, len;
+      grub_efi_char16_t *p16;
+
+      for (i = 1, len = 0; i < argc; i++)
+        len += grub_strlen (argv[i]) + 1;
+
+      len *= sizeof (grub_efi_char16_t);
+      cmdline = p16 = grub_malloc (len);
+      if (! cmdline)
+        goto fail;
+
+      for (i = 1; i < argc; i++)
+        {
+          char *p8;
+
+          p8 = argv[i];
+          while (*p8)
+            *(p16++) = *(p8++);
+
+          *(p16++) = ' ';
+        }
+      *(--p16) = 0;
+
+      loaded_image->load_options = cmdline;
+      loaded_image->load_options_size = len;
+    }
+
   grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
   return;
   
@@ -284,20 +326,11 @@ 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);
 }
 
-static void
-grub_rescue_cmd_chainloader (int argc, char *argv[])
-{
-  if (argc == 0)
-    grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
-  else
-    grub_chainloader_cmd (argv[0]);
-}
-
 static const char loader_name[] = "chainloader";
 
 GRUB_MOD_INIT(chainloader)
diff --git a/loader/efi/chainloader_normal.c b/loader/efi/chainloader_normal.c
index 2ea3368..455669e 100644
--- a/loader/efi/chainloader_normal.c
+++ b/loader/efi/chainloader_normal.c
@@ -29,7 +29,7 @@ chainloader_command (struct grub_arg_list *state __attribute__ ((unused)),
   if (argc == 0)
     grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
   else
-    grub_chainloader_cmd (args[0]);
+    grub_rescue_cmd_chainloader (argc, args);
   return grub_errno;
 }
 
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index ee3fb99..07b825f 100644
--- a/loader/i386/efi/linux.c
+++ b/loader/i386/efi/linux.c
@@ -30,6 +30,11 @@
 #include <grub/cpu/linux.h>
 #include <grub/efi/api.h>
 #include <grub/efi/efi.h>
+#include <grub/efi/uga_draw.h>
+#include <grub/pci.h>
+
+#define GRUB_EFI_CL_OFFSET	0x1000
+#define GRUB_EFI_CL_END_OFFSET	0x2000
 
 #define NEXT_MEMORY_DESCRIPTOR(desc, size)      \
   ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
@@ -55,34 +60,30 @@ static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
     /* Code segment.  */
     0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
     /* Data segment.  */
-    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00,
   };
 
 struct gdt_descriptor
 {
-  grub_uint16_t dummy;
   grub_uint16_t limit;
-  grub_uint32_t base;
-} __attribute__ ((aligned(4), packed));
+  void *base;
+} __attribute__ ((packed));
 
 static struct gdt_descriptor gdt_desc =
   {
-    0,
     sizeof (gdt) - 1,
-    (grub_addr_t) gdt
+    gdt
   };
 
 struct idt_descriptor
 {
-  grub_uint16_t dummy;
   grub_uint16_t limit;
-  grub_uint32_t base;
-} __attribute__ ((aligned(4)));
+  void *base;
+} __attribute__ ((packed));
 
 static struct idt_descriptor idt_desc =
   {
     0,
-    0,
     0
   };
 
@@ -156,23 +157,25 @@ free_pages (void)
 /* Allocate pages for the real mode code and the protected mode code
    for linux as well as a memory map buffer.  */
 static int
-allocate_pages (grub_size_t real_size, grub_size_t prot_size)
+allocate_pages (grub_size_t prot_size)
 {
   grub_efi_uintn_t desc_size;
   grub_efi_memory_descriptor_t *mmap, *mmap_end;
   grub_efi_uintn_t mmap_size, tmp_mmap_size;
   grub_efi_memory_descriptor_t *desc;
+  grub_size_t real_size;
   
   /* Make sure that each size is aligned to a page boundary.  */
-  real_size = page_align (real_size + GRUB_DISK_SECTOR_SIZE);
+  real_size = GRUB_EFI_CL_END_OFFSET;
   prot_size = page_align (prot_size);
   mmap_size = find_mmap_size ();
 
   grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
-		real_size, prot_size, mmap_size);
+		(unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
   
   /* Calculate the number of pages; Combine the real mode code with
      the memory map buffer for simplicity.  */
+  //real_mode_pages = (page_align (GRUB_LINUX_CL_END_OFFSET + 1) >> 12);
   real_mode_pages = ((real_size + mmap_size) >> 12);
   prot_mode_pages = (prot_size >> 12);
   
@@ -217,8 +220,8 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
 	  if (addr < 0x10000)
 	    continue;
 
-	  grub_dprintf ("linux", "trying to allocate %u pages at %x\n",
-			real_mode_pages, (unsigned) addr);
+	  grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
+			(unsigned) real_mode_pages, (unsigned long) addr);
 	  real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
 	  if (! real_mode_mem)
 	    grub_fatal ("cannot allocate pages");
@@ -246,6 +249,11 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
       goto fail;
     }
 
+  grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
+                "prot_mode_mem = %lx, prot_mode_pages = %x\n",
+                (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
+                (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
+
   grub_free (mmap);
   return 1;
 
@@ -255,56 +263,189 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
   return 0;
 }
 
+static void
+grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
+                      grub_uint64_t start, grub_uint64_t size,
+                      grub_uint32_t type)
+{
+  int n = *e820_num;
+
+  if (n >= GRUB_E820_MAX_ENTRY)
+    grub_fatal ("Too many e820 memory map entries");
+
+  if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
+      (e820_map[n - 1].type == type))
+      e820_map[n - 1].size += size;
+  else
+    {
+      e820_map[n].addr = start;
+      e820_map[n].size = size;
+      e820_map[n].type = type;
+      (*e820_num)++;
+    }
+}
+
+#ifdef __x86_64__
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+#endif
+
 static grub_err_t
 grub_linux_boot (void)
 {
-  struct linux_kernel_header *lh;
   struct linux_kernel_params *params;
   grub_efi_uintn_t mmap_size;
   grub_efi_uintn_t map_key;
   grub_efi_uintn_t desc_size;
   grub_efi_uint32_t desc_version;
+  grub_efi_memory_descriptor_t *desc;
+  int e820_num;
   
-  lh = real_mode_mem;
   params = real_mode_mem;
 
-  grub_dprintf ("linux", "code32_start = %x, idt_desc = %x, gdt_desc = %x\n",
-		(unsigned) lh->code32_start, (grub_addr_t) &(idt_desc.limit),
-		(grub_addr_t) &(gdt_desc.limit));
-  grub_dprintf ("linux", "idt = %x:%x, gdt = %x:%x\n",
-		(unsigned) idt_desc.limit, (unsigned) idt_desc.base,
-		(unsigned) gdt_desc.limit, (unsigned) gdt_desc.base);
+  grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
+		(unsigned) params->code32_start,
+                (unsigned long) &(idt_desc.limit),
+		(unsigned long) &(gdt_desc.limit));
+  grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
+		(unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
+		(unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
+
   mmap_size = find_mmap_size ();
   if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
 			       &desc_size, &desc_version) <= 0)
     grub_fatal ("cannot get memory map");
 
+  e820_num = 0;
+  for (desc = mmap_buf;
+       desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
+       desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
+    {
+      switch (desc->type)
+        {
+        case GRUB_EFI_ACPI_RECLAIM_MEMORY:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_ACPI);
+          break;
+
+        case GRUB_EFI_ACPI_MEMORY_NVS:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_NVS);
+          break;
+
+        case GRUB_EFI_RUNTIME_SERVICES_CODE:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_EXEC_CODE);
+          break;
+
+        case GRUB_EFI_LOADER_CODE:
+        case GRUB_EFI_LOADER_DATA:
+        case GRUB_EFI_BOOT_SERVICES_CODE:
+        case GRUB_EFI_BOOT_SERVICES_DATA:
+        case GRUB_EFI_CONVENTIONAL_MEMORY:
+          {
+            grub_uint64_t start, size, end;
+
+            start = desc->physical_start;
+            size = desc->num_pages << 12;
+            end = start + size;
+
+            /* Skip A0000 - 100000 region.  */
+            if ((start < 0x100000ULL) && (end > 0xA0000ULL))
+              {
+                if (start < 0xA0000ULL)
+                  {
+                    grub_e820_add_region (params->e820_map, &e820_num,
+                                          start,
+                                          0xA0000ULL - start,
+                                          GRUB_E820_RAM);
+                  }
+
+                if (end <= 0x100000ULL)
+                  continue;
+
+                start = 0x100000ULL;
+                size = end - start;
+              }
+
+            grub_e820_add_region (params->e820_map, &e820_num,
+                                  start, size, GRUB_E820_RAM);
+            break;
+          }
+
+        default:
+          grub_e820_add_region (params->e820_map, &e820_num,
+                                desc->physical_start,
+                                desc->num_pages << 12,
+                                GRUB_E820_RESERVED);
+        }
+    }
+
+  params->mmap_size = e820_num;
+
   if (! grub_efi_exit_boot_services (map_key))
-    grub_fatal ("cannot exit boot services");
+     grub_fatal ("cannot exit boot services");
 
   /* Note that no boot services are available from here.  */
 
+  /* Pass EFI parameters.  */
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_mem_desc_size = desc_size;
+      params->v0206.efi_mem_desc_version = desc_version;
+      params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0206.efi_mmap_size = mmap_size;
+#ifdef __x86_64__
+      params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_mem_desc_size = desc_size;
+      params->v0204.efi_mem_desc_version = desc_version;
+      params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
+      params->v0204.efi_mmap_size = mmap_size;
+    }
+
   /* Hardware interrupts are not safe any longer.  */
   asm volatile ("cli" : : );
   
-  /* Pass EFI parameters.  */
-  params->efi_mem_desc_size = desc_size;
-  params->efi_mem_desc_version = desc_version;
-  params->efi_mmap = (grub_addr_t) mmap_buf;
-  params->efi_mmap_size = mmap_size;
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+#ifdef __x86_64__
+
+  jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
+  jumpvector.kernel_cs = 0x10;
+
+  asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
+  asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
+
+  asm volatile ( "ljmp *%0" : : "m" (jumpvector));
+
+#else
 
   /* Pass parameters.  */
+  asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
   asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
-  asm volatile ("movl %0, %%ecx" : : "m" (lh->code32_start));
-  asm volatile ("xorl %%ebx, %%ebx" : : );
 
-  /* Load the IDT and the GDT for the bootstrap.  */
-  asm volatile ("lidt %0" : : "m" (idt_desc.limit));
-  asm volatile ("lgdt %0" : : "m" (gdt_desc.limit));
+  asm volatile ("xorl %%ebx, %%ebx" : : );
 
   /* Enter Linux.  */
   asm volatile ("jmp *%%ecx" : : );
   
+#endif
+
   /* Never reach here.  */
   return GRUB_ERR_NONE;
 }
@@ -318,6 +459,111 @@ grub_linux_unload (void)
   return GRUB_ERR_NONE;
 }
 
+grub_uint64_t video_base;
+
+static int
+grub_find_video_card (int bus, int dev, int func,
+                      grub_pci_id_t pciid __attribute__ ((unused)))
+{
+  grub_pci_address_t addr;
+
+  addr = grub_pci_make_address (bus, dev, func, 2);
+
+  if (grub_pci_read (addr) >> 24 == 0x3)
+    {
+      int i;
+
+      addr = grub_pci_make_address (bus, dev, func, 4);
+      for (i = 0; i < 6; i++, addr += 4)
+        {
+          grub_uint32_t base, type;
+
+          base = grub_pci_read (addr);
+
+          if ((base == 0) || (base == 0xffffffff) ||
+              (base & GRUB_PCI_ADDR_SPACE_IO))
+            continue;
+
+          type = base & GRUB_PCI_ADDR_MEM_TYPE_MASK;
+          if (! (addr & GRUB_PCI_ADDR_MEM_PREFETCH))
+            {
+              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+                {
+                  i++;
+                  addr +=4 ;
+                }
+              continue;
+            }
+
+          base &= GRUB_PCI_ADDR_MEM_MASK;
+          if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
+            {
+              if (i == 5)
+                break;
+
+              video_base = grub_pci_read (addr + 4);
+              video_base <<= 32;
+            }
+
+          video_base |= base;
+
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
+static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
+
+static int
+grub_linux_setup_video (struct linux_kernel_params *params)
+{
+  grub_efi_uga_draw_protocol_t *c;
+  grub_uint32_t width, height, depth, rate;
+
+  c = grub_efi_locate_protocol (&uga_draw_guid, 0);
+  if (! c)
+    return 1;
+
+  if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
+    return 1;
+
+  grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate);
+
+  video_base = 0;
+  grub_pci_iterate (grub_find_video_card);
+
+  if (! video_base)
+    {
+      grub_printf ("Can\'t find frame buffer address\n");
+      return 1;
+    }
+
+  grub_printf ("Video frame buffer: %llx\n", (unsigned long long) video_base);
+
+  params->lfb_width = width;
+  params->lfb_height = height;
+  params->lfb_depth = depth;
+
+  /* FIXME: shouldn't use fixed value.  */
+  params->lfb_line_len = 8192;
+
+  params->lfb_base = video_base;
+  params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
+
+  params->red_mask_size = 8;
+  params->red_field_pos = 16;
+  params->green_mask_size = 8;
+  params->green_field_pos = 8;
+  params->blue_mask_size = 8;
+  params->blue_field_pos = 0;
+  params->reserved_mask_size = 8;
+  params->reserved_field_pos = 24;
+
+  return 0;
+}
+
 void
 grub_rescue_cmd_linux (int argc, char *argv[])
 {
@@ -329,6 +575,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   grub_ssize_t len;
   int i;
   char *dest;
+  int video_type;
 
   grub_dl_ref (my_mod);
   
@@ -384,19 +631,33 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
   prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
   
-  if (! allocate_pages (real_size, prot_size))
+  if (! allocate_pages (prot_size))
     goto fail;
   
+  params = (struct linux_kernel_params *) real_mode_mem;
+  grub_memset (params, 0, GRUB_EFI_CL_END_OFFSET);
+  grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
+
+  params->ps_mouse = params->padding10 =  0;
+
+  len = 0x400 - sizeof (lh);
+  if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
   /* XXX Linux assumes that only elilo can boot Linux on EFI!!!  */
-  lh.type_of_loader = 0x50;
+  params->type_of_loader = 0x50;
 
-  lh.cl_magic = GRUB_LINUX_CL_MAGIC;
-  lh.cl_offset = GRUB_LINUX_CL_END_OFFSET;
-  lh.cmd_line_ptr = (char *) real_mode_mem + GRUB_LINUX_CL_OFFSET;
-  lh.ramdisk_image = 0;
-  lh.ramdisk_size = 0;
+  params->cl_magic = GRUB_LINUX_CL_MAGIC;
+  params->cl_offset = 0x1000;
+  params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000;
+  params->ramdisk_image = 0;
+  params->ramdisk_size = 0;
 
-  params = (struct linux_kernel_params *) &lh;
+  params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
+  params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
 
   /* These are not needed to be precise, because Linux uses these values
      only to raise an error when the decompression code cannot find good
@@ -414,6 +675,23 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   params->have_vga = 0;
   params->font_size = 16; /* XXX */
 
+  if (grub_le_to_cpu16 (params->version) >= 0x0206)
+    {
+      params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
+      params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+#ifdef __x86_64__
+      params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
+#endif
+    }
+  else if (grub_le_to_cpu16 (params->version) >= 0x0204)
+    {
+      params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
+      params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
+    }
+
+#if 0
+  /* The structure is zeroed already.  */
+
   /* No VBE on EFI.  */
   params->lfb_width = 0;
   params->lfb_height = 0;
@@ -457,10 +735,6 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   /* No MCA on EFI.  */
   params->rom_config_len = 0;
 
-  params->efi_signature = GRUB_LINUX_EFI_SIGNATURE; /* XXX not used */
-  params->efi_system_table = (grub_addr_t) grub_efi_system_table;
-  /* The other EFI parameters are filled when booting.  */
-
   /* No need to fake the BIOS's memory map.  */
   params->mmap_size = 0;
 
@@ -478,22 +752,19 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   grub_memset (params->padding8, 0, sizeof (params->padding8));
   grub_memset (params->padding9, 0, sizeof (params->padding9));
   
-  /* Put the real mode code at the real location.  */
-  grub_memmove (real_mode_mem, &lh, sizeof (lh));
+#endif
 
-  len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
-  if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
-    {
-      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
-      goto fail;
-    }
+  /* The other EFI parameters are filled when booting.  */
+
+  grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
 
   /* XXX there is no way to know if the kernel really supports EFI.  */
   grub_printf ("   [Linux-EFI, setup=0x%x, size=0x%x]\n",
-	       real_size, prot_size);
+	       (unsigned) real_size, (unsigned) prot_size);
 
   /* Detect explicitly specified memory size, if any.  */
   linux_mem_size = 0;
+  video_type = 0;
   for (i = 1; i < argc; i++)
     if (grub_memcmp (argv[i], "mem=", 4) == 0)
       {
@@ -529,9 +800,22 @@ grub_rescue_cmd_linux (int argc, char *argv[])
 	      linux_mem_size <<= shift;
 	  }
       }
+    else if (grub_memcmp (argv[i], "video=", 6) == 0)
+      {
+        if (grub_memcmp (&argv[i][6], "vesafb", 6) == 0)
+          video_type = GRUB_VIDEO_TYPE_VLFB;
+        else if (grub_memcmp (&argv[i][6], "efifb", 5) == 0)
+          video_type = GRUB_VIDEO_TYPE_EFI;
+      }
+
+  if (video_type)
+    {
+      if (!  grub_linux_setup_video (params))
+        params->have_vga = video_type;
+    }
 
   /* Specify the boot file.  */
-  dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
+  dest = grub_stpcpy ((char *) real_mode_mem + GRUB_EFI_CL_OFFSET,
 		      "BOOT_IMAGE=");
   dest = grub_stpcpy (dest, argv[0]);
   
@@ -539,7 +823,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
   for (i = 1;
        i < argc
 	 && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
-						+ GRUB_LINUX_CL_END_OFFSET);
+						+ GRUB_EFI_CL_END_OFFSET);
        i++)
     {
       *dest++ = ' ';
@@ -601,7 +885,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
 
   lh = (struct linux_kernel_header *) real_mode_mem;
   
-  addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
+  addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
   if (linux_mem_size != 0 && linux_mem_size < addr_max)
     addr_max = linux_mem_size;
   
@@ -612,7 +896,8 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
   addr_max -= 0x10000;
 
   /* Usually, the compression ratio is about 50%.  */
-  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12);
+  addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+             + page_align (size);
   
   /* Find the highest address to put the initrd.  */
   mmap_size = find_mmap_size ();
@@ -625,8 +910,6 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
     {
       if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
-	  && desc->physical_start >= addr_min
-	  && desc->physical_start + size < addr_max
 	  && desc->num_pages >= initrd_pages)
 	{
 	  grub_efi_physical_address_t physical_end;
@@ -635,6 +918,9 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
 	  if (physical_end > addr_max)
 	    physical_end = addr_max;
 
+          if (physical_end < addr_min)
+            continue;
+
 	  if (physical_end > addr)
 	    addr = physical_end - page_align (size);
 	}
@@ -657,7 +943,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
     }
 
   grub_printf ("   [Initrd, addr=0x%x, size=0x%x]\n",
-	       addr, size);
+	       (unsigned) addr, (unsigned) size);
   
   lh->ramdisk_image = addr;
   lh->ramdisk_size = size;
diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c
index bc4567e..290d7b9 100644
--- a/loader/i386/ieee1275/linux.c
+++ b/loader/i386/ieee1275/linux.c
@@ -85,6 +85,49 @@ grub_set_bootpath (void)
 
 }
 
+static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
+  {
+    /* NULL.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Reserved.  */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    /* Code segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
+    /* Data segment.  */
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
+  };
+
+struct gdt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct gdt_descriptor gdt_desc =
+  {
+    sizeof (gdt),
+    gdt
+  };
+
+struct idt_descriptor
+{
+  grub_uint16_t limit;
+  void *base;
+} __attribute__ ((packed));
+
+static struct idt_descriptor idt_desc =
+  {
+    0,
+    0
+  };
+
+struct
+{
+  grub_uint32_t kernel_entry;
+  grub_uint32_t kernel_cs;
+} jumpvector;
+void *jump_start;
+
 static grub_err_t
 grub_linux_boot (void)
 {
@@ -137,11 +180,33 @@ grub_linux_boot (void)
   prot_code = (char *) GRUB_OFW_LINUX_KERNEL_ADDR;
   grub_memcpy (prot_code, kernel_addr, kernel_size);
 
+  jumpvector.kernel_entry = params->code32_start;
+  jumpvector.kernel_cs = 0x10;
+  jump_start = (void *) &jumpvector;
+
+  /* Load the IDT and the GDT for the bootstrap.  */
+  asm volatile ("lidt %0" : : "m" (idt_desc));
+  asm volatile ("lgdt %0" : : "m" (gdt_desc));
+
+  asm volatile ("movl %0, %%esi" : : "m" (params));
+  asm volatile ("movl %0, %%ecx" : : "m" (prot_code));
+  asm volatile ("xorl %%ebx, %%ebx" : : );
+
+  asm volatile ( "mov $24, %%ax" : : );
+  asm volatile ( "mov %%ax, %%ds" : : );
+  asm volatile ( "mov %%ax, %%ss" : : );
+  asm volatile ( "mov %%esi, %%esp" : : );
+
+  /* Enter Linux.  */
+  asm volatile ( "ljmp *(%%ecx)" : :);
+
+#if 0
   asm volatile ("movl %0, %%esi" : : "m" (params));
   asm volatile ("movl %%esi, %%esp" : : );
   asm volatile ("movl %0, %%ecx" : : "m" (prot_code));
   asm volatile ("xorl %%ebx, %%ebx" : : );
   asm volatile ("jmp *%%ecx" : : );
+#endif
 
   return GRUB_ERR_NONE;
 }
diff --git a/normal/x86_64/setjmp.S b/normal/x86_64/setjmp.S
new file mode 100644
index 0000000..4c8d4b3
--- /dev/null
+++ b/normal/x86_64/setjmp.S
@@ -0,0 +1,60 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+	.file	"setjmp.S"
+
+	.text
+
+/*
+ *  jmp_buf:
+ *   rbx rsp rbp r12 r13 r14 r15 rip
+ *   0   8   16  24  32  40  48  56
+ */
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+	pop	%rsi		/* Return address, and adjust the stack */
+	xorq	%rax, %rax
+	movq	%rbx, 0(%rdi)	/* RBX */
+	movq	%rsp, 8(%rdi)   /* RSP */
+	push	%rsi
+	movq	%rbp, 16(%rdi)	/* RBP */
+	movq	%r12, 24(%rdi)	/* R12 */
+	movq	%r13, 32(%rdi)	/* R13 */
+	movq	%r14, 40(%rdi)	/* R14 */
+	movq	%r15, 48(%rdi)	/* R15 */
+	movq	%rsi, 56(%rdi)	/* RSI */
+	ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+	movl	%esi, %eax
+	movq	(%rdi), %rbx
+	movq	8(%rdi), %rsp
+	movq	16(%rdi), %rbp
+	movq	24(%rdi), %r12
+	movq    32(%rdi), %r13
+	movq    40(%rdi), %r14
+	movq    48(%rdi), %r15
+	jmp	*56(%rdi)
diff --git a/term/efi/console.c b/term/efi/console.c
index af198e5..e5c02ad 100644
--- a/term/efi/console.c
+++ b/term/efi/console.c
@@ -36,6 +36,54 @@ grub_console_highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK,
 
 static int read_key = -1;
 
+static grub_uint32_t
+map_char (grub_uint32_t c)
+{
+  if (c > 0x7f)
+    {
+      /* Map some unicode characters to the EFI character.  */
+      switch (c)
+	{
+	case 0x2190:	/* left arrow */
+	  c = 0x25c4;
+	  break;
+	case 0x2191:	/* up arrow */
+	  c = 0x25b2;
+	  break;
+	case 0x2192:	/* right arrow */
+	  c = 0x25ba;
+	  break;
+	case 0x2193:	/* down arrow */
+	  c = 0x25bc;
+	  break;
+	case 0x2501:	/* horizontal line */
+	  c = 0x2500;
+	  break;
+	case 0x2503:	/* vertical line */
+	  c = 0x2502;
+	  break;
+	case 0x250F:	/* upper-left corner */
+	  c = 0x250c;
+	  break;
+	case 0x2513:	/* upper-right corner */
+	  c = 0x2510;
+	  break;
+	case 0x2517:	/* lower-left corner */
+	  c = 0x2514;
+	  break;
+	case 0x251B:	/* lower-right corner */
+	  c = 0x2518;
+	  break;
+
+	default:
+	  c = '?';
+	  break;
+	}
+    }
+
+  return c;
+}
+
 static void
 grub_console_putchar (grub_uint32_t c)
 {
@@ -48,14 +96,14 @@ grub_console_putchar (grub_uint32_t c)
   if (c > 0xffff)
     c = '?';
 
-  str[0] = (grub_efi_char16_t)  (c & 0xffff);
+  str[0] = (grub_efi_char16_t)  map_char (c & 0xffff);
   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,8 +124,8 @@ grub_console_checkkey (void)
     return 1;
 
   i = grub_efi_system_table->con_in;
-  status = i->read_key_stroke (i, &key);
-#if 1
+  status = efi_call_2 (i->read_key_stroke, i, &key);
+#if 0
   switch (status)
     {
     case GRUB_EFI_SUCCESS:
@@ -169,9 +217,9 @@ 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;
+	return -1;
       
       grub_console_checkkey ();
     }
@@ -189,7 +237,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 +262,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 +273,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 +287,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 +320,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..9bd4264 100644
--- a/util/i386/efi/grub-mkimage.c
+++ b/util/i386/efi/grub-mkimage.c
@@ -31,16 +31,56 @@
 #include <grub/efi/pe32.h>
 #include <grub/machine/kernel.h>
 
+#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 + sizeof (Elf_Ehdr) + 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.  */

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-21 17:04 ` Bean
@ 2008-06-23 11:58   ` Isaac Dupree
  2008-06-23 12:53     ` Bean
  2008-06-24 12:52   ` Isaac Dupree
  1 sibling, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-23 11:58 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> On Sat, Jun 21, 2008 at 1:04 AM, Bean <bean123ch@gmail.com> wrote:
>> Hi,
>>
>> This new patch add the following function to the original x86_64 EFI patch:
>>
>> 1, Fix menu drawing problem
>> It maps the unicode char to EFI char so that the rectangle box is
>> showed properly
>>
>> 2, Handle command line option for chainloader command
>>
>> 3, Add new command appleloader
>> The command is used to enable bios boot in apple's bootcamp, for example
>>
>> boot from legacy mbr:
>> appleloader HD
>> boot
>>
>> boot from legacy cd:
>> appleloader CD
>> boot
>>
>> boot from usb:
>> appleloader USB
>> boot
>>
>> The usb booting may not work in some machine.

I'm not so sure about that syntax.  Is there really only one way to boot 
from HD or USB? (for example I've been storing pc-GRUB2 in fat16 header 
on third partition, not mbr, and rEFIt finds it there).  How does 
Windows do it (can we boot Windows using this)? (even though Apple made 
BootCamp for windows, I don't want to find out personally.)  I guess 
you're stuck with some limitations of the apple bios software?  Also , 
"appleloader CD" makes me think it should be used even for Mac OS X 
boot-CD's, which I doubt it should?

> Hi,
> 
> I also fix a few problem in the linux loader, now it can load both 686
> and x86_64 kernel from 64-bit EFI firmware.

do you mean linux successfully booting, or hanging as before?

> Would someone test it in 32-bit EFI ?

I get an error during `make`, after (from a clean tree)
cvs up; patch -p1 -l < ~/../downloads/efi_5.diff;
./configure --with-platform=efi; make

cat kernel_syms.lst def-normal.lst def-_chain.lst def-chain.lst 
def-_linux.lst def-linux.lst def-cpuid.lst def-halt.lst def-reboot.lst 
def-fshelp.lst def-fat.lst def-ufs.lst def-ext2.lst def-ntfs.lst 
def-ntfscomp.lst def-minix.lst def-hfs.lst def-jfs.lst def-iso9660.lst 
def-xfs.lst def-affs.lst def-sfs.lst def-hfsplus.lst def-reiserfs.lst 
def-cpio.lst def-udf.lst def-afs.lst def-amiga.lst def-apple.lst 
def-pc.lst def-sun.lst def-acorn.lst def-gpt.lst def-raid.lst 
def-lvm.lst def-hello.lst def-boot.lst def-terminal.lst def-ls.lst 
def-cmp.lst def-cat.lst def-echo.lst def-help.lst def-font.lst 
def-search.lst def-test.lst def-loopback.lst def-configfile.lst 
def-terminfo.lst def-blocklist.lst def-hexdump.lst def-elf.lst 
def-gzio.lst def-read.lst def-sleep.lst /dev/null \
	  | mawk -f ./genmoddep.awk und-kernel.lst und-normal.lst 
und-_chain.lst und-chain.lst und-_linux.lst und-linux.lst und-cpuid.lst 
und-halt.lst und-reboot.lst und-fshelp.lst und-fat.lst und-ufs.lst 
und-ext2.lst und-ntfs.lst und-ntfscomp.lst und-minix.lst und-hfs.lst 
und-jfs.lst und-iso9660.lst und-xfs.lst und-affs.lst und-sfs.lst 
und-hfsplus.lst und-reiserfs.lst und-cpio.lst und-udf.lst und-afs.lst 
und-amiga.lst und-apple.lst und-pc.lst und-sun.lst und-acorn.lst 
und-gpt.lst und-raid.lst und-lvm.lst und-hello.lst und-boot.lst 
und-terminal.lst und-ls.lst und-cmp.lst und-cat.lst und-echo.lst 
und-help.lst und-font.lst und-search.lst und-test.lst und-loopback.lst 
und-configfile.lst und-terminfo.lst und-blocklist.lst und-hexdump.lst 
und-elf.lst und-gzio.lst und-read.lst und-sleep.lst > moddep.lst \
	  || (rm -f moddep.lst; exit 1)
grub_pci_make_address in _linux is not defined
make: *** [moddep.lst] Error 1



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-23 11:58   ` Isaac Dupree
@ 2008-06-23 12:53     ` Bean
  0 siblings, 0 replies; 45+ messages in thread
From: Bean @ 2008-06-23 12:53 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Jun 23, 2008 at 7:58 PM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> On Sat, Jun 21, 2008 at 1:04 AM, Bean <bean123ch@gmail.com> wrote:
>>>
>>> Hi,
>>>
>>> This new patch add the following function to the original x86_64 EFI
>>> patch:
>>>
>>> 1, Fix menu drawing problem
>>> It maps the unicode char to EFI char so that the rectangle box is
>>> showed properly
>>>
>>> 2, Handle command line option for chainloader command
>>>
>>> 3, Add new command appleloader
>>> The command is used to enable bios boot in apple's bootcamp, for example
>>>
>>> boot from legacy mbr:
>>> appleloader HD
>>> boot
>>>
>>> boot from legacy cd:
>>> appleloader CD
>>> boot
>>>
>>> boot from usb:
>>> appleloader USB
>>> boot
>>>
>>> The usb booting may not work in some machine.
>
> I'm not so sure about that syntax.  Is there really only one way to boot
> from HD or USB? (for example I've been storing pc-GRUB2 in fat16 header on
> third partition, not mbr, and rEFIt finds it there).  How does Windows do it
> (can we boot Windows using this)? (even though Apple made BootCamp for
> windows, I don't want to find out personally.)  I guess you're stuck with
> some limitations of the apple bios software?  Also , "appleloader CD" makes
> me think it should be used even for Mac OS X boot-CD's, which I doubt it
> should?

Yes, this is the only way to boot from legacy HD/CD. Refit is using
the same method, but it also writes an embedded syslinux mbr to the
disk, and mark the partition as active, this is how it boots from
different partition.

>> Hi,
>>
>> I also fix a few problem in the linux loader, now it can load both 686
>> and x86_64 kernel from 64-bit EFI firmware.
>
> do you mean linux successfully booting, or hanging as before?

It can boot both x86_64 and 686 kernel from 64-bit EFI firmware, while
previously it can only boot x86_64.

>
>> Would someone test it in 32-bit EFI ?
>
> I get an error during `make`, after (from a clean tree)
> cvs up; patch -p1 -l < ~/../downloads/efi_5.diff;
> ./configure --with-platform=efi; make
>
> cat kernel_syms.lst def-normal.lst def-_chain.lst def-chain.lst
> def-_linux.lst def-linux.lst def-cpuid.lst def-halt.lst def-reboot.lst
> def-fshelp.lst def-fat.lst def-ufs.lst def-ext2.lst def-ntfs.lst
> def-ntfscomp.lst def-minix.lst def-hfs.lst def-jfs.lst def-iso9660.lst
> def-xfs.lst def-affs.lst def-sfs.lst def-hfsplus.lst def-reiserfs.lst
> def-cpio.lst def-udf.lst def-afs.lst def-amiga.lst def-apple.lst def-pc.lst
> def-sun.lst def-acorn.lst def-gpt.lst def-raid.lst def-lvm.lst def-hello.lst
> def-boot.lst def-terminal.lst def-ls.lst def-cmp.lst def-cat.lst
> def-echo.lst def-help.lst def-font.lst def-search.lst def-test.lst
> def-loopback.lst def-configfile.lst def-terminfo.lst def-blocklist.lst
> def-hexdump.lst def-elf.lst def-gzio.lst def-read.lst def-sleep.lst
> /dev/null \
>          | mawk -f ./genmoddep.awk und-kernel.lst und-normal.lst
> und-_chain.lst und-chain.lst und-_linux.lst und-linux.lst und-cpuid.lst
> und-halt.lst und-reboot.lst und-fshelp.lst und-fat.lst und-ufs.lst
> und-ext2.lst und-ntfs.lst und-ntfscomp.lst und-minix.lst und-hfs.lst
> und-jfs.lst und-iso9660.lst und-xfs.lst und-affs.lst und-sfs.lst
> und-hfsplus.lst und-reiserfs.lst und-cpio.lst und-udf.lst und-afs.lst
> und-amiga.lst und-apple.lst und-pc.lst und-sun.lst und-acorn.lst und-gpt.lst
> und-raid.lst und-lvm.lst und-hello.lst und-boot.lst und-terminal.lst
> und-ls.lst und-cmp.lst und-cat.lst und-echo.lst und-help.lst und-font.lst
> und-search.lst und-test.lst und-loopback.lst und-configfile.lst
> und-terminfo.lst und-blocklist.lst und-hexdump.lst und-elf.lst und-gzio.lst
> und-read.lst und-sleep.lst > moddep.lst \
>          || (rm -f moddep.lst; exit 1)
> grub_pci_make_address in _linux is not defined
> make: *** [moddep.lst] Error 1

You should also run ./autogen.sh to update the mk files. Also, I have
uploaded an binary version at:

http://grub4dos.sourceforge.net/grub2/grub.efi.1

You can use it if you still can't compile it successfully.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-21 17:04 ` Bean
  2008-06-23 11:58   ` Isaac Dupree
@ 2008-06-24 12:52   ` Isaac Dupree
  2008-06-24 13:12     ` Bean
  1 sibling, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-24 12:52 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> On Sat, Jun 21, 2008 at 1:04 AM, Bean <bean123ch@gmail.com> wrote:
>> Hi,
>>
>> This new patch add the following function to the original x86_64 EFI patch:
>>
>> 1, Fix menu drawing problem
>> It maps the unicode char to EFI char so that the rectangle box is
>> showed properly
>>
>> 2, Handle command line option for chainloader command
>>
>> 3, Add new command appleloader
>> The command is used to enable bios boot in apple's bootcamp, for example
>>
>> boot from legacy mbr:
>> appleloader HD
>> boot
>>
>> boot from legacy cd:
>> appleloader CD
>> boot
>>
>> boot from usb:
>> appleloader USB
>> boot
>>
>> The usb booting may not work in some machine.
> 
> Hi,
> 
> I also fix a few problem in the linux loader, now it can load both 686
> and x86_64 kernel from 64-bit EFI firmware.
> 
> Would someone test it in 32-bit EFI ?

with just that patch against CVS, for me

- linux then initrd doesn't run out of memory (that fix is still there). 
  On the other hand, 'linux' with wrong parameters so I repeated the 
command, did give me such an error.  In any case, trying again perfectly 
and booting, gave me the same (as my last test with your EFI patches) 
hanging on the GRUB terminal, not booting successfully.

- appleloader always tells me "Model : Core Duo/Solo" and nothing else 
(no matter whether I give it a parameter or not).  If I say "boot" 
nothing happens, it just stays in GRUB prompt and I can enter more 
commands.  (admittedly, I think I didn't *have* anything to boot in my 
CD drive, USB or MBR)

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-24 12:52   ` Isaac Dupree
@ 2008-06-24 13:12     ` Bean
  2008-06-24 16:57       ` Isaac Dupree
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-06-24 13:12 UTC (permalink / raw)
  To: The development of GRUB 2

On Tue, Jun 24, 2008 at 8:52 PM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> On Sat, Jun 21, 2008 at 1:04 AM, Bean <bean123ch@gmail.com> wrote:
>>>
>>> Hi,
>>>
>>> This new patch add the following function to the original x86_64 EFI
>>> patch:
>>>
>>> 1, Fix menu drawing problem
>>> It maps the unicode char to EFI char so that the rectangle box is
>>> showed properly
>>>
>>> 2, Handle command line option for chainloader command
>>>
>>> 3, Add new command appleloader
>>> The command is used to enable bios boot in apple's bootcamp, for example
>>>
>>> boot from legacy mbr:
>>> appleloader HD
>>> boot
>>>
>>> boot from legacy cd:
>>> appleloader CD
>>> boot
>>>
>>> boot from usb:
>>> appleloader USB
>>> boot
>>>
>>> The usb booting may not work in some machine.
>>
>> Hi,
>>
>> I also fix a few problem in the linux loader, now it can load both 686
>> and x86_64 kernel from 64-bit EFI firmware.
>>
>> Would someone test it in 32-bit EFI ?
>
> with just that patch against CVS, for me
>
> - linux then initrd doesn't run out of memory (that fix is still there).  On
> the other hand, 'linux' with wrong parameters so I repeated the command, did
> give me such an error.  In any case, trying again perfectly and booting,
> gave me the same (as my last test with your EFI patches) hanging on the GRUB
> terminal, not booting successfully.
>

What's the kernel version ? Perhaps you need the latest 2.6.25 series.

Also, you can try adding video=efifb to the command line, does it show
kernel message ?

> - appleloader always tells me "Model : Core Duo/Solo" and nothing else (no
> matter whether I give it a parameter or not).  If I say "boot" nothing
> happens, it just stays in GRUB prompt and I can enter more commands.
>  (admittedly, I think I didn't *have* anything to boot in my CD drive, USB
> or MBR)

The model is quite old, it's possible that it uses xom. Is there a
/System/Library/CoreServices/xom.efi in the OSX partition ?

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-24 13:12     ` Bean
@ 2008-06-24 16:57       ` Isaac Dupree
  2008-06-24 17:11         ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-24 16:57 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
>> - linux then initrd doesn't run out of memory (that fix is still there).  On
>> the other hand, 'linux' with wrong parameters so I repeated the command, did
>> give me such an error.  In any case, trying again perfectly and booting,
>> gave me the same (as my last test with your EFI patches) hanging on the GRUB
>> terminal, not booting successfully.
>>
> 
> What's the kernel version ? Perhaps you need the latest 2.6.25 series.

oh, maybe. It's an Ubuntu kernel.
 > uname -a
Linux east 2.6.24-19-generic #1 SMP Wed Jun 18 14:43:41 UTC 2008 i686 
GNU/Linux

> Also, you can try adding video=efifb to the command line, does it show
> kernel message ?

I'll try that soon, does it need any special customization of the kernel?

>> - appleloader always tells me "Model : Core Duo/Solo" and nothing else (no
>> matter whether I give it a parameter or not).  If I say "boot" nothing
>> happens, it just stays in GRUB prompt and I can enter more commands.
>>  (admittedly, I think I didn't *have* anything to boot in my CD drive, USB
>> or MBR)
> 
> The model is quite old, it's possible that it uses xom. Is there a
> /System/Library/CoreServices/xom.efi in the OSX partition ?

only one year old :)))

No, there isn't.. the only .efi file in that directory is 
/System/Library/CoreServices/boot.efi

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-24 16:57       ` Isaac Dupree
@ 2008-06-24 17:11         ` Bean
  2008-06-24 21:59           ` Isaac Dupree
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-06-24 17:11 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Jun 25, 2008 at 12:57 AM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>>
>>> - linux then initrd doesn't run out of memory (that fix is still there).
>>>  On
>>> the other hand, 'linux' with wrong parameters so I repeated the command,
>>> did
>>> give me such an error.  In any case, trying again perfectly and booting,
>>> gave me the same (as my last test with your EFI patches) hanging on the
>>> GRUB
>>> terminal, not booting successfully.
>>>
>>
>> What's the kernel version ? Perhaps you need the latest 2.6.25 series.
>
> oh, maybe. It's an Ubuntu kernel.
>> uname -a
> Linux east 2.6.24-19-generic #1 SMP Wed Jun 18 14:43:41 UTC 2008 i686
> GNU/Linux
>
>> Also, you can try adding video=efifb to the command line, does it show
>> kernel message ?
>
> I'll try that soon, does it need any special customization of the kernel?

You can try the kernel I extract from Fedora's efidisk:

http://grub4dos.sourceforge.net/grub2/efi.rar

It's 2.6.25. But there is a small problem with this kernel, the screen
would scramble after some kernel output. This is caused by the agp
driver, not grub's fault.

>
>>> - appleloader always tells me "Model : Core Duo/Solo" and nothing else
>>> (no
>>> matter whether I give it a parameter or not).  If I say "boot" nothing
>>> happens, it just stays in GRUB prompt and I can enter more commands.
>>>  (admittedly, I think I didn't *have* anything to boot in my CD drive,
>>> USB
>>> or MBR)
>>
>> The model is quite old, it's possible that it uses xom. Is there a
>> /System/Library/CoreServices/xom.efi in the OSX partition ?
>
> only one year old :)))

Interesting, according to refit, this should be an early 2006 model.
Refit does work, doesn't it ?

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-24 17:11         ` Bean
@ 2008-06-24 21:59           ` Isaac Dupree
  2008-06-25  6:49             ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-24 21:59 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
>>> Also, you can try adding video=efifb to the command line, does it show
>>> kernel message ?
>> I'll try that soon, does it need any special customization of the kernel?
> 
> You can try the kernel I extract from Fedora's efidisk:
> 
> http://grub4dos.sourceforge.net/grub2/efi.rar
> 
> It's 2.6.25. But there is a small problem with this kernel, the screen
> would scramble after some kernel output. This is caused by the agp
> driver, not grub's fault.

Results:
Whatever linux kernel I pick, adding video=efifb to its commandline 
causes grub to output a couple extra lines in response to `linux`:
Video mode: 1280x800-32@59
Video framebuffer: 80000000

Even with video=efifb, the Ubuntu kernel works no better.  But that 
Fedora kernel you mentioned, does work:
- with video=efifb, the penguin and kernel messages flash onto the 
screen for a moment before the screen turns into gibberish.
- without, the screen just turns into different gibberish, which is 
still an improvement over the GRUB screen remaining there :-)

Of course, that Linux kernel doesn't bring me to anything *usable*... 
but it shows that we're loading Linux and it's probably possible to work 
in practice by compiling a new enough Linux with the right configs (and 
maybe patches)


>>>> - appleloader always tells me "Model : Core Duo/Solo" and nothing else
>>>> (no
>>>> matter whether I give it a parameter or not).  If I say "boot" nothing
>>>> happens, it just stays in GRUB prompt and I can enter more commands.
>>>>  (admittedly, I think I didn't *have* anything to boot in my CD drive,
>>>> USB
>>>> or MBR)
>>> The model is quite old, it's possible that it uses xom. Is there a
>>> /System/Library/CoreServices/xom.efi in the OSX partition ?
>> only one year old :)))
> 
> Interesting, according to refit, this should be an early 2006 model.
> Refit does work, doesn't it ?

refit doesn't tell *me* anything about the model when I'm in refit.  In 
case what your appleloader says was confusing you, I actually have a 
2.16 GHz Intel Core 2 Duo CPU (yes, 64-bit capable, I've just never used 
it in that way).  I'm still running refit 0.9 though since I never yet 
bothered to upgrade to 0.10 or 0.11, and since it works fine for me.

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-24 21:59           ` Isaac Dupree
@ 2008-06-25  6:49             ` Bean
  2008-06-25 12:50               ` Isaac Dupree
  2008-06-25 12:59               ` Isaac Dupree
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-06-25  6:49 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Jun 25, 2008 at 5:59 AM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>>>
>>>> Also, you can try adding video=efifb to the command line, does it show
>>>> kernel message ?
>>>
>>> I'll try that soon, does it need any special customization of the kernel?
>>
>> You can try the kernel I extract from Fedora's efidisk:
>>
>> http://grub4dos.sourceforge.net/grub2/efi.rar
>>
>> It's 2.6.25. But there is a small problem with this kernel, the screen
>> would scramble after some kernel output. This is caused by the agp
>> driver, not grub's fault.
>
> Results:
> Whatever linux kernel I pick, adding video=efifb to its commandline causes
> grub to output a couple extra lines in response to `linux`:
> Video mode: 1280x800-32@59
> Video framebuffer: 80000000
>
> Even with video=efifb, the Ubuntu kernel works no better.  But that Fedora
> kernel you mentioned, does work:
> - with video=efifb, the penguin and kernel messages flash onto the screen
> for a moment before the screen turns into gibberish.
> - without, the screen just turns into different gibberish, which is still an
> improvement over the GRUB screen remaining there :-)
>
> Of course, that Linux kernel doesn't bring me to anything *usable*... but it
> shows that we're loading Linux and it's probably possible to work in
> practice by compiling a new enough Linux with the right configs (and maybe
> patches)
>
>

I'm using the 2.6.25 kernel from debian sid, it works fine. I think
ubuntu can use debian packages as well. To solve the screen problem,
you need the following command line:

video=efifb agp=off

If you're interested, you can also try amd64 kernel. You can use it on
686 linux directly, no need to install a full amd64 system.

>>>>> - appleloader always tells me "Model : Core Duo/Solo" and nothing else
>>>>> (no
>>>>> matter whether I give it a parameter or not).  If I say "boot" nothing
>>>>> happens, it just stays in GRUB prompt and I can enter more commands.
>>>>>  (admittedly, I think I didn't *have* anything to boot in my CD drive,
>>>>> USB
>>>>> or MBR)
>>>>
>>>> The model is quite old, it's possible that it uses xom. Is there a
>>>> /System/Library/CoreServices/xom.efi in the OSX partition ?
>>>
>>> only one year old :)))
>>
>> Interesting, according to refit, this should be an early 2006 model.
>> Refit does work, doesn't it ?
>
> refit doesn't tell *me* anything about the model when I'm in refit.  In case
> what your appleloader says was confusing you, I actually have a 2.16 GHz
> Intel Core 2 Duo CPU (yes, 64-bit capable, I've just never used it in that
> way).  I'm still running refit 0.9 though since I never yet bothered to
> upgrade to 0.10 or 0.11, and since it works fine for me.

I take a look at 0.9 source, the handling is the same. Are you sure
you type the command exactly as it is ?

appleloader HD
boot

You can also try my compiled version, see if it works.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-25  6:49             ` Bean
@ 2008-06-25 12:50               ` Isaac Dupree
  2008-06-25 13:54                 ` Bean
  2008-06-25 12:59               ` Isaac Dupree
  1 sibling, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-25 12:50 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> I take a look at 0.9 source, the handling is the same. Are you sure
> you type the command exactly as it is ?
> 
> appleloader HD
> boot

what should I expect the result to be, given that refit is the only 
thing that's ever touched my MBR since Apple's manufacturing? (so 
there's a fake partition table created by refit's gptsync, and maybe 
there's whatever you were saying about refit using hacks with the mbr to 
boot grub-pc from my third partition, but I've never specifically 
installed any bootloaders to this mbr)

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-25  6:49             ` Bean
  2008-06-25 12:50               ` Isaac Dupree
@ 2008-06-25 12:59               ` Isaac Dupree
  1 sibling, 0 replies; 45+ messages in thread
From: Isaac Dupree @ 2008-06-25 12:59 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> I'm using the 2.6.25 kernel from debian sid, it works fine. I think
> ubuntu can use debian packages as well. To solve the screen problem,
> you need the following command line:
> 
> video=efifb agp=off
> 
> If you're interested, you can also try amd64 kernel. You can use it on
> 686 linux directly, no need to install a full amd64 system.

every time I've tried Ubuntu with a different kernel... it has problems. 
  Ubuntu has a fancy initrd, modules, lots of patches, Upstart as init, 
and who knows what assumptions about the boot process... but maybe.  I 
could use the kernel from the Ubuntu development branch, if I had any 
idea how to use APT to upgrade just a few specific things from an 
unstable package-source and not my whole system (the kernel binary 
obviously doesn't depend on system libraries, so it should be uniquely 
easy to do this...).  Do you know about debians -- if that's possible?

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-25 12:50               ` Isaac Dupree
@ 2008-06-25 13:54                 ` Bean
  2008-06-28 10:51                   ` Isaac Dupree
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-06-25 13:54 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Jun 25, 2008 at 8:50 PM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> I take a look at 0.9 source, the handling is the same. Are you sure
>> you type the command exactly as it is ?
>>
>> appleloader HD
>> boot
>
> what should I expect the result to be, given that refit is the only thing
> that's ever touched my MBR since Apple's manufacturing? (so there's a fake
> partition table created by refit's gptsync, and maybe there's whatever you
> were saying about refit using hacks with the mbr to boot grub-pc from my
> third partition, but I've never specifically installed any bootloaders to
> this mbr)

Perhaps command line is not passed to loader correctly, you can verify
it with the OSX loader:

set root=(hd0,2)
chainloader /System/Library/CoreServices/boot.efi -- -v
boot

Please try this out, if parameter -v is passed to the loader, you will
see console screen before switching to GUI.

>every time I've tried Ubuntu with a different kernel... it has problems.  Ubuntu has a fancy initrd, modules, lots of patches, Upstart as init, >and who knows what assumptions about the boot process... but maybe.  I could use the kernel from the Ubuntu development branch, if I >had any idea how to use APT to upgrade just a few specific things from an unstable package-source and not my whole system (the kernel >binary obviously doesn't depend on system libraries, so it should be uniquely easy to do this...).  Do you know about debians -- if that's >possible?

In debian, all I have to do is to add the sid line to
/etc/apt/source.list, apt-get update, then apt-get install
linux-image-xxx. Ubuntu is based on debian, the process should be
similar.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-25 13:54                 ` Bean
@ 2008-06-28 10:51                   ` Isaac Dupree
  2008-06-28 11:55                     ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-28 10:51 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> Perhaps command line is not passed to loader correctly, you can verify
> it with the OSX loader:
> 
> set root=(hd0,2)
> chainloader /System/Library/CoreServices/boot.efi -- -v
> boot
> 
> Please try this out, if parameter -v is passed to the loader, you will
> see console screen before switching to GUI.

That 'chainloader' didn't work at all: It seems GRUB2 here isn't 
understanding the HFS+(journaled) filesystem at all.  Neither in EFI nor 
BIOS grub2 can I see anything on that partition, even though I have 
module hfsplus loaded (I think - but lsmod in grub takes up more than 
the whole screen, so I can't see them all - is there any way to get 
around that?).

Also I decided to play around and try a few other commands in grub2.
cpuid (efi or pc) -- finishes instantly without outputting anything
lspci (efi) -- hangs (but it works properly in pc)
reboot (efi) -- hangs (but it works properly in pc)

> 
>> every time I've tried Ubuntu with a different kernel... it has problems.  Ubuntu has a fancy initrd, modules, lots of patches, Upstart as init, >and who knows what assumptions about the boot process... but maybe.  I could use the kernel from the Ubuntu development branch, if I >had any idea how to use APT to upgrade just a few specific things from an unstable package-source and not my whole system (the kernel >binary obviously doesn't depend on system libraries, so it should be uniquely easy to do this...).  Do you know about debians -- if that's >possible?
> 
> In debian, all I have to do is to add the sid line to
> /etc/apt/source.list, apt-get update, then apt-get install
> linux-image-xxx. Ubuntu is based on debian, the process should be
> similar.

yes it is similar (and I'd probably try and use the Ubuntu development 
branch for the next release, "intrepid") : however, what bothers me is 
that this seems to make the whole apt repo, not just the part I want, be 
a first-class citizen; so that if it contains a newer version number of 
any package on my system, it will install that if I ask to install the 
package, or it will offer to upgrade to that version if it's already 
installed (so I can't even begin to pick out which are the Ubuntu-stable 
updates).  I hope I'm missing some option that lets me avoid this risky 
nuisance, while still keeping tabs on the unstable linux-image packages?

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-28 10:51                   ` Isaac Dupree
@ 2008-06-28 11:55                     ` Bean
  2008-06-29 23:55                       ` Isaac Dupree
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-06-28 11:55 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jun 28, 2008 at 6:51 PM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> Perhaps command line is not passed to loader correctly, you can verify
>> it with the OSX loader:
>>
>> set root=(hd0,2)
>> chainloader /System/Library/CoreServices/boot.efi -- -v
>> boot
>>
>> Please try this out, if parameter -v is passed to the loader, you will
>> see console screen before switching to GUI.
>
> That 'chainloader' didn't work at all: It seems GRUB2 here isn't
> understanding the HFS+(journaled) filesystem at all.  Neither in EFI nor
> BIOS grub2 can I see anything on that partition, even though I have module
> hfsplus loaded (I think - but lsmod in grub takes up more than the whole
> screen, so I can't see them all - is there any way to get around that?).
>
> Also I decided to play around and try a few other commands in grub2.
> cpuid (efi or pc) -- finishes instantly without outputting anything
> lspci (efi) -- hangs (but it works properly in pc)
> reboot (efi) -- hangs (but it works properly in pc)
>

I wonder if there is bug in the hfsplus module. You can check it out
with grub-fstest command:

sudo ./grub-fstest /dev/sda3 ls /

This would list the content of root directory.

You can also create a small hfs+ image and test it with grub-fstest,
if it does have problem, you can upload the image for me to test.

cpuid would check if cpuid exists and set return code, there is no output.

The result is lspci is a little strange. Is there any output before
hanging ? When you use video=efifb or video=vesafb. It enum pci to get
the frame buffer address, if it doesn't hang there, it shouldn't hang
here as well.

reboot could be a firmware related issue, I can check it out.

Oh btw, do you compile from source or use the binary version ?

>>
>>> every time I've tried Ubuntu with a different kernel... it has problems.
>>>  Ubuntu has a fancy initrd, modules, lots of patches, Upstart as init, >and
>>> who knows what assumptions about the boot process... but maybe.  I could use
>>> the kernel from the Ubuntu development branch, if I >had any idea how to use
>>> APT to upgrade just a few specific things from an unstable package-source
>>> and not my whole system (the kernel >binary obviously doesn't depend on
>>> system libraries, so it should be uniquely easy to do this...).  Do you know
>>> about debians -- if that's >possible?
>>
>> In debian, all I have to do is to add the sid line to
>> /etc/apt/source.list, apt-get update, then apt-get install
>> linux-image-xxx. Ubuntu is based on debian, the process should be
>> similar.
>
> yes it is similar (and I'd probably try and use the Ubuntu development
> branch for the next release, "intrepid") : however, what bothers me is that
> this seems to make the whole apt repo, not just the part I want, be a
> first-class citizen; so that if it contains a newer version number of any
> package on my system, it will install that if I ask to install the package,
> or it will offer to upgrade to that version if it's already installed (so I
> can't even begin to pick out which are the Ubuntu-stable updates).  I hope
> I'm missing some option that lets me avoid this risky nuisance, while still
> keeping tabs on the unstable linux-image packages?

Perhaps the most simple way is to download the deb package from
intrpid, then install it with dpkg.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-28 11:55                     ` Bean
@ 2008-06-29 23:55                       ` Isaac Dupree
  2008-06-30  5:05                         ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-06-29 23:55 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> I wonder if there is bug in the hfsplus module. You can check it out
> with grub-fstest command:
> 
> sudo ./grub-fstest /dev/sda3 ls /
> 
> This would list the content of root directory.

outputs nothing, just a blank line, for /dev/sda2 which is my hfsplus 
(it works fine for fat16, ext3 partitions).

> You can also create a small hfs+ image and test it with grub-fstest,
> if it does have problem, you can upload the image for me to test.

not sure how to create a hfs+ image... the one I have is many gigabytes 
and came with the laptop (I just shrunk it to 30GB to fit my linuxes, is 
all).  Does Linux or MacOSX provide a way to create a small HFSJ image? 
  (also I could try going to MacOSX and turning off journalling and see 
if it affects grub2's ability to read it at all, perhaps - although for 
just reading, not writing, I doubt it makes a significant difference)

> cpuid would check if cpuid exists and set return code, there is no output.

oh, okay, then it's just the command's help description that was 
confusing me

> The result is lspci is a little strange. Is there any output before
> hanging ?

no, I hit enter and never get back a prompt or any output

> When you use video=efifb or video=vesafb. It enum pci to get
> the frame buffer address, if it doesn't hang there, it shouldn't hang
> here as well.

odd, because that definitely didn't hang (when loading linux-2.6.25 that 
is).

> 
> reboot could be a firmware related issue, I can check it out.

okay, maybe it is

> Oh btw, do you compile from source or use the binary version ?

I compile grub2 from source

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-29 23:55                       ` Isaac Dupree
@ 2008-06-30  5:05                         ` Bean
  2008-07-02 13:43                           ` Bean
  2008-07-05 23:02                           ` Isaac Dupree
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-06-30  5:05 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Jun 30, 2008 at 7:55 AM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> I wonder if there is bug in the hfsplus module. You can check it out
>> with grub-fstest command:
>>
>> sudo ./grub-fstest /dev/sda3 ls /
>>
>> This would list the content of root directory.
>
> outputs nothing, just a blank line, for /dev/sda2 which is my hfsplus (it
> works fine for fat16, ext3 partitions).
>
>> You can also create a small hfs+ image and test it with grub-fstest,
>> if it does have problem, you can upload the image for me to test.
>
> not sure how to create a hfs+ image... the one I have is many gigabytes and
> came with the laptop (I just shrunk it to 30GB to fit my linuxes, is all).
>  Does Linux or MacOSX provide a way to create a small HFSJ image?  (also I
> could try going to MacOSX and turning off journalling and see if it affects
> grub2's ability to read it at all, perhaps - although for just reading, not
> writing, I doubt it makes a significant difference)
>
>> cpuid would check if cpuid exists and set return code, there is no output.
>
> oh, okay, then it's just the command's help description that was confusing
> me
>
>> The result is lspci is a little strange. Is there any output before
>> hanging ?
>
> no, I hit enter and never get back a prompt or any output
>
>> When you use video=efifb or video=vesafb. It enum pci to get
>> the frame buffer address, if it doesn't hang there, it shouldn't hang
>> here as well.
>
> odd, because that definitely didn't hang (when loading linux-2.6.25 that
> is).
>
>>
>> reboot could be a firmware related issue, I can check it out.
>
> okay, maybe it is
>
>> Oh btw, do you compile from source or use the binary version ?
>
> I compile grub2 from source

Hi,

Perhaps you can also try the binary version at:

http://grub4dos.sourceforge.net/grub2/grub.efi.1

A friend of mine have tested in in 32-bit EFI firmware, there is no
problem for him.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-30  5:05                         ` Bean
@ 2008-07-02 13:43                           ` Bean
  2008-07-05 23:02                           ` Isaac Dupree
  1 sibling, 0 replies; 45+ messages in thread
From: Bean @ 2008-07-02 13:43 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Any comment ?

As this patch is quite large, it's getting more difficult to sync with
HEAD. If there is no objection, I'd like to commit it soon.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-20 17:04 [PATCH] New x86_64 EFI patch Bean
  2008-06-21 17:04 ` Bean
@ 2008-07-03 18:11 ` Marco Gerards
  2008-07-03 19:51   ` Bean
  1 sibling, 1 reply; 45+ messages in thread
From: Marco Gerards @ 2008-07-03 18:11 UTC (permalink / raw)
  To: The development of GRUB 2

Hi,

Bean <bean123ch@gmail.com> writes:

> This new patch add the following function to the original x86_64 EFI patch:
>
> 1, Fix menu drawing problem
> It maps the unicode char to EFI char so that the rectangle box is
> showed properly

Doesn't it break other systems?

> 2, Handle command line option for chainloader command
>
> 3, Add new command appleloader
> The command is used to enable bios boot in apple's bootcamp, for example

I am not sure if appleloader is a good word.  Can you explain how it
works and what it actually does?  Perhaps something like "legacy"
would be a better word, especially since it is not apple specific.

btw, you forgot the changelog entry.

--
Marco




^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-03 18:11 ` Marco Gerards
@ 2008-07-03 19:51   ` Bean
  0 siblings, 0 replies; 45+ messages in thread
From: Bean @ 2008-07-03 19:51 UTC (permalink / raw)
  To: The development of GRUB 2

On Fri, Jul 4, 2008 at 2:11 AM, Marco Gerards <mgerards@xs4all.nl> wrote:
> Hi,
>
> Bean <bean123ch@gmail.com> writes:
>
>> This new patch add the following function to the original x86_64 EFI patch:
>>
>> 1, Fix menu drawing problem
>> It maps the unicode char to EFI char so that the rectangle box is
>> showed properly
>
> Doesn't it break other systems?

It only changes term/efi/console.c, which is efi specific.

>
>> 2, Handle command line option for chainloader command
>>
>> 3, Add new command appleloader
>> The command is used to enable bios boot in apple's bootcamp, for example
>
> I am not sure if appleloader is a good word.  Can you explain how it
> works and what it actually does?  Perhaps something like "legacy"
> would be a better word, especially since it is not apple specific.

The code is apple specific. They use special pathname for the bios
switcher, we just chainloading it. The pathname is not even the same
among different models, we need to go through an array to find a
possible match.

>
> btw, you forgot the changelog entry.
>

Here it is:

2008-07-04  Bean  <bean123ch@gmail.com>

	* conf/i386/efi.rmk (pkglib_MODULES): add pci.mod and lspci.mod.
	(appleldr_mod_SOURCE): New variavle.
	(appleldr_mod_CFLAGS): Likewise.
	(appleldr_mod_LDFLAGS): Likewise.
	(pci_mod_SOURCES): Likewise.
	(pci_mod_CFLAGS): Likewise.
	(pci_mod_LDFLAGS): Likewise.
	(lspci_mod_SOURCES): Likewise.
	(lspci_mod_CFLAGS): Likewise.
	(lspci_mod_LDFLAGS): Likewise.

	* conf/x86_64-efi.rmk: New file.

	* disk/efi/efidisk.c (grub_efidisk_read): Wrap efi calls with efi_call_N
	macro.
	(grub_efidisk_write): Likewise.

	* include/efi/api.h (efi_call_0): New macro.
	(efi_call_1): Likewise.
	(efi_call_2): Likewise.
	(efi_call_3): Likewise.
	(efi_call_4): Likewise.
	(efi_call_5): Likewise.
	(efi_call_6): Likewise.

	* include/grub/efi/chainloader.h (grub_chainloader_cmd): Rename to
	grub_rescue_cmd_chainloader.

	* include/grub/efi/pe32.h (GRUB_PE32_MACHINE_X86_64): New macro.
	(grub_pe32_optional_header): Change some fields based on i386 or
	x86_64 platform.
	(GRUB_PE32_PE32_MAGIC): Likewise.

	* include/grub/efi/uga_draw.h: New file.

	* include/grub/elf.h (STN_ABS): New constant.
	(R_X86_64_NONE): Relocation constant for x86_64.
	(R_X86_64_64): Likewise.
	(R_X86_64_PC32): Likewise.
	(R_X86_64_GOT32): Likewise.
	(R_X86_64_PLT32): Likewise.
	(R_X86_64_COPY): Likewise.
	(R_X86_64_GLOB_DAT): Likewise.
	(R_X86_64_JUMP_SLOT): Likewise.
	(R_X86_64_RELATIVE): Likewise.
	(R_X86_64_GOTPCREL): Likewise.
	(R_X86_64_32): Likewise.
	(R_X86_64_32S): Likewise.
	(R_X86_64_16): Likewise.
	(R_X86_64_PC16): Likewise.
	(R_X86_64_8): Likewise.
	(R_X86_64_PC8): Likewise.

	* include/grub/i386/efi/pci.h: New file.

	* include/grub/i386/linux.h (GRUB_LINUX_EFI_SIGNATURE):
	Change it value based on platform.
	(GRUB_LINUX_EFI_SIGNATURE_0204): New constant.
	(GRUB_E820_RAM): Likewise.
	(GRUB_E820_RESERVED): Likewise.
	(GRUB_E820_ACPI): Likewise.
	(GRUB_E820_NVS): Likewise.
	(GRUB_E820_EXEC_CODE): Likewise.
	(GRUB_E820_MAX_ENTRY): Likewise.
	(grub_e820_mmap): New structure.
	(linux_kernel_header): Change the efi field according to different
	kernel version, also field from linux_kernel_header.

	* include/grub/kernel.h (grub_module_info): Add padding for x86_64.

	* include/grub/pci.h (GRUB_PCI_ADDR_SPACE_MASK): New constant.
	(GRUB_PCI_ADDR_SPACE_MEMORY): Likewise.
	(GRUB_PCI_ADDR_SPACE_IO): Likewise.
	(GRUB_PCI_ADDR_MEM_TYPE_MASK): Likewise.
	(GRUB_PCI_ADDR_MEM_TYPE_32): Likewise.
	(GRUB_PCI_ADDR_MEM_TYPE_1M): Likewise.
	(GRUB_PCI_ADDR_MEM_TYPE_64): Likewise.
	(GRUB_PCI_ADDR_MEM_PREFETCH): Likewise.
	(GRUB_PCI_ADDR_MEM_MASK): Likewise.
	(GRUB_PCI_ADDR_IO_MASK): Likewise.

	* include/grub/x86_64/efi/kernel.h: New file.

	* include/grub/x86_64/efi/loader.h: Likewise.

	* include/grub/x86_64/efi/machine.h: Likewise.

	* include/grub/x86_64/efi/pci.h: Likewise.

	* include/grub/x86_64/efi/time.h: Likewise.

	* include/grub/x86_64/linux.h: Likewise.

	* include/grub/x86_64/setjmp.h: Likewise.

	* include/grub/x86_64/time.h: Likewise.

	* include/grub/x86_64/types.h: Likewise.

	* kern/dl.c (GRUB_CPU_SIZEOF_VOID_P): Changed to
	 GRUB_TARGET_SIZEOF_VOID_P.

	* kern/efi/efi.c (grub_efi_locate_protocol): Wrap efi calls.
	(grub_efi_locate_handle): Likewise.
	(grub_efi_open_protocol): Likewise.
	(grub_efi_set_text_mode): Likewise.
	(grub_efi_stall): Likewise.
	(grub_exit): Likewise.
	(grub_reboot): Likewise.
	(grub_halt): Likewise.
	(grub_efi_exit_boot_services): Likewise.
	(grub_get_rtc): Likewise.

	* kern/efi/mm.c (MEMORY_MAP_SIZE): Change to 0x3000 for new models.
	(GRUB_CPU_SIZEOF_VOID_P): Changed to GRUB_TARGET_SIZEOF_VOID_P.
	(grub_efi_allocate_pages): Wrap efi calls.
	(grub_efi_free_pages): Wrap efi calls.
	(grub_efi_get_memory_map): Wrap efi calls.

	* kern/x86_64/dl.c: New file.

	* kern/x86_64/efi/callwrap.S: Likewise.

	* kern/x86_64/efi/startup.S: Likewise.

	* loader/efi/appleloader.c: Likewise.

	* loader/efi/chainloader.c (cmdline): New variable.
	(grub_chainloader_unload): Wrap efi calls.
	(grub_chainloader_boot): Likewise.
	(grub_rescue_cmd_chainloader): Wrap efi calls, handle
	command line.

	* loader/efi/chainloader_normal.c (chainloader_command):
	Change grub_chainloader_cmd to grub_rescue_cmd_chainloader, pass
	command line.

	* loader/i386/efi/linux.c (allocate_pages): Change allocation
	method.
	(grub_e820_add_region): New function.
	(grub_linux_boot): Construct e820 map from efi map, handle x86_64
	booting.
	(grub_find_video_card): New function.
	(grub_linux_setup_video): New function.
	(grub_rescue_cmd_linux): Probe for video information.

	* normal/x86_64/setjmp.S: New file.

	* term/efi/console.c (map_char): New function.
	(grub_console_putchar): Map unicode char.
	(grub_console_checkkey): Wrap efi calls.
	(grub_console_getkey): Likewise.
	(grub_console_getwh): Likewise.
	(grub_console_gotoxy): Likewise.
	(grub_console_cls): Likewise.
	(grub_console_setcolorstate): Likewise.
	(grub_console_setcursor): Likewise.

	* util/i386/efi/grub-mkimage.c: Add support for x86_64.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-06-30  5:05                         ` Bean
  2008-07-02 13:43                           ` Bean
@ 2008-07-05 23:02                           ` Isaac Dupree
  2008-07-06  4:31                             ` Bean
  1 sibling, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-07-05 23:02 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> Hi,
> 
> Perhaps you can also try the binary version at:
> 
> http://grub4dos.sourceforge.net/grub2/grub.efi.1
> 
> A friend of mine have tested in in 32-bit EFI firmware, there is no
> problem for him.

It confuses me!  I could boot it from refit as EFI.  Then it claimed to 
be GRUB 0.97.  The "help" looked slightly different that what I was 
familiar with (but I've never used grub1 so I don't know...); and 
`reboot` worked.  I didn't test more yet.. should I?

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-05 23:02                           ` Isaac Dupree
@ 2008-07-06  4:31                             ` Bean
  2008-07-08 16:16                               ` Isaac Dupree
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-06  4:31 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, Jul 6, 2008 at 7:02 AM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> Hi,
>>
>> Perhaps you can also try the binary version at:
>>
>> http://grub4dos.sourceforge.net/grub2/grub.efi.1
>>
>> A friend of mine have tested in in 32-bit EFI firmware, there is no
>> problem for him.
>
> It confuses me!  I could boot it from refit as EFI.  Then it claimed to be
> GRUB 0.97.  The "help" looked slightly different that what I was familiar
> with (but I've never used grub1 so I don't know...); and `reboot` worked.  I
> didn't test more yet.. should I?

Hi,

That's the fedora efi loader, have you used the right file ?

BTW, you need to rename it as grub.efi, refit can't find files with .1 suffix.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-06  4:31                             ` Bean
@ 2008-07-08 16:16                               ` Isaac Dupree
  2008-07-08 16:31                                 ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Isaac Dupree @ 2008-07-08 16:16 UTC (permalink / raw)
  To: The development of GRUB 2

Bean wrote:
> On Sun, Jul 6, 2008 at 7:02 AM, Isaac Dupree
> <id@isaac.cedarswampstudios.org> wrote:
>> Bean wrote:
>>> Hi,
>>>
>>> Perhaps you can also try the binary version at:
>>>
>>> http://grub4dos.sourceforge.net/grub2/grub.efi.1
>>>
>>> A friend of mine have tested in in 32-bit EFI firmware, there is no
>>> problem for him.
>> It confuses me!  I could boot it from refit as EFI.  Then it claimed to be
>> GRUB 0.97.  The "help" looked slightly different that what I was familiar
>> with (but I've never used grub1 so I don't know...); and `reboot` worked.  I
>> didn't test more yet.. should I?
> 
> Hi,
> 
> That's the fedora efi loader, have you used the right file ?
> 
> BTW, you need to rename it as grub.efi, refit can't find files with .1 suffix.

oh, oops :-/  Now, actually using that file :-)
-- reboot and lspci work, unlike in my version (I wonder why they're 
different??)
-- appleloader works equally badly as with my compile.
-- I tried passing video=intelfb to linux; it worked under grub2-pc but 
didn't improve anything under efi.

-Isaac



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-08 16:16                               ` Isaac Dupree
@ 2008-07-08 16:31                                 ` Bean
  2008-07-12 14:41                                   ` Robert Millan
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-08 16:31 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Jul 9, 2008 at 12:16 AM, Isaac Dupree
<id@isaac.cedarswampstudios.org> wrote:
> Bean wrote:
>>
>> On Sun, Jul 6, 2008 at 7:02 AM, Isaac Dupree
>> <id@isaac.cedarswampstudios.org> wrote:
>>>
>>> Bean wrote:
>>>>
>>>> Hi,
>>>>
>>>> Perhaps you can also try the binary version at:
>>>>
>>>> http://grub4dos.sourceforge.net/grub2/grub.efi.1
>>>>
>>>> A friend of mine have tested in in 32-bit EFI firmware, there is no
>>>> problem for him.
>>>
>>> It confuses me!  I could boot it from refit as EFI.  Then it claimed to
>>> be
>>> GRUB 0.97.  The "help" looked slightly different that what I was familiar
>>> with (but I've never used grub1 so I don't know...); and `reboot` worked.
>>>  I
>>> didn't test more yet.. should I?
>>
>> Hi,
>>
>> That's the fedora efi loader, have you used the right file ?
>>
>> BTW, you need to rename it as grub.efi, refit can't find files with .1
>> suffix.
>
> oh, oops :-/  Now, actually using that file :-)
> -- reboot and lspci work, unlike in my version (I wonder why they're
> different??)

Oh nice. What about hfs+, can you read files from the osx partition ?

> -- appleloader works equally badly as with my compile.

This command is firmware related, some model may not work.

> -- I tried passing video=intelfb to linux; it worked under grub2-pc but
> didn't improve anything under efi.

intelfb doesn't work. The only way to see console in efi is to use
video=vesafb or video=efifb. grub2 will detect these options and setup
frame buffer for you. You also need to use agp=off to disable agp.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-08 16:31                                 ` Bean
@ 2008-07-12 14:41                                   ` Robert Millan
  2008-07-12 15:16                                     ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Robert Millan @ 2008-07-12 14:41 UTC (permalink / raw)
  To: The development of GRUB 2

On Wed, Jul 09, 2008 at 12:31:53AM +0800, Bean wrote:
> > -- I tried passing video=intelfb to linux; it worked under grub2-pc but
> > didn't improve anything under efi.
> 
> intelfb doesn't work. The only way to see console in efi is to use
> video=vesafb or video=efifb.

How come?  I thought intelfb used the bare hardware.

> grub2 will detect these options and setup
> frame buffer for you.

Can you be more specific?  I thought grub was completely agnostic about Linux
parameters.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 14:41                                   ` Robert Millan
@ 2008-07-12 15:16                                     ` Bean
  2008-07-12 15:26                                       ` Bean
  2008-07-12 15:26                                       ` [PATCH] New x86_64 EFI patch Robert Millan
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-07-12 15:16 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 10:41 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Wed, Jul 09, 2008 at 12:31:53AM +0800, Bean wrote:
>> > -- I tried passing video=intelfb to linux; it worked under grub2-pc but
>> > didn't improve anything under efi.
>>
>> intelfb doesn't work. The only way to see console in efi is to use
>> video=vesafb or video=efifb.
>
> How come?  I thought intelfb used the bare hardware.

The video register in efi mode is not setup in the same way as bios.
There are two sets of register. In EFI, set A is completely zero,
while set B have non-zero value. But in bios mode, both set have
non-zero value. I guess this is because bios have text and graphic
mode, while efi only have graphic mode. (text mode in efi is emulated)

>
>> grub2 will detect these options and setup
>> frame buffer for you.
>
> Can you be more specific?  I thought grub was completely agnostic about Linux
> parameters.

In the parameter passed to linux kernel, there are fields for video
adapter information, for example, frame buffer address, line length,
etc. Normally, we don't have to worry about it, but in the case of
efi, we must fill it in, as kernel can't detect the information
properly.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 15:16                                     ` Bean
@ 2008-07-12 15:26                                       ` Bean
  2008-07-12 17:10                                         ` Robert Millan
  2008-07-12 15:26                                       ` [PATCH] New x86_64 EFI patch Robert Millan
  1 sibling, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-12 15:26 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 11:16 PM, Bean <bean123ch@gmail.com> wrote:
>> Can you be more specific?  I thought grub was completely agnostic about Linux
>> parameters.
>
> In the parameter passed to linux kernel, there are fields for video
> adapter information, for example, frame buffer address, line length,
> etc. Normally, we don't have to worry about it, but in the case of
> efi, we must fill it in, as kernel can't detect the information
> properly.

Hi,

BTW, it's the real mode part of Linux kernel that takes care of such
job. It gathers video information by querying vbe. But in efi, we skip
the real mode part and jump to protected mode directly, so we must
also provide kernel with similar information that would be setup by
the real mode part.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 15:16                                     ` Bean
  2008-07-12 15:26                                       ` Bean
@ 2008-07-12 15:26                                       ` Robert Millan
  2008-07-12 15:37                                         ` Bean
  1 sibling, 1 reply; 45+ messages in thread
From: Robert Millan @ 2008-07-12 15:26 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 11:16:31PM +0800, Bean wrote:
> On Sat, Jul 12, 2008 at 10:41 PM, Robert Millan <rmh@aybabtu.com> wrote:
> > On Wed, Jul 09, 2008 at 12:31:53AM +0800, Bean wrote:
> >> > -- I tried passing video=intelfb to linux; it worked under grub2-pc but
> >> > didn't improve anything under efi.
> >>
> >> intelfb doesn't work. The only way to see console in efi is to use
> >> video=vesafb or video=efifb.
> >
> > How come?  I thought intelfb used the bare hardware.
> 
> The video register in efi mode is not setup in the same way as bios.
> There are two sets of register. In EFI, set A is completely zero,
> while set B have non-zero value. But in bios mode, both set have
> non-zero value. I guess this is because bios have text and graphic
> mode, while efi only have graphic mode. (text mode in efi is emulated)

But isn't intelfb supposed to access the hardware without any support
from bios/vesa or efi?

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 15:26                                       ` [PATCH] New x86_64 EFI patch Robert Millan
@ 2008-07-12 15:37                                         ` Bean
  2008-07-12 15:48                                           ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-12 15:37 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 11:26 PM, Robert Millan <rmh@aybabtu.com> wrote:
> On Sat, Jul 12, 2008 at 11:16:31PM +0800, Bean wrote:
>> On Sat, Jul 12, 2008 at 10:41 PM, Robert Millan <rmh@aybabtu.com> wrote:
>> > On Wed, Jul 09, 2008 at 12:31:53AM +0800, Bean wrote:
>> >> > -- I tried passing video=intelfb to linux; it worked under grub2-pc but
>> >> > didn't improve anything under efi.
>> >>
>> >> intelfb doesn't work. The only way to see console in efi is to use
>> >> video=vesafb or video=efifb.
>> >
>> > How come?  I thought intelfb used the bare hardware.
>>
>> The video register in efi mode is not setup in the same way as bios.
>> There are two sets of register. In EFI, set A is completely zero,
>> while set B have non-zero value. But in bios mode, both set have
>> non-zero value. I guess this is because bios have text and graphic
>> mode, while efi only have graphic mode. (text mode in efi is emulated)
>
> But isn't intelfb supposed to access the hardware without any support
> from bios/vesa or efi?

Intelfb uses the environment setup before, it doesn't try to
reinitialize video registers.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 15:37                                         ` Bean
@ 2008-07-12 15:48                                           ` Bean
  0 siblings, 0 replies; 45+ messages in thread
From: Bean @ 2008-07-12 15:48 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 11:37 PM, Bean <bean123ch@gmail.com> wrote:
> On Sat, Jul 12, 2008 at 11:26 PM, Robert Millan <rmh@aybabtu.com> wrote:
>> On Sat, Jul 12, 2008 at 11:16:31PM +0800, Bean wrote:
>>> On Sat, Jul 12, 2008 at 10:41 PM, Robert Millan <rmh@aybabtu.com> wrote:
>>> > On Wed, Jul 09, 2008 at 12:31:53AM +0800, Bean wrote:
>>> >> > -- I tried passing video=intelfb to linux; it worked under grub2-pc but
>>> >> > didn't improve anything under efi.
>>> >>
>>> >> intelfb doesn't work. The only way to see console in efi is to use
>>> >> video=vesafb or video=efifb.
>>> >
>>> > How come?  I thought intelfb used the bare hardware.
>>>
>>> The video register in efi mode is not setup in the same way as bios.
>>> There are two sets of register. In EFI, set A is completely zero,
>>> while set B have non-zero value. But in bios mode, both set have
>>> non-zero value. I guess this is because bios have text and graphic
>>> mode, while efi only have graphic mode. (text mode in efi is emulated)
>>
>> But isn't intelfb supposed to access the hardware without any support
>> from bios/vesa or efi?
>
> Intelfb uses the environment setup before, it doesn't try to
> reinitialize video registers.

Hi,

I think the real problem of intelfb is that it uses agp, which
requires video hardware to be configure properly. But if we use vesafb
or efifb, it uses the frame buffer, so as long as we setup video
information properly in grub2, we can see console output.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 15:26                                       ` Bean
@ 2008-07-12 17:10                                         ` Robert Millan
  2008-07-12 18:05                                           ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Robert Millan @ 2008-07-12 17:10 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Jul 12, 2008 at 11:26:25PM +0800, Bean wrote:
> On Sat, Jul 12, 2008 at 11:16 PM, Bean <bean123ch@gmail.com> wrote:
> >> Can you be more specific?  I thought grub was completely agnostic about Linux
> >> parameters.
> >
> > In the parameter passed to linux kernel, there are fields for video
> > adapter information, for example, frame buffer address, line length,
> > etc. Normally, we don't have to worry about it, but in the case of
> > efi, we must fill it in, as kernel can't detect the information
> > properly.
> 
> Hi,
> 
> BTW, it's the real mode part of Linux kernel that takes care of such
> job. It gathers video information by querying vbe. But in efi, we skip
> the real mode part and jump to protected mode directly, so we must
> also provide kernel with similar information that would be setup by
> the real mode part.

Ah, I suppose this explains why Linux crashes when we try to load it via
grub-linuxbios (I reused the i386-pc loader when doing the port, unaware
that this would be an issue).

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 17:10                                         ` Robert Millan
@ 2008-07-12 18:05                                           ` Bean
  2008-07-17  9:50                                             ` Bean
  2008-07-19 15:01                                             ` generic BIOS-less boot (Re: [PATCH] New x86_64 EFI patch) Robert Millan
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-07-12 18:05 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, Jul 13, 2008 at 1:10 AM, Robert Millan <rmh@aybabtu.com> wrote:
> On Sat, Jul 12, 2008 at 11:26:25PM +0800, Bean wrote:
>> On Sat, Jul 12, 2008 at 11:16 PM, Bean <bean123ch@gmail.com> wrote:
>> >> Can you be more specific?  I thought grub was completely agnostic about Linux
>> >> parameters.
>> >
>> > In the parameter passed to linux kernel, there are fields for video
>> > adapter information, for example, frame buffer address, line length,
>> > etc. Normally, we don't have to worry about it, but in the case of
>> > efi, we must fill it in, as kernel can't detect the information
>> > properly.
>>
>> Hi,
>>
>> BTW, it's the real mode part of Linux kernel that takes care of such
>> job. It gathers video information by querying vbe. But in efi, we skip
>> the real mode part and jump to protected mode directly, so we must
>> also provide kernel with similar information that would be setup by
>> the real mode part.
>
> Ah, I suppose this explains why Linux crashes when we try to load it via
> grub-linuxbios (I reused the i386-pc loader when doing the port, unaware
> that this would be an issue).

Hi,

Here are the information gathered in real mode:

memory map information
video information
monitor information (edid)
hard disk information
perhaps more

The first two can be retrieved in grub, others are optional, kernel
can normally get the value itself.

Perhaps we can write a generic protected mode linux loader for i386.
Functions such as claiming memory, getting memory map and the like can
be wrapped in platform dependent call arch_xxx.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-12 18:05                                           ` Bean
@ 2008-07-17  9:50                                             ` Bean
  2008-07-17 15:02                                               ` Javier Martín
  2008-07-19 15:01                                             ` generic BIOS-less boot (Re: [PATCH] New x86_64 EFI patch) Robert Millan
  1 sibling, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-17  9:50 UTC (permalink / raw)
  To: The development of GRUB 2

Committed.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17  9:50                                             ` Bean
@ 2008-07-17 15:02                                               ` Javier Martín
  2008-07-17 15:18                                                 ` Bean
  2008-07-17 15:22                                                 ` Pavel Roskin
  0 siblings, 2 replies; 45+ messages in thread
From: Javier Martín @ 2008-07-17 15:02 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 1317 bytes --]

El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
> Committed.
> 
Seemingly, the fact that there is now separate recognition for "x86_64"
machine types has borked the current build system in amd64 PCs:

$ make
./config.status --recheck
running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
--prefix=/home/javier/Proyectos/grub/build/out/  --no-create
--no-recursion
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
configure: error: unsupported machine type
make: *** [config.status] Error 1

The current system would build bootloader files as i386-pc (with the
-m32 switch in gcc, which itself created the infamous "cannot find start
or _start" problem when a multilib version of gcc was not installed) and
helper files like grub-setup as amd64. This caused problems of its own,
like grub-emu (built as amd64) being unable to load any grub modules
(built as i386), but at least worked OOtB.

I was able to correctly recompile if I reconfigured GRUB with
--target=i386-pc-linux-gnu (i386-pc alone was not recognized). Is this
the current way to go? I feel it should not be so, because it multiboot2
comes out with amd64 support, there should be an x86_64-pc grub2.

[-- Attachment #2: Esta parte del mensaje está firmada digitalmente --]
[-- Type: application/pgp-signature, Size: 827 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:02                                               ` Javier Martín
@ 2008-07-17 15:18                                                 ` Bean
  2008-07-17 15:28                                                   ` Pavel Roskin
  2008-07-17 15:22                                                 ` Pavel Roskin
  1 sibling, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-17 15:18 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, Jul 17, 2008 at 11:02 PM, Javier Martín <lordhabbit@gmail.com> wrote:
> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
>> Committed.
>>
> Seemingly, the fact that there is now separate recognition for "x86_64"
> machine types has borked the current build system in amd64 PCs:
>
> $ make
> ./config.status --recheck
> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
> --no-recursion
> checking build system type... x86_64-unknown-linux-gnu
> checking host system type... x86_64-unknown-linux-gnu
> checking target system type... x86_64-unknown-linux-gnu
> configure: error: unsupported machine type
> make: *** [config.status] Error 1
>
> The current system would build bootloader files as i386-pc (with the
> -m32 switch in gcc, which itself created the infamous "cannot find start
> or _start" problem when a multilib version of gcc was not installed) and
> helper files like grub-setup as amd64. This caused problems of its own,
> like grub-emu (built as amd64) being unable to load any grub modules
> (built as i386), but at least worked OOtB.
>
> I was able to correctly recompile if I reconfigured GRUB with
> --target=i386-pc-linux-gnu (i386-pc alone was not recognized). Is this
> the current way to go? I feel it should not be so, because it multiboot2
> comes out with amd64 support, there should be an x86_64-pc grub2.

Hi,

To compile 32-bit efi:

./configure --platform=efi --target=i386

To compile 64-bit efi:

./configure --platform=efi --target=x86_64

This works in i386 and x86_64 host. If you don't use --target, it will
build native image.

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:02                                               ` Javier Martín
  2008-07-17 15:18                                                 ` Bean
@ 2008-07-17 15:22                                                 ` Pavel Roskin
  2008-07-17 15:26                                                   ` Bean
  1 sibling, 1 reply; 45+ messages in thread
From: Pavel Roskin @ 2008-07-17 15:22 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, 2008-07-17 at 17:02 +0200, Javier Martín wrote:
> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
> > Committed.
> > 
> Seemingly, the fact that there is now separate recognition for "x86_64"
> machine types has borked the current build system in amd64 PCs:
> 
> $ make
> ./config.status --recheck
> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
> --no-recursion
> checking build system type... x86_64-unknown-linux-gnu
> checking host system type... x86_64-unknown-linux-gnu
> checking target system type... x86_64-unknown-linux-gnu
> configure: error: unsupported machine type
> make: *** [config.status] Error 1

I've just noticed that.  I think x86_64 should default to "i386-pc"
platform.  I'll have a look how to do it nicely.

> The current system would build bootloader files as i386-pc (with the
> -m32 switch in gcc, which itself created the infamous "cannot find start
> or _start" problem when a multilib version of gcc was not installed) and
> helper files like grub-setup as amd64.

I was trying add an extra check there, but ran into more interesting
stuff.  Basically, the target checks should be better separated from the
rest.  I'll take another look.

>  This caused problems of its own,
> like grub-emu (built as amd64) being unable to load any grub modules
> (built as i386), but at least worked OOtB.

I didn't know grub-emu could load modules!  Live and learn :-)

> I was able to correctly recompile if I reconfigured GRUB with
> --target=i386-pc-linux-gnu (i386-pc alone was not recognized). Is this
> the current way to go? I feel it should not be so, because it multiboot2
> comes out with amd64 support, there should be an x86_64-pc grub2.

Perhaps we'll have it eventually.  But I agree, the default should be
restored for now.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:22                                                 ` Pavel Roskin
@ 2008-07-17 15:26                                                   ` Bean
  2008-07-17 15:45                                                     ` Javier Martín
  0 siblings, 1 reply; 45+ messages in thread
From: Bean @ 2008-07-17 15:26 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, Jul 17, 2008 at 11:22 PM, Pavel Roskin <proski@gnu.org> wrote:
> On Thu, 2008-07-17 at 17:02 +0200, Javier Martín wrote:
>> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
>> > Committed.
>> >
>> Seemingly, the fact that there is now separate recognition for "x86_64"
>> machine types has borked the current build system in amd64 PCs:
>>
>> $ make
>> ./config.status --recheck
>> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
>> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
>> --no-recursion
>> checking build system type... x86_64-unknown-linux-gnu
>> checking host system type... x86_64-unknown-linux-gnu
>> checking target system type... x86_64-unknown-linux-gnu
>> configure: error: unsupported machine type
>> make: *** [config.status] Error 1
>
> I've just noticed that.  I think x86_64 should default to "i386-pc"
> platform.  I'll have a look how to do it nicely.

I have the following in configure.ac:

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

If platform is not efi, x86_64 will become i386, perhaps there is
something I miss ?

-- 
Bean



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:18                                                 ` Bean
@ 2008-07-17 15:28                                                   ` Pavel Roskin
  0 siblings, 0 replies; 45+ messages in thread
From: Pavel Roskin @ 2008-07-17 15:28 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, 2008-07-17 at 23:18 +0800, Bean wrote:
> Hi,
> 
> To compile 32-bit efi:
> 
> ./configure --platform=efi --target=i386
> 
> To compile 64-bit efi:
> 
> ./configure --platform=efi --target=x86_64
> 
> This works in i386 and x86_64 host. If you don't use --target, it will
> build native image.

It won't.  There is no default defined for x86_64.  I'm fixing it now.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:26                                                   ` Bean
@ 2008-07-17 15:45                                                     ` Javier Martín
  2008-07-17 15:50                                                       ` Bean
  0 siblings, 1 reply; 45+ messages in thread
From: Javier Martín @ 2008-07-17 15:45 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2087 bytes --]

El jue, 17-07-2008 a las 23:26 +0800, Bean escribió:
> On Thu, Jul 17, 2008 at 11:22 PM, Pavel Roskin <proski@gnu.org> wrote:
> > On Thu, 2008-07-17 at 17:02 +0200, Javier Martín wrote:
> >> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
> >> > Committed.
> >> >
> >> Seemingly, the fact that there is now separate recognition for "x86_64"
> >> machine types has borked the current build system in amd64 PCs:
> >>
> >> $ make
> >> ./config.status --recheck
> >> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
> >> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
> >> --no-recursion
> >> checking build system type... x86_64-unknown-linux-gnu
> >> checking host system type... x86_64-unknown-linux-gnu
> >> checking target system type... x86_64-unknown-linux-gnu
> >> configure: error: unsupported machine type
> >> make: *** [config.status] Error 1
> >
> > I've just noticed that.  I think x86_64 should default to "i386-pc"
> > platform.  I'll have a look how to do it nicely.
> 
> I have the following in configure.ac:
> 
> 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
> 
> If platform is not efi, x86_64 will become i386, perhaps there is
> something I miss ?
> 

It does not reach that point, the "unsupported machine type" message is
thrown by this earlier check (line 59)

# Guess the platform if not specified.
if test "x$with_platform" = x; then
  case "$target_cpu"-"$target_vendor" in
    i386-apple) platform=efi ;;
    i386-*) platform=pc ;;
    powerpc-*) platform=ieee1275 ;;
    sparc64-*) platform=ieee1275 ;;
    *) AC_MSG_ERROR([unsupported machine type]) ;;
  esac
else
  platform="$with_platform"
fi

[-- Attachment #2: Esta parte del mensaje está firmada digitalmente --]
[-- Type: application/pgp-signature, Size: 827 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:45                                                     ` Javier Martín
@ 2008-07-17 15:50                                                       ` Bean
  2008-07-17 16:01                                                         ` Javier Martín
  2008-07-17 16:06                                                         ` Pavel Roskin
  0 siblings, 2 replies; 45+ messages in thread
From: Bean @ 2008-07-17 15:50 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, Jul 17, 2008 at 11:45 PM, Javier Martín <lordhabbit@gmail.com> wrote:
> El jue, 17-07-2008 a las 23:26 +0800, Bean escribió:
>> On Thu, Jul 17, 2008 at 11:22 PM, Pavel Roskin <proski@gnu.org> wrote:
>> > On Thu, 2008-07-17 at 17:02 +0200, Javier Martín wrote:
>> >> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
>> >> > Committed.
>> >> >
>> >> Seemingly, the fact that there is now separate recognition for "x86_64"
>> >> machine types has borked the current build system in amd64 PCs:
>> >>
>> >> $ make
>> >> ./config.status --recheck
>> >> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
>> >> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
>> >> --no-recursion
>> >> checking build system type... x86_64-unknown-linux-gnu
>> >> checking host system type... x86_64-unknown-linux-gnu
>> >> checking target system type... x86_64-unknown-linux-gnu
>> >> configure: error: unsupported machine type
>> >> make: *** [config.status] Error 1
>> >
>> > I've just noticed that.  I think x86_64 should default to "i386-pc"
>> > platform.  I'll have a look how to do it nicely.
>>
>> I have the following in configure.ac:
>>
>> 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
>>
>> If platform is not efi, x86_64 will become i386, perhaps there is
>> something I miss ?
>>
>
> It does not reach that point, the "unsupported machine type" message is
> thrown by this earlier check (line 59)

Hi,

Oh, you're right, use this patch:

diff --git a/configure.ac b/configure.ac
index 943b9fe..45eb472 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,6 +61,7 @@ if test "x$with_platform" = x; then
   case "$target_cpu"-"$target_vendor" in
     i386-apple) platform=efi ;;
     i386-*) platform=pc ;;
+    x86_64-*) platform=pc ;;
     powerpc-*) platform=ieee1275 ;;
     sparc64-*) platform=ieee1275 ;;
     *) AC_MSG_ERROR([unsupported machine type]) ;;


-- 
Bean



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:50                                                       ` Bean
@ 2008-07-17 16:01                                                         ` Javier Martín
  2008-07-17 16:17                                                           ` Pavel Roskin
  2008-07-17 16:06                                                         ` Pavel Roskin
  1 sibling, 1 reply; 45+ messages in thread
From: Javier Martín @ 2008-07-17 16:01 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 3508 bytes --]

El jue, 17-07-2008 a las 23:50 +0800, Bean escribió:
> On Thu, Jul 17, 2008 at 11:45 PM, Javier Martín <lordhabbit@gmail.com> wrote:
> > El jue, 17-07-2008 a las 23:26 +0800, Bean escribió:
> >> On Thu, Jul 17, 2008 at 11:22 PM, Pavel Roskin <proski@gnu.org> wrote:
> >> > On Thu, 2008-07-17 at 17:02 +0200, Javier Martín wrote:
> >> >> El jue, 17-07-2008 a las 17:50 +0800, Bean escribió:
> >> >> > Committed.
> >> >> >
> >> >> Seemingly, the fact that there is now separate recognition for "x86_64"
> >> >> machine types has borked the current build system in amd64 PCs:
> >> >>
> >> >> $ make
> >> >> ./config.status --recheck
> >> >> running CONFIG_SHELL=/bin/bash /bin/bash ../src/configure
> >> >> --prefix=/home/javier/Proyectos/grub/build/out/  --no-create
> >> >> --no-recursion
> >> >> checking build system type... x86_64-unknown-linux-gnu
> >> >> checking host system type... x86_64-unknown-linux-gnu
> >> >> checking target system type... x86_64-unknown-linux-gnu
> >> >> configure: error: unsupported machine type
> >> >> make: *** [config.status] Error 1
> >> >
> >> > I've just noticed that.  I think x86_64 should default to "i386-pc"
> >> > platform.  I'll have a look how to do it nicely.
> >>
> >> I have the following in configure.ac:
> >>
> >> 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
> >>
> >> If platform is not efi, x86_64 will become i386, perhaps there is
> >> something I miss ?
> >>
> >
> > It does not reach that point, the "unsupported machine type" message is
> > thrown by this earlier check (line 59)
> 
> Hi,
> 
> Oh, you're right, use this patch:
> 
> diff --git a/configure.ac b/configure.ac
> index 943b9fe..45eb472 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -61,6 +61,7 @@ if test "x$with_platform" = x; then
>    case "$target_cpu"-"$target_vendor" in
>      i386-apple) platform=efi ;;
>      i386-*) platform=pc ;;
> +    x86_64-*) platform=pc ;;
>      powerpc-*) platform=ieee1275 ;;
>      sparc64-*) platform=ieee1275 ;;
>      *) AC_MSG_ERROR([unsupported machine type]) ;;
> 
> 

I think this one would be better, as it follows the structure what's
done with i386: vendor=apple -> efi; anything_else -> pc. Also, this one
errors out with a more understandable message that does not conflict
with another check some lines down.

Index: configure.ac
===================================================================
--- configure.ac        (revisión: 1714)
+++ configure.ac        (copia de trabajo)
@@ -59,11 +59,11 @@
 # Guess the platform if not specified.
 if test "x$with_platform" = x; then
   case "$target_cpu"-"$target_vendor" in
-    i386-apple) platform=efi ;;
-    i386-*) platform=pc ;;
+    i386-apple|x86_64-apple) platform=efi ;;
+    i386-*|x86_64-*) platform=pc ;;
     powerpc-*) platform=ieee1275 ;;
     sparc64-*) platform=ieee1275 ;;
-    *) AC_MSG_ERROR([unsupported machine type]) ;;
+    *) AC_MSG_ERROR([unable to guess platform. Use --with-platform]) ;;
   esac
 else
   platform="$with_platform"


[-- Attachment #2: Esta parte del mensaje está firmada digitalmente --]
[-- Type: application/pgp-signature, Size: 827 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 15:50                                                       ` Bean
  2008-07-17 16:01                                                         ` Javier Martín
@ 2008-07-17 16:06                                                         ` Pavel Roskin
  2008-07-17 16:17                                                           ` Javier Martín
  1 sibling, 1 reply; 45+ messages in thread
From: Pavel Roskin @ 2008-07-17 16:06 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, 2008-07-17 at 23:50 +0800, Bean wrote:
> > It does not reach that point, the "unsupported machine type" message is
> > thrown by this earlier check (line 59)
> 
> Hi,
> 
> Oh, you're right, use this patch:

It's there already.  Now I'm trying to simplify checks and make output
more comprehensible.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 16:06                                                         ` Pavel Roskin
@ 2008-07-17 16:17                                                           ` Javier Martín
  0 siblings, 0 replies; 45+ messages in thread
From: Javier Martín @ 2008-07-17 16:17 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 910 bytes --]

El jue, 17-07-2008 a las 12:06 -0400, Pavel Roskin escribió:
> On Thu, 2008-07-17 at 23:50 +0800, Bean wrote:
> > > It does not reach that point, the "unsupported machine type" message is
> > > thrown by this earlier check (line 59)
> > 
> > Hi,
> > 
> > Oh, you're right, use this patch:
> 
> It's there already.  Now I'm trying to simplify checks and make output
> more comprehensible.
> 
Dunno if you read the latter patch, but nevertheless those three checks
have some nasty circular dependencies. Besides, now that we're talking
about the build system, the Makefile.in file refers to the inexistent
conf/i386-coreboot.rmk file, and that's affecting every other system
because make "can't find a rule to make conf/i386-coreboot.rmk, required
for conf/i386.coreboot.mk. Halt" - I suspect a rename to/from
conf/i386-linuxbios.rmk file was left incomplete or is still uncommitted
to SVN.

[-- Attachment #2: Esta parte del mensaje está firmada digitalmente --]
[-- Type: application/pgp-signature, Size: 827 bytes --]

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] New x86_64 EFI patch
  2008-07-17 16:01                                                         ` Javier Martín
@ 2008-07-17 16:17                                                           ` Pavel Roskin
  0 siblings, 0 replies; 45+ messages in thread
From: Pavel Roskin @ 2008-07-17 16:17 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, 2008-07-17 at 18:01 +0200, Javier Martín wrote:

> I think this one would be better, as it follows the structure what's
> done with i386: vendor=apple -> efi; anything_else -> pc.

That's a good call.  I'm working on a more radical patch now.  I'll post
it for review.

>  Also, this one
> errors out with a more understandable message that does not conflict
> with another check some lines down.

I agree that the messages should be improved.

> Index: configure.ac
> ===================================================================
> --- configure.ac        (revisión: 1714)
> +++ configure.ac        (copia de trabajo)
> @@ -59,11 +59,11 @@
>  # Guess the platform if not specified.
>  if test "x$with_platform" = x; then
>    case "$target_cpu"-"$target_vendor" in
> -    i386-apple) platform=efi ;;
> -    i386-*) platform=pc ;;
> +    i386-apple|x86_64-apple) platform=efi ;;
> +    i386-*|x86_64-*) platform=pc ;;
>      powerpc-*) platform=ieee1275 ;;
>      sparc64-*) platform=ieee1275 ;;
> -    *) AC_MSG_ERROR([unsupported machine type]) ;;
> +    *) AC_MSG_ERROR([unable to guess platform. Use --with-platform]) ;;

That's misleading.  We can guess platform for any supported CPU (well,
we try out best).  The real problem is that the CPU is not supported,
and that's what the message should say.

-- 
Regards,
Pavel Roskin



^ permalink raw reply	[flat|nested] 45+ messages in thread

* generic BIOS-less boot (Re: [PATCH] New x86_64 EFI patch)
  2008-07-12 18:05                                           ` Bean
  2008-07-17  9:50                                             ` Bean
@ 2008-07-19 15:01                                             ` Robert Millan
  1 sibling, 0 replies; 45+ messages in thread
From: Robert Millan @ 2008-07-19 15:01 UTC (permalink / raw)
  To: The development of GRUB 2

On Sun, Jul 13, 2008 at 02:05:13AM +0800, Bean wrote:
> 
> Hi,
> 
> Here are the information gathered in real mode:
> 
> memory map information
> video information
> monitor information (edid)
> hard disk information
> perhaps more
> 
> The first two can be retrieved in grub, others are optional, kernel
> can normally get the value itself.
> 
> Perhaps we can write a generic protected mode linux loader for i386.
> Functions such as claiming memory, getting memory map and the like can
> be wrapped in platform dependent call arch_xxx.

I was wondering if maybe it would be simpler to emulate the BIOS (and use
stubs where suitable).  Memory map would be simple to produce since we
already have this information which we used to initialize our heap.  As
for video information, do you have more details (or know a document that
explains what's probed for)?  If it's only for vesa modes maybe we could
just stub it.

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)



^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2008-07-19 15:02 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-20 17:04 [PATCH] New x86_64 EFI patch Bean
2008-06-21 17:04 ` Bean
2008-06-23 11:58   ` Isaac Dupree
2008-06-23 12:53     ` Bean
2008-06-24 12:52   ` Isaac Dupree
2008-06-24 13:12     ` Bean
2008-06-24 16:57       ` Isaac Dupree
2008-06-24 17:11         ` Bean
2008-06-24 21:59           ` Isaac Dupree
2008-06-25  6:49             ` Bean
2008-06-25 12:50               ` Isaac Dupree
2008-06-25 13:54                 ` Bean
2008-06-28 10:51                   ` Isaac Dupree
2008-06-28 11:55                     ` Bean
2008-06-29 23:55                       ` Isaac Dupree
2008-06-30  5:05                         ` Bean
2008-07-02 13:43                           ` Bean
2008-07-05 23:02                           ` Isaac Dupree
2008-07-06  4:31                             ` Bean
2008-07-08 16:16                               ` Isaac Dupree
2008-07-08 16:31                                 ` Bean
2008-07-12 14:41                                   ` Robert Millan
2008-07-12 15:16                                     ` Bean
2008-07-12 15:26                                       ` Bean
2008-07-12 17:10                                         ` Robert Millan
2008-07-12 18:05                                           ` Bean
2008-07-17  9:50                                             ` Bean
2008-07-17 15:02                                               ` Javier Martín
2008-07-17 15:18                                                 ` Bean
2008-07-17 15:28                                                   ` Pavel Roskin
2008-07-17 15:22                                                 ` Pavel Roskin
2008-07-17 15:26                                                   ` Bean
2008-07-17 15:45                                                     ` Javier Martín
2008-07-17 15:50                                                       ` Bean
2008-07-17 16:01                                                         ` Javier Martín
2008-07-17 16:17                                                           ` Pavel Roskin
2008-07-17 16:06                                                         ` Pavel Roskin
2008-07-17 16:17                                                           ` Javier Martín
2008-07-19 15:01                                             ` generic BIOS-less boot (Re: [PATCH] New x86_64 EFI patch) Robert Millan
2008-07-12 15:26                                       ` [PATCH] New x86_64 EFI patch Robert Millan
2008-07-12 15:37                                         ` Bean
2008-07-12 15:48                                           ` Bean
2008-06-25 12:59               ` Isaac Dupree
2008-07-03 18:11 ` Marco Gerards
2008-07-03 19:51   ` Bean

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.