* Can we get video card information in EFI environment ?
@ 2008-06-07 18:38 Bean
2008-06-08 17:08 ` Bean
0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2008-06-07 18:38 UTC (permalink / raw)
To: The development of GRUB 2
Hi,
I encounter a small problem when writing the x86_64 EFI code. The
loader does work, but I'm struggle to get the frame buffer to work. In
order to do so, I need some information to fill in the linux header:
1. frame buffer address
2. frame buffer size
3. line buffer length
Other information, width, height and color depth can be retrieved
using UGA Draw protocol.
I have figured out the correct value for my macbook. By setting them
manually, I can get vesafb and efifb to work properly. intelfb is
supposed to work by accessing video card directly, but it doesn't
work for me. imacfb is just a hack, it works if I feed in the value
properly.
But for a normal user, they can't know the values. Is there a way to
query them using pci interface, or is there some EFI service that I
miss ?
BTW, EFI 2.0 support Gop protocol which can be used to returned the
above information. Unfortunately, apple don't support it. When would
they upgrade to 2.0 ?
--
Bean
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Can we get video card information in EFI environment ?
2008-06-07 18:38 Can we get video card information in EFI environment ? Bean
@ 2008-06-08 17:08 ` Bean
2008-06-08 17:17 ` Vesa Jääskeläinen
0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2008-06-08 17:08 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1886 bytes --]
On Sun, Jun 8, 2008 at 2:38 AM, Bean <bean123ch@gmail.com> wrote:
> Hi,
>
> I encounter a small problem when writing the x86_64 EFI code. The
> loader does work, but I'm struggle to get the frame buffer to work. In
> order to do so, I need some information to fill in the linux header:
>
> 1. frame buffer address
> 2. frame buffer size
> 3. line buffer length
>
> Other information, width, height and color depth can be retrieved
> using UGA Draw protocol.
>
> I have figured out the correct value for my macbook. By setting them
> manually, I can get vesafb and efifb to work properly. intelfb is
> supposed to work by accessing video card directly, but it doesn't
> work for me. imacfb is just a hack, it works if I feed in the value
> properly.
>
> But for a normal user, they can't know the values. Is there a way to
> query them using pci interface, or is there some EFI service that I
> miss ?
>
> BTW, EFI 2.0 support Gop protocol which can be used to returned the
> above information. Unfortunately, apple don't support it. When would
> they upgrade to 2.0 ?
Hi,
I figure it out. The new patch query pci base address registry to get
the frame buffer address, I hope it works.
To load the framebuffer, you need to use the video parameter:
linux /boot/vmlinuz video=vesafb root=/dev/sda3
You can also use efifb.
BTW, you need to remove the udev start script from /etc/rcS.d,
otherwise the screen would scramble again. I believe the cause is
agppart. Fame buffer of EFI is a little strange, the line length is
not equal to width * 4, for example, my macbook:
width: 1280
depth: 32
line length: 8192
So there is some invisible space after the screen boundary. But in
bios emulation mode, the length is exactly width * 4. I think the
driver should take this into account, or reconfigure the video
hardware to use the new line length. (Anyone know how to do it ?)
--
Bean
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: efi_3.diff --]
[-- Type: text/x-diff; name=efi_3.diff, Size: 109509 bytes --]
diff --git a/conf/i386-efi.mk b/conf/i386-efi.mk
index b6a9d26..57abbd5 100644
--- a/conf/i386-efi.mk
+++ b/conf/i386-efi.mk
@@ -116,7 +116,7 @@ grub-install: util/i386/efi/grub-install.in $(util/i386/efi/grub-install.in_DEPE
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
- _linux.mod linux.mod cpuid.mod halt.mod reboot.mod
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -1351,4 +1351,116 @@ partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DE
reboot_mod_CFLAGS = $(COMMON_CFLAGS)
reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For pci.mod
+pci_mod_SOURCES = bus/pci.c
+CLEANFILES += pci.mod mod-pci.o mod-pci.c pre-pci.o pci_mod-bus_pci.o und-pci.lst
+ifneq ($(pci_mod_EXPORTS),no)
+CLEANFILES += def-pci.lst
+DEFSYMFILES += def-pci.lst
+endif
+MOSTLYCLEANFILES += pci_mod-bus_pci.d
+UNDSYMFILES += und-pci.lst
+
+pci.mod: pre-pci.o mod-pci.o
+ -rm -f $@
+ $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^
+ $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-pci.o: $(pci_mod_DEPENDENCIES) pci_mod-bus_pci.o
+ -rm -f $@
+ $(TARGET_CC) $(pci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pci_mod-bus_pci.o
+
+mod-pci.o: mod-pci.c
+ $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -c -o $@ $<
+
+mod-pci.c: moddep.lst genmodsrc.sh
+ sh $(srcdir)/genmodsrc.sh 'pci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(pci_mod_EXPORTS),no)
+def-pci.lst: pre-pci.o
+ $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 pci/' > $@
+endif
+
+und-pci.lst: pre-pci.o
+ echo 'pci' > $@
+ $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+pci_mod-bus_pci.o: bus/pci.c $(bus/pci.c_DEPENDENCIES)
+ $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -MD -c -o $@ $<
+-include pci_mod-bus_pci.d
+
+CLEANFILES += cmd-pci_mod-bus_pci.lst fs-pci_mod-bus_pci.lst partmap-pci_mod-bus_pci.lst
+COMMANDFILES += cmd-pci_mod-bus_pci.lst
+FSFILES += fs-pci_mod-bus_pci.lst
+PARTMAPFILES += partmap-pci_mod-bus_pci.lst
+
+cmd-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) gencmdlist.sh
+ set -e; $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh pci > $@ || (rm -f $@; exit 1)
+
+fs-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genfslist.sh
+ set -e; $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh pci > $@ || (rm -f $@; exit 1)
+
+partmap-pci_mod-bus_pci.lst: bus/pci.c $(bus/pci.c_DEPENDENCIES) genpartmaplist.sh
+ set -e; $(TARGET_CC) -Ibus -I$(srcdir)/bus $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(pci_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh pci > $@ || (rm -f $@; exit 1)
+
+
+pci_mod_CFLAGS = $(COMMON_CFLAGS)
+pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For lspci.mod
+lspci_mod_SOURCES = commands/lspci.c
+CLEANFILES += lspci.mod mod-lspci.o mod-lspci.c pre-lspci.o lspci_mod-commands_lspci.o und-lspci.lst
+ifneq ($(lspci_mod_EXPORTS),no)
+CLEANFILES += def-lspci.lst
+DEFSYMFILES += def-lspci.lst
+endif
+MOSTLYCLEANFILES += lspci_mod-commands_lspci.d
+UNDSYMFILES += und-lspci.lst
+
+lspci.mod: pre-lspci.o mod-lspci.o
+ -rm -f $@
+ $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^
+ $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
+
+pre-lspci.o: $(lspci_mod_DEPENDENCIES) lspci_mod-commands_lspci.o
+ -rm -f $@
+ $(TARGET_CC) $(lspci_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ lspci_mod-commands_lspci.o
+
+mod-lspci.o: mod-lspci.c
+ $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -c -o $@ $<
+
+mod-lspci.c: moddep.lst genmodsrc.sh
+ sh $(srcdir)/genmodsrc.sh 'lspci' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(lspci_mod_EXPORTS),no)
+def-lspci.lst: pre-lspci.o
+ $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 lspci/' > $@
+endif
+
+und-lspci.lst: pre-lspci.o
+ echo 'lspci' > $@
+ $(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+lspci_mod-commands_lspci.o: commands/lspci.c $(commands/lspci.c_DEPENDENCIES)
+ $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -MD -c -o $@ $<
+-include lspci_mod-commands_lspci.d
+
+CLEANFILES += cmd-lspci_mod-commands_lspci.lst fs-lspci_mod-commands_lspci.lst partmap-lspci_mod-commands_lspci.lst
+COMMANDFILES += cmd-lspci_mod-commands_lspci.lst
+FSFILES += fs-lspci_mod-commands_lspci.lst
+PARTMAPFILES += partmap-lspci_mod-commands_lspci.lst
+
+cmd-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) gencmdlist.sh
+ set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh lspci > $@ || (rm -f $@; exit 1)
+
+fs-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genfslist.sh
+ set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh lspci > $@ || (rm -f $@; exit 1)
+
+partmap-lspci_mod-commands_lspci.lst: commands/lspci.c $(commands/lspci.c_DEPENDENCIES) genpartmaplist.sh
+ set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(lspci_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh lspci > $@ || (rm -f $@; exit 1)
+
+
+lspci_mod_CFLAGS = $(COMMON_CFLAGS)
+lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index 87626c2..d616415 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -74,7 +74,7 @@ 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
+ _linux.mod linux.mod cpuid.mod halt.mod reboot.mod pci.mod lspci.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
@@ -147,4 +147,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..8b1436c
--- /dev/null
+++ b/conf/x86_64-efi.rmk
@@ -0,0 +1,164 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin -m64
+COMMON_CFLAGS = -fno-builtin -m64
+COMMON_LDFLAGS = -melf_x86_64 -nostdlib
+
+# Used by various components. These rules need to precede them.
+normal/execute.c_DEPENDENCIES = grub_script.tab.h
+normal/command.c_DEPENDENCIES = grub_script.tab.h
+normal/function.c_DEPENDENCIES = grub_script.tab.h
+normal/lexer.c_DEPENDENCIES = grub_script.tab.h
+
+# Utilities.
+bin_UTILITIES = grub-mkimage
+#sbin_UTILITIES = grub-mkdevicemap
+#ifeq ($(enable_grub_emu), yes)
+#sbin_UTILITIES += grub-emu
+#endif
+
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
+ util/resolve.c
+
+# For grub-setup.
+#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/biosdisk.c \
+# util/misc.c util/getroot.c kern/device.c kern/disk.c \
+# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
+# fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c \
+# fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
+# kern/fs.c kern/env.c fs/fshelp.c
+
+# For grub-mkdevicemap.
+grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c \
+ util/i386/get_disk_name.c
+
+# For grub-emu.
+util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
+grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
+ commands/configfile.c commands/help.c \
+ commands/terminal.c commands/ls.c commands/test.c \
+ commands/search.c commands/hexdump.c \
+ commands/halt.c commands/reboot.c \
+ commands/i386/cpuid.c \
+ disk/loopback.c \
+ \
+ fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
+ fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
+ fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
+ fs/ufs.c fs/xfs.c fs/afs.c \
+ \
+ io/gzio.c \
+ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \
+ kern/err.c \
+ normal/execute.c kern/file.c kern/fs.c normal/lexer.c \
+ kern/loader.c kern/main.c kern/misc.c kern/parser.c \
+ grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
+ normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
+ normal/completion.c normal/context.c normal/main.c \
+ normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
+ normal/color.c \
+ partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
+ partmap/acorn.c partmap/gpt.c \
+ util/console.c util/hostfs.c util/grub-emu.c util/misc.c \
+ util/biosdisk.c util/getroot.c \
+ util/i386/pc/misc.c \
+ \
+ disk/raid.c disk/lvm.c \
+ grub_emu_init.c
+
+grub_emu_LDFLAGS = $(LIBCURSES)
+
+# Scripts.
+sbin_SCRIPTS = grub-install
+
+# For grub-install.
+grub_install_SOURCES = util/i386/efi/grub-install.in
+
+# Modules.
+pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \
+ cpuid.mod halt.mod reboot.mod _linux.mod linux.mod 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 _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 b/configure
index 1f44d19..e7de78c 100755
--- a/configure
+++ b/configure
@@ -1927,13 +1927,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) ;;
- *) { { echo "$as_me:$LINENO: error: unsupported CPU type" >&5
-echo "$as_me: error: unsupported CPU type" >&2;}
- { (exit 1); exit 1; }; } ;;
esac
# Specify the platform (such as firmware).
@@ -1959,9 +1952,31 @@ else
platform="$with_platform"
fi
+if test "x$platform" = "xefi" ; then
+ case "$target_cpu" in
+ i386) ;;
+ x86_64) target_m64=1 ;;
+ *) { { echo "$as_me:$LINENO: error: unsupported CPU type for EFI" >&5
+echo "$as_me: error: unsupported CPU type for EFI" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ case "$target_cpu" in
+ i386) ;;
+ x86_64) target_cpu=i386 target_m32=1 ;;
+ powerpc) ;;
+ powerpc64) target_cpu=powerpc target_m32=1;;
+ sparc64) ;;
+ *) { { echo "$as_me:$LINENO: error: unsupported CPU type" >&5
+echo "$as_me: error: unsupported CPU type" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+fi
+
# Sanity check.
case "$target_cpu"-"$platform" in
i386-efi) ;;
+ x86_64-efi) ;;
i386-pc) ;;
i386-linuxbios) ;;
i386-ieee1275) ;;
@@ -6686,6 +6701,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/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/fs/ext2.c b/fs/ext2.c
index ffe9e33..4e76097 100644
--- a/fs/ext2.c
+++ b/fs/ext2.c
@@ -443,14 +443,19 @@ grub_ext3_get_journal (struct grub_ext2_data *data)
log->last_block = grub_be_to_cpu32 (jsb->maxlen);
log->start_block = grub_be_to_cpu32 (jsb->start);
+ grub_printf ("header: %d %d %d\n", log->first_block, log->last_block, log->start_block);
+
last_num = num = 0;
block = log->start_block;
seq = grub_be_to_cpu32 (jsb->sequence);
+ grub_printf ("seq: %d\n", seq);
while (1)
{
struct grub_ext3_journal_header *jh;
+ grub_printf ("block: %d\n", block);
+
if (grub_fshelp_read_file (data->disk, &data->logfile, 0,
block << (log2bs + 9), sizeof (buf),
buf, grub_ext2_read_block,
@@ -476,6 +481,7 @@ grub_ext3_get_journal (struct grub_ext2_data *data)
struct grub_ext3_journal_block_tag *tag;
int ofs, flags;
+ grub_printf ("dblock: ");
ofs = sizeof (struct grub_ext3_journal_header);
do
@@ -491,15 +497,19 @@ grub_ext3_get_journal (struct grub_ext2_data *data)
ofs += 16;
log->mapping[num++] = grub_be_to_cpu32 (tag->block);
+ grub_printf ("%d ", grub_be_to_cpu32 (tag->block));
next_block();
}
while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
+ grub_printf ("\n");
+
continue;
}
case EXT3_JOURNAL_COMMIT_BLOCK:
{
+ grub_printf ("cblock: %d\n", seq);
seq++;
last_num = num - 1;
continue;
@@ -510,6 +520,8 @@ grub_ext3_get_journal (struct grub_ext2_data *data)
struct grub_ext3_journal_revoke_header *jrh;
grub_uint32_t i;
+ grub_printf ("rblock: %d ", jrh->count);
+
jrh = (struct grub_ext3_journal_revoke_header *) jh;
for (i = 0; i < grub_be_to_cpu32 (jrh->count); i++)
@@ -518,11 +530,12 @@ grub_ext3_get_journal (struct grub_ext2_data *data)
grub_uint32_t map;
map = grub_be_to_cpu32 (jrh->data[i]);
+ grub_printf ("%d ", map);
for (j = 0; j < num; j++)
if (log->mapping[j] == map)
log->mapping[j] = GRUB_FSHELP_JOURNAL_UNUSED_MAPPING;
}
-
+ grub_printf ("\n");
continue;
}
default:
@@ -538,6 +551,7 @@ quit:
{
int size;
+ grub_printf ("num: %d\n", last_num);
size = sizeof (struct grub_fshelp_journal) +
last_num * sizeof (grub_disk_addr_t);
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 6c29753..96db9a6 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1095,4 +1095,42 @@ struct grub_efi_block_io
};
typedef struct grub_efi_block_io grub_efi_block_io_t;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
+#define efi_call_0(func) func()
+#define efi_call_1(func, a) func(a)
+#define efi_call_2(func, a, b) func(a, b)
+#define efi_call_3(func, a, b, c) func(a, b, c)
+#define efi_call_4(func, a, b, c, d) func(a, b, c, d)
+#define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e)
+#define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f)
+
+#else
+
+#define efi_call_0(func) efi_wrap_0(func)
+#define efi_call_1(func, a) efi_wrap_1(func, (grub_uint64_t) a)
+#define efi_call_2(func, a, b) efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b)
+#define efi_call_3(func, a, b, c) efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c)
+#define efi_call_4(func, a, b, c, d) efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d)
+#define efi_call_5(func, a, b, c, d, e) efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d, (grub_uint64_t) e)
+#define efi_call_6(func, a, b, c, d, e, f) efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f)
+
+grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func);
+grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1);
+grub_uint64_t EXPORT_FUNC(efi_wrap_2) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2);
+grub_uint64_t EXPORT_FUNC(efi_wrap_3) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3);
+grub_uint64_t EXPORT_FUNC(efi_wrap_4) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4);
+grub_uint64_t EXPORT_FUNC(efi_wrap_5) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4, grub_uint64_t arg5);
+grub_uint64_t EXPORT_FUNC(efi_wrap_6) (void *func, grub_uint64_t arg1,
+ grub_uint64_t arg2, grub_uint64_t arg3,
+ grub_uint64_t arg4, grub_uint64_t arg5,
+ grub_uint64_t arg6);
+#endif
+
#endif /* ! GRUB_EFI_API_HEADER */
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
index b6f01a8..f2072c5 100644
--- a/include/grub/efi/pe32.h
+++ b/include/grub/efi/pe32.h
@@ -64,6 +64,7 @@ struct grub_pe32_coff_header
};
#define GRUB_PE32_MACHINE_I386 0x14c
+#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_RELOCS_STRIPPED 0x0001
#define GRUB_PE32_EXECUTABLE_IMAGE 0x0002
@@ -98,9 +99,13 @@ struct grub_pe32_optional_header
grub_uint32_t entry_addr;
grub_uint32_t code_base;
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
grub_uint32_t data_base;
-
grub_uint32_t image_base;
+#else
+ grub_uint64_t image_base;
+#endif
+
grub_uint32_t section_alignment;
grub_uint32_t file_alignment;
grub_uint16_t major_os_version;
@@ -115,10 +120,23 @@ struct grub_pe32_optional_header
grub_uint32_t checksum;
grub_uint16_t subsystem;
grub_uint16_t dll_characteristics;
+
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
grub_uint32_t stack_reserve_size;
grub_uint32_t stack_commit_size;
grub_uint32_t heap_reserve_size;
grub_uint32_t heap_commit_size;
+
+#else
+
+ grub_uint64_t stack_reserve_size;
+ grub_uint64_t stack_commit_size;
+ grub_uint64_t heap_reserve_size;
+ grub_uint64_t heap_commit_size;
+
+#endif
+
grub_uint32_t loader_flags;
grub_uint32_t num_data_directories;
@@ -141,8 +159,16 @@ struct grub_pe32_optional_header
struct grub_pe32_data_directory reserved_entry;
};
+#if GRUB_TARGET_SIZEOF_VOID_P == 4
+
#define GRUB_PE32_PE32_MAGIC 0x10b
+#else
+
+#define GRUB_PE32_PE32_MAGIC 0x20b
+
+#endif
+
#define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10
#define GRUB_PE32_NUM_DATA_DIRECTORIES 16
diff --git a/include/grub/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/linux.h b/include/grub/i386/linux.h
old mode 100644
new mode 100755
index 7a8e006..377efa7
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -44,14 +44,41 @@
#define GRUB_LINUX_SETUP_MOVE_SIZE 0x9100
#define GRUB_LINUX_CL_MAGIC 0xA33F
+#ifdef __x86_64__
+
+#define GRUB_LINUX_EFI_SIGNATURE \
+ ('4' << 24 | '6' << 16 | 'L' << 8 | 'E')
+
+#else
+
#define GRUB_LINUX_EFI_SIGNATURE \
- ('E' << 24 | 'F' << 16 | 'I' << 8 | 'L')
+ ('2' << 24 | '3' << 16 | 'L' << 8 | 'E')
+
+#endif
#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
{
@@ -173,17 +200,39 @@ struct linux_kernel_params
grub_uint32_t efi_mmap; /* 1d0 */
grub_uint32_t efi_mmap_size; /* 1d4 */
- grub_uint8_t padding8[0x1e0 - 0x1d8];
+ grub_uint32_t efi_system_table_hi; /* 1d8 */
+ grub_uint32_t efi_mmap_hi; /* 1dc */
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/chainloader.c b/loader/efi/chainloader.c
index 19285d9..a79e772 100644
--- a/loader/efi/chainloader.c
+++ b/loader/efi/chainloader.c
@@ -47,9 +47,9 @@ grub_chainloader_unload (void)
grub_efi_boot_services_t *b;
b = grub_efi_system_table->boot_services;
- b->unload_image (image_handle);
- b->free_pages (address, pages);
- grub_free (file_path);
+ efi_call_1 (b->unload_image, image_handle);
+ efi_call_2 (b->free_pages, address, pages);
+ efi_call_1 (grub_free, file_path);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
@@ -64,7 +64,7 @@ grub_chainloader_boot (void)
grub_efi_char16_t *exit_data;
b = grub_efi_system_table->boot_services;
- status = b->start_image (image_handle, &exit_data_size, &exit_data);
+ status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
if (status != GRUB_EFI_SUCCESS)
{
if (exit_data)
@@ -86,7 +86,7 @@ grub_chainloader_boot (void)
}
if (exit_data)
- b->free_pool (exit_data);
+ efi_call_1 (b->free_pool, exit_data);
grub_chainloader_unload ();
@@ -227,7 +227,7 @@ grub_chainloader_cmd (const char *filename)
size = grub_file_size (file);
pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
- status = b->allocate_pages (GRUB_EFI_ALLOCATE_ANY_PAGES,
+ status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
GRUB_EFI_LOADER_CODE,
pages, &address);
if (status != GRUB_EFI_SUCCESS)
@@ -244,7 +244,7 @@ grub_chainloader_cmd (const char *filename)
goto fail;
}
- status = b->load_image (0, grub_efi_image_handle, file_path,
+ status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
(void *) ((grub_addr_t) address), size,
&image_handle);
if (status != GRUB_EFI_SUCCESS)
@@ -284,7 +284,7 @@ grub_chainloader_cmd (const char *filename)
grub_free (file_path);
if (address)
- b->free_pages (address, pages);
+ efi_call_2 (b->free_pages, address, pages);
grub_dl_unref (my_mod);
}
diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c
index ee3fb99..b896fa3 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 = ((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 > real_mode_mem)
+ real_mode_mem = 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);
@@ -255,56 +252,182 @@ 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;
+#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. */
- /* 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 = (grub_uint32_t) mmap_buf;
+#ifdef __x86_64__
+ params->efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
+#endif
params->efi_mmap_size = mmap_size;
+ /* Hardware interrupts are not safe any longer. */
+ asm volatile ("cli" : : );
+
+#ifdef __x86_64__
+
+ jumpvector.kernel_entry = params->code32_start;
+ jumpvector.kernel_cs = 0x10;
+ jump_start = (void *) &jumpvector;
+
+ 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
+
/* 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" (params->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 ("lidt %0" : : "m" (idt_desc));
+ asm volatile ("lgdt %0" : : "m" (gdt_desc));
/* Enter Linux. */
asm volatile ("jmp *%%ecx" : : );
+#endif
+
/* Never reach here. */
return GRUB_ERR_NONE;
}
@@ -318,6 +441,116 @@ 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 void
+grub_linux_getio ()
+{
+}
+
+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 +562,9 @@ grub_rescue_cmd_linux (int argc, char *argv[])
grub_ssize_t len;
int i;
char *dest;
+ int video_type;
+
+ grub_linux_getio();
grub_dl_ref (my_mod);
@@ -384,19 +620,22 @@ 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;
- /* XXX Linux assumes that only elilo can boot Linux on EFI!!! */
- lh.type_of_loader = 0x50;
+ params = (struct linux_kernel_params *) real_mode_mem;
+ grub_memset (params, 0, sizeof (struct linux_kernel_params));
+ grub_memcpy (¶ms->jump, &lh.jump,
+ (char *) &lh.ramdisk_image - (char *) &lh.jump);
- 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;
+ /* XXX Linux assumes that only elilo can boot Linux on EFI!!! */
+ params->type_of_loader = 0x50;
- params = (struct linux_kernel_params *) &lh;
+ params->cl_magic = GRUB_LINUX_CL_MAGIC;
+ params->cl_offset = GRUB_LINUX_CL_END_OFFSET;
+ params->cmd_line_ptr = (grub_uint32_t) real_mode_mem + GRUB_LINUX_CL_OFFSET;
+ params->ramdisk_image = 0;
+ params->ramdisk_size = 0;
/* 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 +653,15 @@ grub_rescue_cmd_linux (int argc, char *argv[])
params->have_vga = 0;
params->font_size = 16; /* XXX */
+ params->efi_signature = GRUB_LINUX_EFI_SIGNATURE; /* XXX not used */
+ params->efi_system_table = (grub_uint32_t) grub_efi_system_table;
+#ifdef __x86_64__
+ params->efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
+#endif
+
+#if 0
+ /* The structure is zeroed already. */
+
/* No VBE on EFI. */
params->lfb_width = 0;
params->lfb_height = 0;
@@ -457,10 +705,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 +722,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 +770,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 +855,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 +866,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 +880,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 +888,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 +913,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/normal/x86_64/setjmp.S b/normal/x86_64/setjmp.S
new file mode 100644
index 0000000..4beb90c
--- /dev/null
+++ b/normal/x86_64/setjmp.S
@@ -0,0 +1,64 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2007 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/symbol.h>
+
+ .file "setjmp.S"
+
+ .text
+
+/*
+ * jmp_buf:
+ * rbx rbp r12 r13 r14 r15 rsp rip
+ * 0 8 16 24 32 40 48 56
+ */
+
+/*
+ * int grub_setjmp (grub_jmp_buf env)
+ */
+FUNCTION(grub_setjmp)
+ movq %rbx, 0(%rdi)
+ movq %rbp, 8(%rdi)
+ movq %r12, 16(%rdi)
+ movq %r13, 24(%rdi)
+ movq %r14, 32(%rdi)
+ movq %r15, 40(%rdi)
+ leaq 8(%rsp), %rax
+ movq %rax, 48(%rdi)
+ movq (%rsp), %rax
+ movq %rax, 56(%rdi)
+ movq $0, %rax
+ ret
+
+/*
+ * int grub_longjmp (grub_jmp_buf env, int val)
+ */
+FUNCTION(grub_longjmp)
+ movq %rsi, %rax
+
+ movq 8(%rdi), %rbp
+
+ movq 48(%rdi), %rsp
+ pushq 56(%rdi)
+ movq 0(%rdi), %rbx
+ movq 16(%rdi), %r12
+ movq 24(%rdi), %r13
+ movq 32(%rdi), %r14
+ movq 40(%rdi), %r15
+
+ ret
diff --git a/term/efi/console.c b/term/efi/console.c
index af198e5..3e88b28 100644
--- a/term/efi/console.c
+++ b/term/efi/console.c
@@ -52,10 +52,10 @@ grub_console_putchar (grub_uint32_t c)
str[1] = 0;
/* Should this test be cached? */
- if (c > 0x7f && o->test_string (o, str) != GRUB_EFI_SUCCESS)
+ if (c > 0x7f && efi_call_2 (o->test_string, o, str) != GRUB_EFI_SUCCESS)
return;
- o->output_string (o, str);
+ efi_call_2 (o->output_string, o, str);
}
static grub_ssize_t
@@ -76,7 +76,7 @@ grub_console_checkkey (void)
return 1;
i = grub_efi_system_table->con_in;
- status = i->read_key_stroke (i, &key);
+ status = efi_call_2 (i->read_key_stroke, i, &key);
#if 1
switch (status)
{
@@ -169,7 +169,7 @@ grub_console_getkey (void)
do
{
- status = b->wait_for_event (1, &(i->wait_for_key), &index);
+ status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index);
if (status != GRUB_EFI_SUCCESS)
return -1;
@@ -189,7 +189,7 @@ grub_console_getwh (void)
grub_efi_uintn_t columns, rows;
o = grub_efi_system_table->con_out;
- if (o->query_mode (o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS)
+ if (efi_call_4 (o->query_mode, o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS)
{
/* Why does this fail? */
columns = 80;
@@ -214,7 +214,7 @@ grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y)
grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out;
- o->set_cursor_position (o, x, y);
+ efi_call_3 (o->set_cursor_position, o, x, y);
}
static void
@@ -225,9 +225,9 @@ grub_console_cls (void)
o = grub_efi_system_table->con_out;
orig_attr = o->mode->attribute;
- o->set_attributes (o, GRUB_EFI_BACKGROUND_BLACK);
- o->clear_screen (o);
- o->set_attributes (o, orig_attr);
+ efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK);
+ efi_call_1 (o->clear_screen, o);
+ efi_call_2 (o->set_attributes, o, orig_attr);
}
static void
@@ -239,13 +239,13 @@ grub_console_setcolorstate (grub_term_color_state state)
switch (state) {
case GRUB_TERM_COLOR_STANDARD:
- o->set_attributes (o, grub_console_standard_color);
+ efi_call_2 (o->set_attributes, o, grub_console_standard_color);
break;
case GRUB_TERM_COLOR_NORMAL:
- o->set_attributes (o, grub_console_normal_color);
+ efi_call_2 (o->set_attributes, o, grub_console_normal_color);
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
- o->set_attributes (o, grub_console_highlight_color);
+ efi_call_2 (o->set_attributes, o, grub_console_highlight_color);
break;
default:
break;
@@ -272,7 +272,7 @@ grub_console_setcursor (int on)
grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out;
- o->enable_cursor (o, on);
+ efi_call_2 (o->enable_cursor, o, on);
}
static struct grub_term grub_console_term =
diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c
index 57c1fc8..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] 6+ messages in thread
* Re: Can we get video card information in EFI environment ?
2008-06-08 17:08 ` Bean
@ 2008-06-08 17:17 ` Vesa Jääskeläinen
2008-06-08 17:35 ` Bean
0 siblings, 1 reply; 6+ messages in thread
From: Vesa Jääskeläinen @ 2008-06-08 17:17 UTC (permalink / raw)
To: The development of GRUB 2
Bean wrote:
> BTW, you need to remove the udev start script from /etc/rcS.d,
> otherwise the screen would scramble again. I believe the cause is
> agppart. Fame buffer of EFI is a little strange, the line length is
> not equal to width * 4, for example, my macbook:
>
> width: 1280
> depth: 32
> line length: 8192
This is quite normal and can change from card to card. So thats the
reason you ask for line length from VBE/HW.
> So there is some invisible space after the screen boundary. But in
> bios emulation mode, the length is exactly width * 4. I think the
> driver should take this into account, or reconfigure the video
> hardware to use the new line length. (Anyone know how to do it ?)
GRUB 2 VBE driver already should work nicely with this (assuming VBE is
available). If you are planning to do EFI driver then you just use its
API to do blitting. Writing driver for EFI should be rather easy if I
remember correctly its interface. Can't write that driver myself unless
someone wants to provide me environment to do the coding.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Can we get video card information in EFI environment ?
2008-06-08 17:17 ` Vesa Jääskeläinen
@ 2008-06-08 17:35 ` Bean
2008-06-08 17:51 ` Vesa Jääskeläinen
0 siblings, 1 reply; 6+ messages in thread
From: Bean @ 2008-06-08 17:35 UTC (permalink / raw)
To: The development of GRUB 2
On Mon, Jun 9, 2008 at 1:17 AM, Vesa Jääskeläinen <chaac@nic.fi> wrote:
> Bean wrote:
>>
>> BTW, you need to remove the udev start script from /etc/rcS.d,
>> otherwise the screen would scramble again. I believe the cause is
>> agppart. Fame buffer of EFI is a little strange, the line length is
>> not equal to width * 4, for example, my macbook:
>>
>> width: 1280
>> depth: 32
>> line length: 8192
>
> This is quite normal and can change from card to card. So thats the reason
> you ask for line length from VBE/HW.
>
>> So there is some invisible space after the screen boundary. But in
>> bios emulation mode, the length is exactly width * 4. I think the
>> driver should take this into account, or reconfigure the video
>> hardware to use the new line length. (Anyone know how to do it ?)
>
> GRUB 2 VBE driver already should work nicely with this (assuming VBE is
> available). If you are planning to do EFI driver then you just use its API
> to do blitting. Writing driver for EFI should be rather easy if I remember
> correctly its interface. Can't write that driver myself unless someone wants
> to provide me environment to do the coding.
Hi,
I think the vbe driver need to call bios, is there a way to do it directly ?
EFI have uga draw protocol that can do bitblt, but they don't have a
method to query low level information like frame buffer address and
line length easily.
--
Bean
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Can we get video card information in EFI environment ?
2008-06-08 17:35 ` Bean
@ 2008-06-08 17:51 ` Vesa Jääskeläinen
2008-06-08 18:00 ` Bean
0 siblings, 1 reply; 6+ messages in thread
From: Vesa Jääskeläinen @ 2008-06-08 17:51 UTC (permalink / raw)
To: The development of GRUB 2
Bean wrote:
> I think the vbe driver need to call bios, is there a way to do it directly ?
Yes, it uses BIOS to determine frame buffer address and setup video mode.
> EFI have uga draw protocol that can do bitblt, but they don't have a
> method to query low level information like frame buffer address and
> line length easily.
In EFI you should use this protocol to do drawing to screen. And you do
not basicly need that low level information (in GRUB 2).
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Can we get video card information in EFI environment ?
2008-06-08 17:51 ` Vesa Jääskeläinen
@ 2008-06-08 18:00 ` Bean
0 siblings, 0 replies; 6+ messages in thread
From: Bean @ 2008-06-08 18:00 UTC (permalink / raw)
To: The development of GRUB 2
On Mon, Jun 9, 2008 at 1:51 AM, Vesa Jääskeläinen <chaac@nic.fi> wrote:
> Bean wrote:
>>
>> I think the vbe driver need to call bios, is there a way to do it directly
>> ?
>
> Yes, it uses BIOS to determine frame buffer address and setup video mode.
>
>> EFI have uga draw protocol that can do bitblt, but they don't have a
>> method to query low level information like frame buffer address and
>> line length easily.
>
> In EFI you should use this protocol to do drawing to screen. And you do not
> basicly need that low level information (in GRUB 2).
Yes, I don't need such information to draw in grub2. But I need to
pass them to the linux kernel, otherwise its frame buffer don't work
and you can only seen a scramble screen. Technically, this isn't
grub's fault, but I want to make it work better.
--
Bean
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-06-08 18:01 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-07 18:38 Can we get video card information in EFI environment ? Bean
2008-06-08 17:08 ` Bean
2008-06-08 17:17 ` Vesa Jääskeläinen
2008-06-08 17:35 ` Bean
2008-06-08 17:51 ` Vesa Jääskeläinen
2008-06-08 18:00 ` 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.