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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	* loader/efi/appleloader.c: Likewise.

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

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

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

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

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

	* util/i386/efi/grub-mkimage.c: Add support for x86_64.
This commit is contained in:
bean 2008-07-17 09:50:26 +00:00
parent ef29405511
commit 2001169405
39 changed files with 3960 additions and 309 deletions

162
ChangeLog
View file

@ -1,3 +1,165 @@
2008-07-17 Bean <bean123ch@gmail.com>
* conf/i386/efi.rmk (pkglib_MODULES): add pci.mod and lspci.mod.
(appleldr_mod_SOURCE): New variavle.
(appleldr_mod_CFLAGS): Likewise.
(appleldr_mod_LDFLAGS): Likewise.
(pci_mod_SOURCES): Likewise.
(pci_mod_CFLAGS): Likewise.
(pci_mod_LDFLAGS): Likewise.
(lspci_mod_SOURCES): Likewise.
(lspci_mod_CFLAGS): Likewise.
(lspci_mod_LDFLAGS): Likewise.
* conf/x86_64-efi.rmk: New file.
* disk/efi/efidisk.c (grub_efidisk_read): Wrap efi calls with efi_call_N
macro.
(grub_efidisk_write): Likewise.
* include/efi/api.h (efi_call_0): New macro.
(efi_call_1): Likewise.
(efi_call_2): Likewise.
(efi_call_3): Likewise.
(efi_call_4): Likewise.
(efi_call_5): Likewise.
(efi_call_6): Likewise.
* include/grub/efi/chainloader.h (grub_chainloader_cmd): Rename to
grub_rescue_cmd_chainloader.
* include/grub/efi/pe32.h (GRUB_PE32_MACHINE_X86_64): New macro.
(grub_pe32_optional_header): Change some fields based on i386 or
x86_64 platform.
(GRUB_PE32_PE32_MAGIC): Likewise.
* include/grub/efi/uga_draw.h: New file.
* include/grub/elf.h (STN_ABS): New constant.
(R_X86_64_NONE): Relocation constant for x86_64.
(R_X86_64_64): Likewise.
(R_X86_64_PC32): Likewise.
(R_X86_64_GOT32): Likewise.
(R_X86_64_PLT32): Likewise.
(R_X86_64_COPY): Likewise.
(R_X86_64_GLOB_DAT): Likewise.
(R_X86_64_JUMP_SLOT): Likewise.
(R_X86_64_RELATIVE): Likewise.
(R_X86_64_GOTPCREL): Likewise.
(R_X86_64_32): Likewise.
(R_X86_64_32S): Likewise.
(R_X86_64_16): Likewise.
(R_X86_64_PC16): Likewise.
(R_X86_64_8): Likewise.
(R_X86_64_PC8): Likewise.
* include/grub/i386/efi/pci.h: New file.
* include/grub/i386/linux.h (GRUB_LINUX_EFI_SIGNATURE):
Change it value based on platform.
(GRUB_LINUX_EFI_SIGNATURE_0204): New constant.
(GRUB_E820_RAM): Likewise.
(GRUB_E820_RESERVED): Likewise.
(GRUB_E820_ACPI): Likewise.
(GRUB_E820_NVS): Likewise.
(GRUB_E820_EXEC_CODE): Likewise.
(GRUB_E820_MAX_ENTRY): Likewise.
(grub_e820_mmap): New structure.
(linux_kernel_header): Change the efi field according to different
kernel version, also field from linux_kernel_header.
* include/grub/kernel.h (grub_module_info): Add padding for x86_64.
* include/grub/pci.h (GRUB_PCI_ADDR_SPACE_MASK): New constant.
(GRUB_PCI_ADDR_SPACE_MEMORY): Likewise.
(GRUB_PCI_ADDR_SPACE_IO): Likewise.
(GRUB_PCI_ADDR_MEM_TYPE_MASK): Likewise.
(GRUB_PCI_ADDR_MEM_TYPE_32): Likewise.
(GRUB_PCI_ADDR_MEM_TYPE_1M): Likewise.
(GRUB_PCI_ADDR_MEM_TYPE_64): Likewise.
(GRUB_PCI_ADDR_MEM_PREFETCH): Likewise.
(GRUB_PCI_ADDR_MEM_MASK): Likewise.
(GRUB_PCI_ADDR_IO_MASK): Likewise.
* include/grub/x86_64/efi/kernel.h: New file.
* include/grub/x86_64/efi/loader.h: Likewise.
* include/grub/x86_64/efi/machine.h: Likewise.
* include/grub/x86_64/efi/pci.h: Likewise.
* include/grub/x86_64/efi/time.h: Likewise.
* include/grub/x86_64/linux.h: Likewise.
* include/grub/x86_64/setjmp.h: Likewise.
* include/grub/x86_64/time.h: Likewise.
* include/grub/x86_64/types.h: Likewise.
* kern/dl.c (GRUB_CPU_SIZEOF_VOID_P): Changed to
GRUB_TARGET_SIZEOF_VOID_P.
* kern/efi/efi.c (grub_efi_locate_protocol): Wrap efi calls.
(grub_efi_locate_handle): Likewise.
(grub_efi_open_protocol): Likewise.
(grub_efi_set_text_mode): Likewise.
(grub_efi_stall): Likewise.
(grub_exit): Likewise.
(grub_reboot): Likewise.
(grub_halt): Likewise.
(grub_efi_exit_boot_services): Likewise.
(grub_get_rtc): Likewise.
* kern/efi/mm.c (MEMORY_MAP_SIZE): Change to 0x3000 for new models.
(GRUB_CPU_SIZEOF_VOID_P): Changed to GRUB_TARGET_SIZEOF_VOID_P.
(grub_efi_allocate_pages): Wrap efi calls.
(grub_efi_free_pages): Wrap efi calls.
(grub_efi_get_memory_map): Wrap efi calls.
* kern/x86_64/dl.c: New file.
* kern/x86_64/efi/callwrap.S: Likewise.
* kern/x86_64/efi/startup.S: Likewise.
* loader/efi/appleloader.c: Likewise.
* loader/efi/chainloader.c (cmdline): New variable.
(grub_chainloader_unload): Wrap efi calls.
(grub_chainloader_boot): Likewise.
(grub_rescue_cmd_chainloader): Wrap efi calls, handle
command line.
* loader/efi/chainloader_normal.c (chainloader_command):
Change grub_chainloader_cmd to grub_rescue_cmd_chainloader, pass
command line.
* loader/i386/efi/linux.c (allocate_pages): Change allocation
method.
(grub_e820_add_region): New function.
(grub_linux_boot): Construct e820 map from efi map, handle x86_64
booting.
(grub_find_video_card): New function.
(grub_linux_setup_video): New function.
(grub_rescue_cmd_linux): Probe for video information.
* normal/x86_64/setjmp.S: New file.
* term/efi/console.c (map_char): New function.
(grub_console_putchar): Map unicode char.
(grub_console_checkkey): Wrap efi calls.
(grub_console_getkey): Likewise.
(grub_console_getwh): Likewise.
(grub_console_gotoxy): Likewise.
(grub_console_cls): Likewise.
(grub_console_setcolorstate): Likewise.
(grub_console_setcursor): Likewise.
* util/i386/efi/grub-mkimage.c: Add support for x86_64.
2008-07-16 Pavel Roskin <proski@gnu.org> 2008-07-16 Pavel Roskin <proski@gnu.org>
* loader/i386/efi/linux.c (allocate_pages): Fix warnings in * loader/i386/efi/linux.c (allocate_pages): Fix warnings in

View file

@ -116,8 +116,8 @@ grub-install: util/i386/efi/grub-install.in $(util/i386/efi/grub-install.in_DEPE
# Modules. # Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \ pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.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. # For kernel.mod.
kernel_mod_EXPORTS = no kernel_mod_EXPORTS = no
@ -1072,6 +1072,62 @@ partmap-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_norm
chain_mod_CFLAGS = $(COMMON_CFLAGS) chain_mod_CFLAGS = $(COMMON_CFLAGS)
chain_mod_LDFLAGS = $(COMMON_LDFLAGS) chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For appleldr.mod.
appleldr_mod_SOURCES = loader/efi/appleloader.c
CLEANFILES += appleldr.mod mod-appleldr.o mod-appleldr.c pre-appleldr.o appleldr_mod-loader_efi_appleloader.o und-appleldr.lst
ifneq ($(appleldr_mod_EXPORTS),no)
CLEANFILES += def-appleldr.lst
DEFSYMFILES += def-appleldr.lst
endif
MOSTLYCLEANFILES += appleldr_mod-loader_efi_appleloader.d
UNDSYMFILES += und-appleldr.lst
appleldr.mod: pre-appleldr.o mod-appleldr.o
-rm -f $@
$(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ $^
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
pre-appleldr.o: $(appleldr_mod_DEPENDENCIES) appleldr_mod-loader_efi_appleloader.o
-rm -f $@
$(TARGET_CC) $(appleldr_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ appleldr_mod-loader_efi_appleloader.o
mod-appleldr.o: mod-appleldr.c
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -c -o $@ $<
mod-appleldr.c: moddep.lst genmodsrc.sh
sh $(srcdir)/genmodsrc.sh 'appleldr' $< > $@ || (rm -f $@; exit 1)
ifneq ($(appleldr_mod_EXPORTS),no)
def-appleldr.lst: pre-appleldr.o
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 appleldr/' > $@
endif
und-appleldr.lst: pre-appleldr.o
echo 'appleldr' > $@
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
appleldr_mod-loader_efi_appleloader.o: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES)
$(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -MD -c -o $@ $<
-include appleldr_mod-loader_efi_appleloader.d
CLEANFILES += cmd-appleldr_mod-loader_efi_appleloader.lst fs-appleldr_mod-loader_efi_appleloader.lst partmap-appleldr_mod-loader_efi_appleloader.lst
COMMANDFILES += cmd-appleldr_mod-loader_efi_appleloader.lst
FSFILES += fs-appleldr_mod-loader_efi_appleloader.lst
PARTMAPFILES += partmap-appleldr_mod-loader_efi_appleloader.lst
cmd-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) gencmdlist.sh
set -e; $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh appleldr > $@ || (rm -f $@; exit 1)
fs-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genfslist.sh
set -e; $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh appleldr > $@ || (rm -f $@; exit 1)
partmap-appleldr_mod-loader_efi_appleloader.lst: loader/efi/appleloader.c $(loader/efi/appleloader.c_DEPENDENCIES) genpartmaplist.sh
set -e; $(TARGET_CC) -Iloader/efi -I$(srcdir)/loader/efi $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(appleldr_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh appleldr > $@ || (rm -f $@; exit 1)
appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For _linux.mod. # For _linux.mod.
_linux_mod_SOURCES = loader/i386/efi/linux.c _linux_mod_SOURCES = loader/i386/efi/linux.c
CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_efi_linux.o und-_linux.lst CLEANFILES += _linux.mod mod-_linux.o mod-_linux.c pre-_linux.o _linux_mod-loader_i386_efi_linux.o und-_linux.lst
@ -1352,4 +1408,116 @@ partmap-reboot_mod-commands_reboot.lst: commands/reboot.c $(commands/reboot.c_DE
reboot_mod_CFLAGS = $(COMMON_CFLAGS) reboot_mod_CFLAGS = $(COMMON_CFLAGS)
reboot_mod_LDFLAGS = $(COMMON_LDFLAGS) 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) $(MODULE_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) $(MODULE_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 include $(srcdir)/conf/common.mk

View file

@ -74,8 +74,8 @@ sbin_SCRIPTS = grub-install
grub_install_SOURCES = util/i386/efi/grub-install.in grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules. # Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod \ pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.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. # For kernel.mod.
kernel_mod_EXPORTS = no kernel_mod_EXPORTS = no
@ -123,6 +123,11 @@ chain_mod_SOURCES = loader/efi/chainloader_normal.c
chain_mod_CFLAGS = $(COMMON_CFLAGS) chain_mod_CFLAGS = $(COMMON_CFLAGS)
chain_mod_LDFLAGS = $(COMMON_LDFLAGS) chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For appleldr.mod.
appleldr_mod_SOURCES = loader/efi/appleloader.c
appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For _linux.mod. # For _linux.mod.
_linux_mod_SOURCES = loader/i386/efi/linux.c _linux_mod_SOURCES = loader/i386/efi/linux.c
_linux_mod_CFLAGS = $(COMMON_CFLAGS) _linux_mod_CFLAGS = $(COMMON_CFLAGS)
@ -148,4 +153,14 @@ reboot_mod_SOURCES = commands/reboot.c
reboot_mod_CFLAGS = $(COMMON_CFLAGS) reboot_mod_CFLAGS = $(COMMON_CFLAGS)
reboot_mod_LDFLAGS = $(COMMON_LDFLAGS) 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 include $(srcdir)/conf/common.mk

1527
conf/x86_64-efi.mk Normal file

File diff suppressed because it is too large Load diff

169
conf/x86_64-efi.rmk Normal file
View file

@ -0,0 +1,169 @@
# -*- makefile -*-
COMMON_ASFLAGS = -nostdinc -fno-builtin -m64
COMMON_CFLAGS = -fno-builtin -m64
COMMON_LDFLAGS = -melf_x86_64 -nostdlib
# Used by various components. These rules need to precede them.
normal/execute.c_DEPENDENCIES = grub_script.tab.h
normal/command.c_DEPENDENCIES = grub_script.tab.h
normal/function.c_DEPENDENCIES = grub_script.tab.h
normal/lexer.c_DEPENDENCIES = grub_script.tab.h
# Utilities.
bin_UTILITIES = grub-mkimage
#sbin_UTILITIES = grub-mkdevicemap
#ifeq ($(enable_grub_emu), yes)
#sbin_UTILITIES += grub-emu
#endif
# For grub-mkimage.
grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \
util/resolve.c
# For grub-setup.
#grub_setup_SOURCES = util/i386/pc/grub-setup.c util/biosdisk.c \
# util/misc.c util/getroot.c kern/device.c kern/disk.c \
# kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c \
# fs/sfs.c kern/parser.c kern/partition.c partmap/pc.c \
# fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c \
# kern/fs.c kern/env.c fs/fshelp.c
# For grub-mkdevicemap.
grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c \
util/i386/get_disk_name.c
# For grub-emu.
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/help.c \
commands/terminal.c commands/ls.c commands/test.c \
commands/search.c commands/hexdump.c \
commands/halt.c commands/reboot.c \
commands/i386/cpuid.c \
disk/loopback.c \
\
fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \
fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \
fs/ntfs.c fs/ntfscomp.c fs/reiserfs.c fs/sfs.c \
fs/ufs.c fs/xfs.c fs/afs.c \
\
io/gzio.c \
kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \
kern/err.c \
normal/execute.c kern/file.c kern/fs.c normal/lexer.c \
kern/loader.c kern/main.c kern/misc.c kern/parser.c \
grub_script.tab.c kern/partition.c kern/rescue.c kern/term.c \
normal/arg.c normal/cmdline.c normal/command.c normal/function.c\
normal/completion.c normal/context.c normal/main.c \
normal/menu.c normal/menu_entry.c normal/misc.c normal/script.c \
normal/color.c \
partmap/amiga.c partmap/apple.c partmap/pc.c partmap/sun.c \
partmap/acorn.c partmap/gpt.c \
util/console.c util/hostfs.c util/grub-emu.c util/misc.c \
util/biosdisk.c util/getroot.c \
util/i386/pc/misc.c \
\
disk/raid.c disk/lvm.c \
grub_emu_init.c
grub_emu_LDFLAGS = $(LIBCURSES)
# Scripts.
sbin_SCRIPTS = grub-install
# For grub-install.
grub_install_SOURCES = util/i386/efi/grub-install.in
# Modules.
pkglib_MODULES = kernel.mod normal.mod _chain.mod chain.mod appleldr.mod \
cpuid.mod halt.mod reboot.mod _linux.mod linux.mod pci.mod lspci.mod
# For kernel.mod.
kernel_mod_EXPORTS = no
kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
term/efi/console.c disk/efi/efidisk.c
kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
efi/efi.h efi/time.h efi/disk.h machine/loader.h
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
MOSTLYCLEANFILES += symlist.c
MOSTLYCLEANFILES += symlist.c kernel_syms.lst
DEFSYMFILES += kernel_syms.lst
symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.sh
/bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
normal/completion.c normal/execute.c \
normal/function.c normal/lexer.c normal/main.c normal/menu.c \
normal/menu_entry.c normal/misc.c grub_script.tab.c \
normal/script.c normal/x86_64/setjmp.S normal/color.c
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For _chain.mod.
_chain_mod_SOURCES = loader/efi/chainloader.c
_chain_mod_CFLAGS = $(COMMON_CFLAGS)
_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For chain.mod.
chain_mod_SOURCES = loader/efi/chainloader_normal.c
chain_mod_CFLAGS = $(COMMON_CFLAGS)
chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For appleldr.mod.
appleldr_mod_SOURCES = loader/efi/appleloader.c
appleldr_mod_CFLAGS = $(COMMON_CFLAGS)
appleldr_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/efi/linux.c
_linux_mod_CFLAGS = $(COMMON_CFLAGS)
_linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For linux.mod.
linux_mod_SOURCES = loader/i386/efi/linux_normal.c
linux_mod_CFLAGS = $(COMMON_CFLAGS)
linux_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For cpuid.mod.
cpuid_mod_SOURCES = commands/i386/cpuid.c
cpuid_mod_CFLAGS = $(COMMON_CFLAGS)
cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For halt.mod.
halt_mod_SOURCES = commands/halt.c
halt_mod_CFLAGS = $(COMMON_CFLAGS)
halt_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For reboot.mod.
reboot_mod_SOURCES = commands/reboot.c
reboot_mod_CFLAGS = $(COMMON_CFLAGS)
reboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For pci.mod
pci_mod_SOURCES = bus/pci.c
pci_mod_CFLAGS = $(COMMON_CFLAGS)
pci_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For lspci.mod
lspci_mod_SOURCES = commands/lspci.c
lspci_mod_CFLAGS = $(COMMON_CFLAGS)
lspci_mod_LDFLAGS = $(COMMON_LDFLAGS)
include $(srcdir)/conf/common.mk

35
configure vendored
View file

@ -1930,13 +1930,6 @@ esac
case "$target_cpu" in case "$target_cpu" in
i[3456]86) target_cpu=i386 ;; 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 esac
# Specify the platform (such as firmware). # Specify the platform (such as firmware).
@ -1962,9 +1955,31 @@ else
platform="$with_platform" platform="$with_platform"
fi 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. # Sanity check.
case "$target_cpu"-"$platform" in case "$target_cpu"-"$platform" in
i386-efi) ;; i386-efi) ;;
x86_64-efi) ;;
i386-pc) ;; i386-pc) ;;
i386-linuxbios) ;; i386-linuxbios) ;;
i386-ieee1275) ;; i386-ieee1275) ;;
@ -6708,6 +6723,12 @@ if test "x$target_m32" = x1; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32" TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
fi 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. # Compiler features.
# #

View file

@ -49,11 +49,6 @@ esac
case "$target_cpu" in case "$target_cpu" in
i[[3456]]86) target_cpu=i386 ;; 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 esac
# Specify the platform (such as firmware). # Specify the platform (such as firmware).
@ -74,9 +69,27 @@ else
platform="$with_platform" platform="$with_platform"
fi 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. # Sanity check.
case "$target_cpu"-"$platform" in case "$target_cpu"-"$platform" in
i386-efi) ;; i386-efi) ;;
x86_64-efi) ;;
i386-pc) ;; i386-pc) ;;
i386-linuxbios) ;; i386-linuxbios) ;;
i386-ieee1275) ;; i386-ieee1275) ;;
@ -247,6 +260,12 @@ if test "x$target_m32" = x1; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32" TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
fi 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. # Compiler features.
# #

View file

@ -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", "reading 0x%x sectors at the sector 0x%llx from %s\n",
size, sector, disk->name); 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_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
buf); 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", "writing 0x%x sectors at the sector 0x%llx to %s\n",
size, sector, disk->name); 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_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
(void *) buf); (void *) buf);

View file

@ -1095,4 +1095,42 @@ struct grub_efi_block_io
}; };
typedef struct grub_efi_block_io grub_efi_block_io_t; 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 */ #endif /* ! GRUB_EFI_API_HEADER */

View file

@ -19,6 +19,6 @@
#ifndef GRUB_EFI_CHAINLOADER_HEADER #ifndef GRUB_EFI_CHAINLOADER_HEADER
#define GRUB_EFI_CHAINLOADER_HEADER 1 #define GRUB_EFI_CHAINLOADER_HEADER 1
void grub_chainloader_cmd (const char *filename); void grub_rescue_cmd_chainloader (int argc, char *argv[]);
#endif /* ! GRUB_EFI_CHAINLOADER_HEADER */ #endif /* ! GRUB_EFI_CHAINLOADER_HEADER */

View file

@ -64,6 +64,7 @@ struct grub_pe32_coff_header
}; };
#define GRUB_PE32_MACHINE_I386 0x14c #define GRUB_PE32_MACHINE_I386 0x14c
#define GRUB_PE32_MACHINE_X86_64 0x8664
#define GRUB_PE32_RELOCS_STRIPPED 0x0001 #define GRUB_PE32_RELOCS_STRIPPED 0x0001
#define GRUB_PE32_EXECUTABLE_IMAGE 0x0002 #define GRUB_PE32_EXECUTABLE_IMAGE 0x0002
@ -98,9 +99,13 @@ struct grub_pe32_optional_header
grub_uint32_t entry_addr; grub_uint32_t entry_addr;
grub_uint32_t code_base; grub_uint32_t code_base;
#if GRUB_TARGET_SIZEOF_VOID_P == 4
grub_uint32_t data_base; grub_uint32_t data_base;
grub_uint32_t image_base; grub_uint32_t image_base;
#else
grub_uint64_t image_base;
#endif
grub_uint32_t section_alignment; grub_uint32_t section_alignment;
grub_uint32_t file_alignment; grub_uint32_t file_alignment;
grub_uint16_t major_os_version; grub_uint16_t major_os_version;
@ -115,10 +120,23 @@ struct grub_pe32_optional_header
grub_uint32_t checksum; grub_uint32_t checksum;
grub_uint16_t subsystem; grub_uint16_t subsystem;
grub_uint16_t dll_characteristics; grub_uint16_t dll_characteristics;
#if GRUB_TARGET_SIZEOF_VOID_P == 4
grub_uint32_t stack_reserve_size; grub_uint32_t stack_reserve_size;
grub_uint32_t stack_commit_size; grub_uint32_t stack_commit_size;
grub_uint32_t heap_reserve_size; grub_uint32_t heap_reserve_size;
grub_uint32_t heap_commit_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 loader_flags;
grub_uint32_t num_data_directories; grub_uint32_t num_data_directories;
@ -141,8 +159,16 @@ struct grub_pe32_optional_header
struct grub_pe32_data_directory reserved_entry; struct grub_pe32_data_directory reserved_entry;
}; };
#if GRUB_TARGET_SIZEOF_VOID_P == 4
#define GRUB_PE32_PE32_MAGIC 0x10b #define GRUB_PE32_PE32_MAGIC 0x10b
#else
#define GRUB_PE32_PE32_MAGIC 0x20b
#endif
#define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10 #define GRUB_PE32_SUBSYSTEM_EFI_APPLICATION 10
#define GRUB_PE32_NUM_DATA_DIRECTORIES 16 #define GRUB_PE32_NUM_DATA_DIRECTORIES 16

View file

@ -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 */

View file

@ -454,6 +454,7 @@ typedef struct
the end of a chain, meaning no further symbols are found in that bucket. */ the end of a chain, meaning no further symbols are found in that bucket. */
#define STN_UNDEF 0 /* End of a chain. */ #define STN_UNDEF 0 /* End of a chain. */
#define STN_ABS 65521
/* How to extract and insert information held in the st_other field. */ /* How to extract and insert information held in the st_other field. */
@ -1108,8 +1109,27 @@ typedef struct
/* Keep this the last entry. */ /* Keep this the last entry. */
#define R_386_NUM 38 #define R_386_NUM 38
/* SUN SPARC specific definitions. */ /* 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). */ /* Legal values for ST_TYPE subfield of st_info (symbol type). */
#define STT_REGISTER 13 /* Global register reserved to app. */ #define STT_REGISTER 13 /* Global register reserved to app. */

View file

@ -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>

View file

@ -44,14 +44,44 @@
#define GRUB_LINUX_SETUP_MOVE_SIZE 0x9100 #define GRUB_LINUX_SETUP_MOVE_SIZE 0x9100
#define GRUB_LINUX_CL_MAGIC 0xA33F #define GRUB_LINUX_CL_MAGIC 0xA33F
#ifdef __x86_64__
#define GRUB_LINUX_EFI_SIGNATURE \ #define GRUB_LINUX_EFI_SIGNATURE \
('E' << 24 | 'F' << 16 | 'I' << 8 | 'L') ('4' << 24 | '6' << 16 | 'L' << 8 | 'E')
#else
#define GRUB_LINUX_EFI_SIGNATURE \
('2' << 24 | '3' << 16 | 'L' << 8 | 'E')
#endif
#define GRUB_LINUX_EFI_SIGNATURE_0204 \
('L' << 24 | 'I' << 16 | 'F' << 8 | 'E')
#define GRUB_LINUX_OFW_SIGNATURE \ #define GRUB_LINUX_OFW_SIGNATURE \
(' ' << 24 | 'W' << 16 | 'F' << 8 | 'O') (' ' << 24 | 'W' << 16 | 'F' << 8 | 'O')
#ifndef ASM_FILE #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. */ /* For the Linux/i386 boot protocol version 2.03. */
struct linux_kernel_header struct linux_kernel_header
{ {
@ -164,26 +194,74 @@ struct linux_kernel_params
grub_uint32_t ofw_cif_handler; /* b8 */ grub_uint32_t ofw_cif_handler; /* b8 */
grub_uint32_t ofw_idt; /* bc */ grub_uint32_t ofw_idt; /* bc */
grub_uint8_t padding7[0x1c0 - 0xc0]; grub_uint8_t padding7[0x1b8 - 0xc0];
grub_uint32_t efi_signature; /* 1c0 */ union
grub_uint32_t efi_system_table; /* 1c4 */ {
grub_uint32_t efi_mem_desc_size; /* 1c8 */ struct
grub_uint32_t efi_mem_desc_version; /* 1cc */ {
grub_uint32_t efi_mmap; /* 1d0 */ grub_uint32_t efi_system_table; /* 1b8 */
grub_uint32_t efi_mmap_size; /* 1d4 */ grub_uint32_t padding7_1; /* 1bc */
grub_uint32_t efi_signature; /* 1c0 */
grub_uint8_t padding8[0x1e0 - 0x1d8]; grub_uint32_t efi_mem_desc_size; /* 1c4 */
grub_uint32_t efi_mem_desc_version; /* 1c8 */
grub_uint32_t efi_mmap_size; /* 1cc */
grub_uint32_t efi_mmap; /* 1d0 */
} v0204;
struct
{
grub_uint32_t padding7_1; /* 1b8 */
grub_uint32_t padding7_2; /* 1bc */
grub_uint32_t efi_signature; /* 1c0 */
grub_uint32_t efi_system_table; /* 1c4 */
grub_uint32_t efi_mem_desc_size; /* 1c8 */
grub_uint32_t efi_mem_desc_version; /* 1cc */
grub_uint32_t efi_mmap; /* 1d0 */
grub_uint32_t efi_mmap_size; /* 1d4 */
grub_uint32_t efi_system_table_hi; /* 1d8 */
grub_uint32_t efi_mmap_hi; /* 1dc */
} v0206;
};
grub_uint32_t alt_mem; /* 1e0 */ grub_uint32_t alt_mem; /* 1e0 */
grub_uint8_t padding9[0x1e8 - 0x1e4]; grub_uint8_t padding8[0x1e8 - 0x1e4];
grub_uint32_t mmap_size; /* 1e8 */ grub_uint32_t mmap_size; /* 1e8 */
grub_uint8_t padding10[0x1ff - 0x1ec]; grub_uint8_t padding9[0x1f1 - 0x1ec];
grub_uint8_t setup_sects; /* The size of the setup in sectors */
grub_uint16_t root_flags; /* If the root is mounted readonly */
grub_uint16_t syssize; /* obsolete */
grub_uint16_t swap_dev; /* obsolete */
grub_uint16_t ram_size; /* obsolete */
grub_uint16_t vid_mode; /* Video mode control */
grub_uint16_t root_dev; /* Default root device number */
grub_uint8_t padding10; /* 1fe */
grub_uint8_t ps_mouse; /* 1ff */ grub_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)); } __attribute__ ((packed));
#endif /* ! ASM_FILE */ #endif /* ! ASM_FILE */

View file

@ -38,6 +38,9 @@ struct grub_module_info
{ {
/* Magic number so we know we have modules present. */ /* Magic number so we know we have modules present. */
grub_uint32_t magic; grub_uint32_t magic;
#if GRUB_TARGET_SIZEOF_VOID_P == 8
grub_uint32_t padding;
#endif
/* The offset of the modules. */ /* The offset of the modules. */
grub_target_off_t offset; grub_target_off_t offset;
/* The size of all modules plus this header. */ /* The size of all modules plus this header. */

View file

@ -22,6 +22,19 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/symbol.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 grub_uint32_t grub_pci_id_t;
typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func, typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
grub_pci_id_t pciid); grub_pci_id_t pciid);

View file

@ -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 */

View file

@ -0,0 +1,32 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_LOADER_MACHINE_HEADER
#define GRUB_LOADER_MACHINE_HEADER 1
#include <grub/types.h>
#include <grub/symbol.h>
/* It is necessary to export these functions, because normal mode commands
reuse rescue mode commands. */
void grub_rescue_cmd_linux (int argc, char *argv[]);
void grub_rescue_cmd_initrd (int argc, char *argv[]);
void EXPORT_FUNC(grub_linux_real_boot) (void);
#endif /* ! GRUB_LOADER_MACHINE_HEADER */

View file

@ -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 */

View file

@ -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>

View file

@ -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 */

View file

@ -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>

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -29,7 +29,7 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/cache.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_Word Elf_Word;
typedef Elf32_Addr Elf_Addr; 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_BIND(val) ELF32_ST_BIND (val)
# define ELF_ST_TYPE(val) ELF32_ST_TYPE (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_Word Elf_Word;
typedef Elf64_Addr Elf_Addr; typedef Elf64_Addr Elf_Addr;

View file

@ -43,9 +43,8 @@ grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
void *interface; void *interface;
grub_efi_status_t status; grub_efi_status_t status;
status = grub_efi_system_table->boot_services->locate_protocol (protocol, status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol,
registration, protocol, registration, &interface);
&interface);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
return 0; return 0;
@ -71,7 +70,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
return 0; return 0;
b = grub_efi_system_table->boot_services; 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); &buffer_size, buffer);
if (status == GRUB_EFI_BUFFER_TOO_SMALL) 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) if (! buffer)
return 0; 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); &buffer_size, buffer);
} }
@ -104,12 +103,12 @@ grub_efi_open_protocol (grub_efi_handle_t handle,
void *interface; void *interface;
b = grub_efi_system_table->boot_services; b = grub_efi_system_table->boot_services;
status = b->open_protocol (handle, status = efi_call_6 (b->open_protocol, handle,
protocol, protocol,
&interface, &interface,
grub_efi_image_handle, grub_efi_image_handle,
0, 0,
attributes); attributes);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
return 0; return 0;
@ -128,12 +127,12 @@ grub_efi_set_text_mode (int on)
already in text mode. */ already in text mode. */
return 1; 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; return 0;
new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS; new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
if (mode != new_mode) 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 0;
return 1; return 1;
@ -142,7 +141,7 @@ grub_efi_set_text_mode (int on)
void void
grub_efi_stall (grub_efi_uintn_t microseconds) 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 * grub_efi_loaded_image_t *
@ -157,25 +156,24 @@ void
grub_exit (void) grub_exit (void)
{ {
grub_efi_fini (); grub_efi_fini ();
grub_efi_system_table->boot_services->exit (grub_efi_image_handle, efi_call_4 (grub_efi_system_table->boot_services->exit,
GRUB_EFI_SUCCESS, grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0);
0, 0);
} }
void void
grub_reboot (void) grub_reboot (void)
{ {
grub_efi_fini (); grub_efi_fini ();
grub_efi_system_table->runtime_services-> efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
reset_system (GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
} }
void void
grub_halt (void) grub_halt (void)
{ {
grub_efi_fini (); grub_efi_fini ();
grub_efi_system_table->runtime_services-> efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
reset_system (GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL);
} }
int int
@ -185,7 +183,7 @@ grub_efi_exit_boot_services (grub_efi_uintn_t map_key)
grub_efi_status_t status; grub_efi_status_t status;
b = grub_efi_system_table->boot_services; 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; return status == GRUB_EFI_SUCCESS;
} }
@ -196,7 +194,7 @@ grub_get_rtc (void)
grub_efi_runtime_services_t *r; grub_efi_runtime_services_t *r;
r = grub_efi_system_table->runtime_services; 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? */ /* What is possible in this case? */
return 0; return 0;

View file

@ -30,7 +30,7 @@
/* The size of a memory map obtained from the firmware. This must be /* The size of a memory map obtained from the firmware. This must be
a multiplier of 4KB. */ a multiplier of 4KB. */
#define MEMORY_MAP_SIZE 0x1000 #define MEMORY_MAP_SIZE 0x3000
/* Maintain the list of allocated pages. */ /* Maintain the list of allocated pages. */
struct allocated_page struct allocated_page
@ -59,7 +59,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
grub_efi_status_t status; grub_efi_status_t status;
grub_efi_boot_services_t *b; 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. */ /* Limit the memory access to less than 4GB for 32-bit platforms. */
if (address > 0xffffffff) if (address > 0xffffffff)
return 0; return 0;
@ -79,7 +79,7 @@ grub_efi_allocate_pages (grub_efi_physical_address_t address,
#endif #endif
b = grub_efi_system_table->boot_services; 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) if (status != GRUB_EFI_SUCCESS)
return 0; 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, /* Uggh, the address 0 was allocated... This is too annoying,
so reallocate another one. */ so reallocate another one. */
address = 0xffffffff; 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); grub_efi_free_pages (0, pages);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
return 0; return 0;
@ -135,7 +135,7 @@ grub_efi_free_pages (grub_efi_physical_address_t address,
} }
b = grub_efi_system_table->boot_services; 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, /* 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; descriptor_version = &version;
b = grub_efi_system_table->boot_services; 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); descriptor_size, descriptor_version);
if (status == GRUB_EFI_SUCCESS) if (status == GRUB_EFI_SUCCESS)
return 1; return 1;
@ -218,7 +218,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{ {
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY 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 && desc->physical_start <= 0xffffffff
#endif #endif
&& desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 && 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; 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) if (BYTES_TO_PAGES (filtered_desc->physical_start)
+ filtered_desc->num_pages + filtered_desc->num_pages
> BYTES_TO_PAGES (0x100000000LL)) > BYTES_TO_PAGES (0x100000000LL))

121
kern/x86_64/dl.c Normal file
View file

@ -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;
}

View file

@ -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

87
kern/x86_64/efi/startup.S Normal file
View file

@ -0,0 +1,87 @@
/* startup.S - bootstrap GRUB itself */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/boot.h>
.file "startup.S"
.text
.globl start, _start
.code64
start:
_start:
jmp codestart
/*
* Compatibility version number
*
* These MUST be at byte offset 6 and 7 of the executable
* DO NOT MOVE !!!
*/
. = EXT_C(start) + 0x6
.byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
/*
* This is a special data area 8 bytes from the beginning.
*/
. = EXT_C(start) + 0x8
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
/*
* Leave some breathing room for the prefix.
*/
. = EXT_C(start) + 0x50
codestart:
movq %rcx, EXT_C(grub_efi_image_handle)
movq %rdx, EXT_C(grub_efi_system_table)
call EXT_C(grub_main)
ret
.code32
FUNCTION(grub_linux_real_boot)
/* Turn off PG bit in CR0 and set CR3 to zero. */
movl %cr0, %eax
andl $0x7FFFFFFF, %eax
movl %eax, %cr0
/* Setup EFER (Extended Feature Enable Register). */
movl $0xc0000080, %ecx
rdmsr
/* Disable Long Mode. */
andl $0xFFFFFEFF, %eax
/* Make changes effective. */
wrmsr
/* Disable PAE. */
xorl %eax, %eax
movl %eax, %cr4
jmp *%ebx

208
loader/efi/appleloader.c Normal file
View file

@ -0,0 +1,208 @@
/* appleloader.c - apple legacy boot loader. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/loader.h>
#include <grub/err.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/normal.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
static grub_dl_t my_mod;
static grub_efi_handle_t image_handle;
static grub_efi_char16_t *cmdline;
static grub_err_t
grub_appleloader_unload (void)
{
grub_efi_boot_services_t *b;
b = grub_efi_system_table->boot_services;
efi_call_1 (b->unload_image, image_handle);
grub_free (cmdline);
cmdline = 0;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_appleloader_boot (void)
{
grub_efi_boot_services_t *b;
b = grub_efi_system_table->boot_services;
efi_call_3 (b->start_image, image_handle, 0, 0);
grub_appleloader_unload ();
return grub_errno;
}
/* early 2006 Core Duo / Core Solo models */
static grub_uint8_t devpath_1[] =
{
0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
};
/* mid-2006 Mac Pro (and probably other Core 2 models) */
static grub_uint8_t devpath_2[] =
{
0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xF7, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
};
/* mid-2007 MBP ("Santa Rosa" based models) */
static grub_uint8_t devpath_3[] =
{
0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
};
/* early-2008 MBA */
static grub_uint8_t devpath_4[] =
{
0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
};
struct devdata
{
char *model;
grub_efi_device_path_t *devpath;
};
struct devdata devs[] =
{
{"Core Duo/Solo", (grub_efi_device_path_t *) devpath_1},
{"Mac Pro", (grub_efi_device_path_t *) devpath_2},
{"MBP", (grub_efi_device_path_t *) devpath_3},
{"MBA", (grub_efi_device_path_t *) devpath_4},
{NULL, NULL},
};
static grub_err_t
grub_cmd_appleloader (struct grub_arg_list *state __attribute__ ((unused)),
int argc, char *argv[])
{
grub_efi_boot_services_t *b;
grub_efi_loaded_image_t *loaded_image;
struct devdata *pdev;
grub_dl_ref (my_mod);
/* Initialize some global variables. */
image_handle = 0;
b = grub_efi_system_table->boot_services;
for (pdev = devs ; pdev->devpath ; pdev++)
if (efi_call_6 (b->load_image, 0, grub_efi_image_handle, pdev->devpath,
NULL, 0, &image_handle) == GRUB_EFI_SUCCESS)
break;
if (! pdev->devpath)
{
grub_error (GRUB_ERR_BAD_OS, "can't find model");
goto fail;
}
grub_printf ("Model : %s\n", pdev->model);
loaded_image = grub_efi_get_loaded_image (image_handle);
if (! loaded_image)
{
grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
goto fail;
}
if (argc > 0)
{
int i, len;
grub_efi_char16_t *p16;
for (i = 0, len = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
len *= sizeof (grub_efi_char16_t);
cmdline = p16 = grub_malloc (len);
if (! cmdline)
goto fail;
for (i = 0; i < argc; i++)
{
char *p8;
p8 = argv[i];
while (*p8)
*(p16++) = *(p8++);
*(p16++) = ' ';
}
*(--p16) = 0;
loaded_image->load_options = cmdline;
loaded_image->load_options_size = len;
}
grub_loader_set (grub_appleloader_boot, grub_appleloader_unload, 0);
return 0;
fail:
grub_dl_unref (my_mod);
return grub_errno;
}
GRUB_MOD_INIT(appleloader)
{
grub_register_command ("appleloader", grub_cmd_appleloader,
GRUB_COMMAND_FLAG_BOTH,
"appleloader [OPTS]",
"Boot legacy system.", 0);
my_mod = mod;
}
GRUB_MOD_FINI(appleloader)
{
grub_unregister_command ("appleloader");
}

View file

@ -40,6 +40,7 @@ static grub_efi_physical_address_t address;
static grub_efi_uintn_t pages; static grub_efi_uintn_t pages;
static grub_efi_device_path_t *file_path; static grub_efi_device_path_t *file_path;
static grub_efi_handle_t image_handle; static grub_efi_handle_t image_handle;
static grub_efi_char16_t *cmdline;
static grub_err_t static grub_err_t
grub_chainloader_unload (void) grub_chainloader_unload (void)
@ -47,9 +48,12 @@ grub_chainloader_unload (void)
grub_efi_boot_services_t *b; grub_efi_boot_services_t *b;
b = grub_efi_system_table->boot_services; b = grub_efi_system_table->boot_services;
b->unload_image (image_handle); efi_call_1 (b->unload_image, image_handle);
b->free_pages (address, pages); efi_call_2 (b->free_pages, address, pages);
grub_free (file_path); grub_free (file_path);
grub_free (cmdline);
cmdline = 0;
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -64,7 +68,7 @@ grub_chainloader_boot (void)
grub_efi_char16_t *exit_data; grub_efi_char16_t *exit_data;
b = grub_efi_system_table->boot_services; 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 (status != GRUB_EFI_SUCCESS)
{ {
if (exit_data) if (exit_data)
@ -86,7 +90,7 @@ grub_chainloader_boot (void)
} }
if (exit_data) if (exit_data)
b->free_pool (exit_data); efi_call_1 (b->free_pool, exit_data);
grub_chainloader_unload (); grub_chainloader_unload ();
@ -175,7 +179,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
} }
void void
grub_chainloader_cmd (const char *filename) grub_rescue_cmd_chainloader (int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
grub_ssize_t size; grub_ssize_t size;
@ -185,6 +189,14 @@ grub_chainloader_cmd (const char *filename)
grub_device_t dev = 0; grub_device_t dev = 0;
grub_efi_device_path_t *dp = 0; grub_efi_device_path_t *dp = 0;
grub_efi_loaded_image_t *loaded_image; grub_efi_loaded_image_t *loaded_image;
char *filename;
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
return;
}
filename = argv[0];
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -227,7 +239,7 @@ grub_chainloader_cmd (const char *filename)
size = grub_file_size (file); size = grub_file_size (file);
pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); 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, GRUB_EFI_LOADER_CODE,
pages, &address); pages, &address);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
@ -244,7 +256,7 @@ grub_chainloader_cmd (const char *filename)
goto fail; 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, (void *) ((grub_addr_t) address), size,
&image_handle); &image_handle);
if (status != GRUB_EFI_SUCCESS) if (status != GRUB_EFI_SUCCESS)
@ -269,6 +281,36 @@ grub_chainloader_cmd (const char *filename)
loaded_image->device_handle = dev_handle; loaded_image->device_handle = dev_handle;
grub_file_close (file); grub_file_close (file);
if (argc > 1)
{
int i, len;
grub_efi_char16_t *p16;
for (i = 1, len = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
len *= sizeof (grub_efi_char16_t);
cmdline = p16 = grub_malloc (len);
if (! cmdline)
goto fail;
for (i = 1; i < argc; i++)
{
char *p8;
p8 = argv[i];
while (*p8)
*(p16++) = *(p8++);
*(p16++) = ' ';
}
*(--p16) = 0;
loaded_image->load_options = cmdline;
loaded_image->load_options_size = len;
}
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
return; return;
@ -284,20 +326,11 @@ grub_chainloader_cmd (const char *filename)
grub_free (file_path); grub_free (file_path);
if (address) if (address)
b->free_pages (address, pages); efi_call_2 (b->free_pages, address, pages);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
} }
static void
grub_rescue_cmd_chainloader (int argc, char *argv[])
{
if (argc == 0)
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
else
grub_chainloader_cmd (argv[0]);
}
static const char loader_name[] = "chainloader"; static const char loader_name[] = "chainloader";
GRUB_MOD_INIT(chainloader) GRUB_MOD_INIT(chainloader)

View file

@ -29,7 +29,7 @@ chainloader_command (struct grub_arg_list *state __attribute__ ((unused)),
if (argc == 0) if (argc == 0)
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
else else
grub_chainloader_cmd (args[0]); grub_rescue_cmd_chainloader (argc, args);
return grub_errno; return grub_errno;
} }

View file

@ -30,6 +30,11 @@
#include <grub/cpu/linux.h> #include <grub/cpu/linux.h>
#include <grub/efi/api.h> #include <grub/efi/api.h>
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
#include <grub/efi/uga_draw.h>
#include <grub/pci.h>
#define GRUB_EFI_CL_OFFSET 0x1000
#define GRUB_EFI_CL_END_OFFSET 0x2000
#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ #define NEXT_MEMORY_DESCRIPTOR(desc, size) \
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
@ -60,28 +65,24 @@ static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
struct gdt_descriptor struct gdt_descriptor
{ {
grub_uint16_t dummy;
grub_uint16_t limit; grub_uint16_t limit;
grub_uint32_t base; void *base;
} __attribute__ ((aligned(4), packed)); } __attribute__ ((packed));
static struct gdt_descriptor gdt_desc = static struct gdt_descriptor gdt_desc =
{ {
0,
sizeof (gdt) - 1, sizeof (gdt) - 1,
(grub_addr_t) gdt gdt
}; };
struct idt_descriptor struct idt_descriptor
{ {
grub_uint16_t dummy;
grub_uint16_t limit; grub_uint16_t limit;
grub_uint32_t base; void *base;
} __attribute__ ((aligned(4))); } __attribute__ ((packed));
static struct idt_descriptor idt_desc = static struct idt_descriptor idt_desc =
{ {
0,
0, 0,
0 0
}; };
@ -156,20 +157,21 @@ free_pages (void)
/* Allocate pages for the real mode code and the protected mode code /* Allocate pages for the real mode code and the protected mode code
for linux as well as a memory map buffer. */ for linux as well as a memory map buffer. */
static int 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_uintn_t desc_size;
grub_efi_memory_descriptor_t *mmap, *mmap_end; grub_efi_memory_descriptor_t *mmap, *mmap_end;
grub_efi_uintn_t mmap_size, tmp_mmap_size; grub_efi_uintn_t mmap_size, tmp_mmap_size;
grub_efi_memory_descriptor_t *desc; grub_efi_memory_descriptor_t *desc;
grub_size_t real_size;
/* Make sure that each size is aligned to a page boundary. */ /* Make sure that each size is aligned to a page boundary. */
real_size = page_align (real_size + GRUB_DISK_SECTOR_SIZE); real_size = GRUB_EFI_CL_END_OFFSET;
prot_size = page_align (prot_size); prot_size = page_align (prot_size);
mmap_size = find_mmap_size (); mmap_size = find_mmap_size ();
grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %lx\n", 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 /* Calculate the number of pages; Combine the real mode code with
the memory map buffer for simplicity. */ the memory map buffer for simplicity. */
@ -217,8 +219,8 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
if (addr < 0x10000) if (addr < 0x10000)
continue; continue;
grub_dprintf ("linux", "trying to allocate %lu pages at %x\n", grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
real_mode_pages, (unsigned) addr); (unsigned) real_mode_pages, (unsigned long) addr);
real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages); real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
if (! real_mode_mem) if (! real_mode_mem)
grub_fatal ("cannot allocate pages"); grub_fatal ("cannot allocate pages");
@ -246,6 +248,11 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
goto fail; goto fail;
} }
grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
"prot_mode_mem = %lx, prot_mode_pages = %x\n",
(unsigned long) real_mode_mem, (unsigned) real_mode_pages,
(unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
grub_free (mmap); grub_free (mmap);
return 1; return 1;
@ -255,56 +262,189 @@ allocate_pages (grub_size_t real_size, grub_size_t prot_size)
return 0; return 0;
} }
static void
grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
grub_uint64_t start, grub_uint64_t size,
grub_uint32_t type)
{
int n = *e820_num;
if (n >= GRUB_E820_MAX_ENTRY)
grub_fatal ("Too many e820 memory map entries");
if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
(e820_map[n - 1].type == type))
e820_map[n - 1].size += size;
else
{
e820_map[n].addr = start;
e820_map[n].size = size;
e820_map[n].type = type;
(*e820_num)++;
}
}
#ifdef __x86_64__
struct
{
grub_uint32_t kernel_entry;
grub_uint32_t kernel_cs;
} jumpvector;
#endif
static grub_err_t static grub_err_t
grub_linux_boot (void) grub_linux_boot (void)
{ {
struct linux_kernel_header *lh;
struct linux_kernel_params *params; struct linux_kernel_params *params;
grub_efi_uintn_t mmap_size; grub_efi_uintn_t mmap_size;
grub_efi_uintn_t map_key; grub_efi_uintn_t map_key;
grub_efi_uintn_t desc_size; grub_efi_uintn_t desc_size;
grub_efi_uint32_t desc_version; grub_efi_uint32_t desc_version;
grub_efi_memory_descriptor_t *desc;
int e820_num;
lh = real_mode_mem;
params = real_mode_mem; params = real_mode_mem;
grub_dprintf ("linux", "code32_start = %x, idt_desc = %x, gdt_desc = %x\n", grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
(unsigned) lh->code32_start, (grub_addr_t) &(idt_desc.limit), (unsigned) params->code32_start,
(grub_addr_t) &(gdt_desc.limit)); (unsigned long) &(idt_desc.limit),
grub_dprintf ("linux", "idt = %x:%x, gdt = %x:%x\n", (unsigned long) &(gdt_desc.limit));
(unsigned) idt_desc.limit, (unsigned) idt_desc.base, grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
(unsigned) gdt_desc.limit, (unsigned) gdt_desc.base); (unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
(unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
mmap_size = find_mmap_size (); mmap_size = find_mmap_size ();
if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
&desc_size, &desc_version) <= 0) &desc_size, &desc_version) <= 0)
grub_fatal ("cannot get memory map"); 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)) 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. */ /* Note that no boot services are available from here. */
/* Pass EFI parameters. */
if (grub_le_to_cpu16 (params->version) >= 0x0206)
{
params->v0206.efi_mem_desc_size = desc_size;
params->v0206.efi_mem_desc_version = desc_version;
params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
params->v0206.efi_mmap_size = mmap_size;
#ifdef __x86_64__
params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
#endif
}
else if (grub_le_to_cpu16 (params->version) >= 0x0204)
{
params->v0204.efi_mem_desc_size = desc_size;
params->v0204.efi_mem_desc_version = desc_version;
params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
params->v0204.efi_mmap_size = mmap_size;
}
/* Hardware interrupts are not safe any longer. */ /* Hardware interrupts are not safe any longer. */
asm volatile ("cli" : : ); asm volatile ("cli" : : );
/* Pass EFI parameters. */ /* Load the IDT and the GDT for the bootstrap. */
params->efi_mem_desc_size = desc_size; asm volatile ("lidt %0" : : "m" (idt_desc));
params->efi_mem_desc_version = desc_version; asm volatile ("lgdt %0" : : "m" (gdt_desc));
params->efi_mmap = (grub_addr_t) mmap_buf;
params->efi_mmap_size = mmap_size; #ifdef __x86_64__
jumpvector.kernel_entry = (grub_uint64_t) grub_linux_real_boot;
jumpvector.kernel_cs = 0x10;
asm volatile ( "mov %0, %%rbx" : : "m" (params->code32_start));
asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem));
asm volatile ( "ljmp *%0" : : "m" (jumpvector));
#else
/* Pass parameters. */ /* Pass parameters. */
asm volatile ("movl %0, %%ecx" : : "m" (params->code32_start));
asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem)); asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
asm volatile ("movl %0, %%ecx" : : "m" (lh->code32_start));
asm volatile ("xorl %%ebx, %%ebx" : : );
/* Load the IDT and the GDT for the bootstrap. */ asm volatile ("xorl %%ebx, %%ebx" : : );
asm volatile ("lidt %0" : : "m" (idt_desc.limit));
asm volatile ("lgdt %0" : : "m" (gdt_desc.limit));
/* Enter Linux. */ /* Enter Linux. */
asm volatile ("jmp *%%ecx" : : ); asm volatile ("jmp *%%ecx" : : );
#endif
/* Never reach here. */ /* Never reach here. */
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -318,6 +458,111 @@ grub_linux_unload (void)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_uint64_t video_base;
static int
grub_find_video_card (int bus, int dev, int func,
grub_pci_id_t pciid __attribute__ ((unused)))
{
grub_pci_address_t addr;
addr = grub_pci_make_address (bus, dev, func, 2);
if (grub_pci_read (addr) >> 24 == 0x3)
{
int i;
addr = grub_pci_make_address (bus, dev, func, 4);
for (i = 0; i < 6; i++, addr += 4)
{
grub_uint32_t base, type;
base = grub_pci_read (addr);
if ((base == 0) || (base == 0xffffffff) ||
(base & GRUB_PCI_ADDR_SPACE_IO))
continue;
type = base & GRUB_PCI_ADDR_MEM_TYPE_MASK;
if (! (addr & GRUB_PCI_ADDR_MEM_PREFETCH))
{
if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
{
i++;
addr +=4 ;
}
continue;
}
base &= GRUB_PCI_ADDR_MEM_MASK;
if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
{
if (i == 5)
break;
video_base = grub_pci_read (addr + 4);
video_base <<= 32;
}
video_base |= base;
return 1;
}
}
return 0;
}
static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
static int
grub_linux_setup_video (struct linux_kernel_params *params)
{
grub_efi_uga_draw_protocol_t *c;
grub_uint32_t width, height, depth, rate;
c = grub_efi_locate_protocol (&uga_draw_guid, 0);
if (! c)
return 1;
if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
return 1;
grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate);
video_base = 0;
grub_pci_iterate (grub_find_video_card);
if (! video_base)
{
grub_printf ("Can\'t find frame buffer address\n");
return 1;
}
grub_printf ("Video frame buffer: %llx\n", (unsigned long long) video_base);
params->lfb_width = width;
params->lfb_height = height;
params->lfb_depth = depth;
/* FIXME: shouldn't use fixed value. */
params->lfb_line_len = 8192;
params->lfb_base = video_base;
params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16;
params->red_mask_size = 8;
params->red_field_pos = 16;
params->green_mask_size = 8;
params->green_field_pos = 8;
params->blue_mask_size = 8;
params->blue_field_pos = 0;
params->reserved_mask_size = 8;
params->reserved_field_pos = 24;
return 0;
}
void void
grub_rescue_cmd_linux (int argc, char *argv[]) grub_rescue_cmd_linux (int argc, char *argv[])
{ {
@ -329,6 +574,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
grub_ssize_t len; grub_ssize_t len;
int i; int i;
char *dest; char *dest;
int video_type;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -384,19 +630,33 @@ grub_rescue_cmd_linux (int argc, char *argv[])
real_size = setup_sects << GRUB_DISK_SECTOR_BITS; real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; 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; goto fail;
params = (struct linux_kernel_params *) real_mode_mem;
grub_memset (params, 0, GRUB_EFI_CL_END_OFFSET);
grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
params->ps_mouse = params->padding10 = 0;
len = 0x400 - sizeof (lh);
if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
{
grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
goto fail;
}
/* XXX Linux assumes that only elilo can boot Linux on EFI!!! */ /* XXX Linux assumes that only elilo can boot Linux on EFI!!! */
lh.type_of_loader = 0x50; params->type_of_loader = 0x50;
lh.cl_magic = GRUB_LINUX_CL_MAGIC; params->cl_magic = GRUB_LINUX_CL_MAGIC;
lh.cl_offset = GRUB_LINUX_CL_END_OFFSET; params->cl_offset = 0x1000;
lh.cmd_line_ptr = (char *) real_mode_mem + GRUB_LINUX_CL_OFFSET; params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000;
lh.ramdisk_image = 0; params->ramdisk_image = 0;
lh.ramdisk_size = 0; params->ramdisk_size = 0;
params = (struct linux_kernel_params *) &lh; params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
/* These are not needed to be precise, because Linux uses these values /* These are not needed to be precise, because Linux uses these values
only to raise an error when the decompression code cannot find good only to raise an error when the decompression code cannot find good
@ -414,6 +674,23 @@ grub_rescue_cmd_linux (int argc, char *argv[])
params->have_vga = 0; params->have_vga = 0;
params->font_size = 16; /* XXX */ params->font_size = 16; /* XXX */
if (grub_le_to_cpu16 (params->version) >= 0x0206)
{
params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
#ifdef __x86_64__
params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
#endif
}
else if (grub_le_to_cpu16 (params->version) >= 0x0204)
{
params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
}
#if 0
/* The structure is zeroed already. */
/* No VBE on EFI. */ /* No VBE on EFI. */
params->lfb_width = 0; params->lfb_width = 0;
params->lfb_height = 0; params->lfb_height = 0;
@ -457,10 +734,6 @@ grub_rescue_cmd_linux (int argc, char *argv[])
/* No MCA on EFI. */ /* No MCA on EFI. */
params->rom_config_len = 0; 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. */ /* No need to fake the BIOS's memory map. */
params->mmap_size = 0; params->mmap_size = 0;
@ -478,22 +751,19 @@ grub_rescue_cmd_linux (int argc, char *argv[])
grub_memset (params->padding8, 0, sizeof (params->padding8)); grub_memset (params->padding8, 0, sizeof (params->padding8));
grub_memset (params->padding9, 0, sizeof (params->padding9)); grub_memset (params->padding9, 0, sizeof (params->padding9));
/* Put the real mode code at the real location. */ #endif
grub_memmove (real_mode_mem, &lh, sizeof (lh));
len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); /* The other EFI parameters are filled when booting. */
if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
{ grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
goto fail;
}
/* XXX there is no way to know if the kernel really supports EFI. */ /* XXX there is no way to know if the kernel really supports EFI. */
grub_printf (" [Linux-EFI, setup=0x%x, size=0x%x]\n", 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. */ /* Detect explicitly specified memory size, if any. */
linux_mem_size = 0; linux_mem_size = 0;
video_type = 0;
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
if (grub_memcmp (argv[i], "mem=", 4) == 0) if (grub_memcmp (argv[i], "mem=", 4) == 0)
{ {
@ -529,9 +799,22 @@ grub_rescue_cmd_linux (int argc, char *argv[])
linux_mem_size <<= shift; 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. */ /* Specify the boot file. */
dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET, dest = grub_stpcpy ((char *) real_mode_mem + GRUB_EFI_CL_OFFSET,
"BOOT_IMAGE="); "BOOT_IMAGE=");
dest = grub_stpcpy (dest, argv[0]); dest = grub_stpcpy (dest, argv[0]);
@ -539,7 +822,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
for (i = 1; for (i = 1;
i < argc i < argc
&& dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
+ GRUB_LINUX_CL_END_OFFSET); + GRUB_EFI_CL_END_OFFSET);
i++) i++)
{ {
*dest++ = ' '; *dest++ = ' ';
@ -601,7 +884,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
lh = (struct linux_kernel_header *) real_mode_mem; 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) if (linux_mem_size != 0 && linux_mem_size < addr_max)
addr_max = linux_mem_size; addr_max = linux_mem_size;
@ -612,7 +895,8 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
addr_max -= 0x10000; addr_max -= 0x10000;
/* Usually, the compression ratio is about 50%. */ /* 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. */ /* Find the highest address to put the initrd. */
mmap_size = find_mmap_size (); mmap_size = find_mmap_size ();
@ -625,8 +909,6 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
{ {
if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
&& desc->physical_start >= addr_min
&& desc->physical_start + size < addr_max
&& desc->num_pages >= initrd_pages) && desc->num_pages >= initrd_pages)
{ {
grub_efi_physical_address_t physical_end; grub_efi_physical_address_t physical_end;
@ -635,6 +917,9 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
if (physical_end > addr_max) if (physical_end > addr_max)
physical_end = addr_max; physical_end = addr_max;
if (physical_end < addr_min)
continue;
if (physical_end > addr) if (physical_end > addr)
addr = physical_end - page_align (size); addr = physical_end - page_align (size);
} }
@ -657,7 +942,7 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
} }
grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n", grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n",
addr, size); (unsigned) addr, (unsigned) size);
lh->ramdisk_image = addr; lh->ramdisk_image = addr;
lh->ramdisk_size = size; lh->ramdisk_size = size;

60
normal/x86_64/setjmp.S Normal file
View file

@ -0,0 +1,60 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
.file "setjmp.S"
.text
/*
* jmp_buf:
* rbx rsp rbp r12 r13 r14 r15 rip
* 0 8 16 24 32 40 48 56
*/
/*
* int grub_setjmp (grub_jmp_buf env)
*/
FUNCTION(grub_setjmp)
pop %rsi /* Return address, and adjust the stack */
xorq %rax, %rax
movq %rbx, 0(%rdi) /* RBX */
movq %rsp, 8(%rdi) /* RSP */
push %rsi
movq %rbp, 16(%rdi) /* RBP */
movq %r12, 24(%rdi) /* R12 */
movq %r13, 32(%rdi) /* R13 */
movq %r14, 40(%rdi) /* R14 */
movq %r15, 48(%rdi) /* R15 */
movq %rsi, 56(%rdi) /* RSI */
ret
/*
* int grub_longjmp (grub_jmp_buf env, int val)
*/
FUNCTION(grub_longjmp)
movl %esi, %eax
movq (%rdi), %rbx
movq 8(%rdi), %rsp
movq 16(%rdi), %rbp
movq 24(%rdi), %r12
movq 32(%rdi), %r13
movq 40(%rdi), %r14
movq 48(%rdi), %r15
jmp *56(%rdi)

View file

@ -36,6 +36,54 @@ grub_console_highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_BLACK,
static int read_key = -1; static int read_key = -1;
static grub_uint32_t
map_char (grub_uint32_t c)
{
if (c > 0x7f)
{
/* Map some unicode characters to the EFI character. */
switch (c)
{
case 0x2190: /* left arrow */
c = 0x25c4;
break;
case 0x2191: /* up arrow */
c = 0x25b2;
break;
case 0x2192: /* right arrow */
c = 0x25ba;
break;
case 0x2193: /* down arrow */
c = 0x25bc;
break;
case 0x2501: /* horizontal line */
c = 0x2500;
break;
case 0x2503: /* vertical line */
c = 0x2502;
break;
case 0x250F: /* upper-left corner */
c = 0x250c;
break;
case 0x2513: /* upper-right corner */
c = 0x2510;
break;
case 0x2517: /* lower-left corner */
c = 0x2514;
break;
case 0x251B: /* lower-right corner */
c = 0x2518;
break;
default:
c = '?';
break;
}
}
return c;
}
static void static void
grub_console_putchar (grub_uint32_t c) grub_console_putchar (grub_uint32_t c)
{ {
@ -48,14 +96,14 @@ grub_console_putchar (grub_uint32_t c)
if (c > 0xffff) if (c > 0xffff)
c = '?'; c = '?';
str[0] = (grub_efi_char16_t) (c & 0xffff); str[0] = (grub_efi_char16_t) map_char (c & 0xffff);
str[1] = 0; str[1] = 0;
/* Should this test be cached? */ /* 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; return;
o->output_string (o, str); efi_call_2 (o->output_string, o, str);
} }
static grub_ssize_t static grub_ssize_t
@ -76,8 +124,8 @@ grub_console_checkkey (void)
return 1; return 1;
i = grub_efi_system_table->con_in; 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 #if 0
switch (status) switch (status)
{ {
case GRUB_EFI_SUCCESS: case GRUB_EFI_SUCCESS:
@ -137,6 +185,15 @@ grub_console_checkkey (void)
break; break;
case 0x0a: case 0x0a:
break; break;
case 0x0b:
read_key = 24;
break;
case 0x0c:
read_key = 1;
break;
case 0x0d:
read_key = 5;
break;
case 0x17: case 0x17:
read_key = '\e'; read_key = '\e';
break; break;
@ -169,9 +226,9 @@ grub_console_getkey (void)
do 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) if (status != GRUB_EFI_SUCCESS)
return -1; return -1;
grub_console_checkkey (); grub_console_checkkey ();
} }
@ -189,7 +246,7 @@ grub_console_getwh (void)
grub_efi_uintn_t columns, rows; grub_efi_uintn_t columns, rows;
o = grub_efi_system_table->con_out; 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? */ /* Why does this fail? */
columns = 80; columns = 80;
@ -214,7 +271,7 @@ grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y)
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out; 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 static void
@ -225,9 +282,9 @@ grub_console_cls (void)
o = grub_efi_system_table->con_out; o = grub_efi_system_table->con_out;
orig_attr = o->mode->attribute; orig_attr = o->mode->attribute;
o->set_attributes (o, GRUB_EFI_BACKGROUND_BLACK); efi_call_2 (o->set_attributes, o, GRUB_EFI_BACKGROUND_BLACK);
o->clear_screen (o); efi_call_1 (o->clear_screen, o);
o->set_attributes (o, orig_attr); efi_call_2 (o->set_attributes, o, orig_attr);
} }
static void static void
@ -239,13 +296,13 @@ grub_console_setcolorstate (grub_term_color_state state)
switch (state) { switch (state) {
case GRUB_TERM_COLOR_STANDARD: 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; break;
case GRUB_TERM_COLOR_NORMAL: 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; break;
case GRUB_TERM_COLOR_HIGHLIGHT: 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; break;
default: default:
break; break;
@ -272,7 +329,7 @@ grub_console_setcursor (int on)
grub_efi_simple_text_output_interface_t *o; grub_efi_simple_text_output_interface_t *o;
o = grub_efi_system_table->con_out; 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 = static struct grub_term grub_console_term =

View file

@ -31,16 +31,56 @@
#include <grub/efi/pe32.h> #include <grub/efi/pe32.h>
#include <grub/machine/kernel.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 const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
static inline Elf32_Addr static inline Elf_Addr
align_address (Elf32_Addr addr, unsigned alignment) align_address (Elf_Addr addr, unsigned alignment)
{ {
return (addr + alignment - 1) & ~(alignment - 1); return (addr + alignment - 1) & ~(alignment - 1);
} }
static inline Elf32_Addr static inline Elf_Addr
align_pe32_section (Elf32_Addr addr) align_pe32_section (Elf_Addr addr)
{ {
return align_address (addr, GRUB_PE32_SECTION_ALIGNMENT); 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) if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
grub_util_error ("prefix too long"); 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 kernel_image;
} }
/* Return if the ELF header is valid. */ /* Return if the ELF header is valid. */
static int static int
check_elf_header (Elf32_Ehdr *e, size_t size) check_elf_header (Elf_Ehdr *e, size_t size)
{ {
if (size < sizeof (*e) if (size < sizeof (*e)
|| e->e_ident[EI_MAG0] != ELFMAG0 || 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_MAG3] != ELFMAG3
|| e->e_ident[EI_VERSION] != EV_CURRENT || e->e_ident[EI_VERSION] != EV_CURRENT
|| e->e_version != grub_cpu_to_le32 (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_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 0;
return 1; return 1;
@ -87,7 +130,7 @@ check_elf_header (Elf32_Ehdr *e, size_t size)
/* Return the starting address right after the header, /* Return the starting address right after the header,
aligned by the section alignment. Allocate 4 section tables for aligned by the section alignment. Allocate 4 section tables for
.text, .data, .reloc, and mods. */ .text, .data, .reloc, and mods. */
static Elf32_Addr static Elf_Addr
get_starting_section_address (void) get_starting_section_address (void)
{ {
return align_pe32_section (sizeof (struct grub_pe32_header) 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 /* Determine if this section is a text section. Return false if this
section is not allocated. */ section is not allocated. */
static int 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)) return ((s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR | SHF_ALLOC))
== 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 BSS is also a data section, since the converter initializes BSS
when producing PE32 to avoid a bug in EFI implementations. */ when producing PE32 to avoid a bug in EFI implementations. */
static int static int
is_data_section (Elf32_Shdr *s) is_data_section (Elf_Shdr *s)
{ {
return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC) return (s->sh_flags & grub_cpu_to_le32 (SHF_ALLOC)
&& ! (s->sh_flags & grub_cpu_to_le32 (SHF_EXECINSTR))); && ! (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 /* Locate section addresses by merging code sections and data sections
into .text and .data, respectively. Return the array of section into .text and .data, respectively. Return the array of section
addresses. */ addresses. */
static Elf32_Addr * static Elf_Addr *
locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize, locate_sections (Elf_Shdr *sections, Elf_Half section_entsize,
Elf32_Half num_sections, const char *strtab) Elf_Half num_sections, const char *strtab)
{ {
int i; int i;
Elf32_Addr current_address; Elf_Addr current_address;
Elf32_Addr *section_addresses; Elf_Addr *section_addresses;
Elf32_Shdr *s; Elf_Shdr *s;
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections); section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, 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 */ /* .text */
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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)) 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); const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align) if (align)
@ -153,10 +196,10 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
/* .data */ /* .data */
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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)) 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); const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align) if (align)
@ -172,16 +215,16 @@ locate_sections (Elf32_Shdr *sections, Elf32_Half section_entsize,
} }
/* Return the symbol table section, if any. */ /* Return the symbol table section, if any. */
static Elf32_Shdr * static Elf_Shdr *
find_symtab_section (Elf32_Shdr *sections, find_symtab_section (Elf_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections) Elf_Half section_entsize, Elf_Half num_sections)
{ {
int i; int i;
Elf32_Shdr *s; Elf_Shdr *s;
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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)) if (s->sh_type == grub_cpu_to_le32 (SHT_SYMTAB))
return s; return s;
@ -190,12 +233,12 @@ find_symtab_section (Elf32_Shdr *sections,
/* Return the address of the string table. */ /* Return the address of the string table. */
static const char * 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; char *strtab;
s = (Elf32_Shdr *) ((char *) sections s = (Elf_Shdr *) ((char *) sections
+ grub_le_to_cpu16 (e->e_shstrndx) * section_entsize); + grub_le_to_cpu16 (e->e_shstrndx) * section_entsize);
strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset); strtab = (char *) e + grub_le_to_cpu32 (s->sh_offset);
return strtab; 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. /* Relocate symbols; note that this function overwrites the symbol table.
Return the address of a start symbol. */ Return the address of a start symbol. */
static Elf32_Addr static Elf_Addr
relocate_symbols (Elf32_Ehdr *e, Elf32_Shdr *sections, relocate_symbols (Elf_Ehdr *e, Elf_Shdr *sections,
Elf32_Shdr *symtab_section, Elf32_Addr *section_addresses, Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
Elf32_Half section_entsize, Elf32_Half num_sections) Elf_Half section_entsize, Elf_Half num_sections)
{ {
Elf32_Word symtab_size, sym_size, num_syms; Elf_Word symtab_size, sym_size, num_syms;
Elf32_Off symtab_offset; Elf_Off symtab_offset;
Elf32_Addr start_address = 0; Elf_Addr start_address = 0;
Elf32_Sym *sym; Elf_Sym *sym;
Elf32_Word i; Elf_Word i;
Elf32_Shdr *strtab_section; Elf_Shdr *strtab_section;
const char *strtab; const char *strtab;
strtab_section strtab_section
= (Elf32_Shdr *) ((char *) sections = (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (symtab_section->sh_link) + (grub_le_to_cpu32 (symtab_section->sh_link)
* section_entsize)); * section_entsize));
strtab = (char *) e + grub_le_to_cpu32 (strtab_section->sh_offset); 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); symtab_offset = grub_le_to_cpu32 (symtab_section->sh_offset);
num_syms = symtab_size / sym_size; 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 < 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; const char *name;
name = strtab + grub_le_to_cpu32 (sym->st_name); name = strtab + grub_le_to_cpu32 (sym->st_name);
index = grub_le_to_cpu16 (sym->st_shndx); 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) if (sym->st_name)
grub_util_error ("undefined symbol %s", 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. */ /* Return the address of a symbol at the index I in the section S. */
static Elf32_Addr static Elf_Addr
get_symbol_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Word i) 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) + grub_le_to_cpu32 (s->sh_offset)
+ i * grub_le_to_cpu32 (s->sh_entsize)); + i * grub_le_to_cpu32 (s->sh_entsize));
return sym->st_value; return sym->st_value;
} }
/* Return the address of a modified value. */ /* Return the address of a modified value. */
static Elf32_Addr * static Elf_Addr *
get_target_address (Elf32_Ehdr *e, Elf32_Shdr *s, Elf32_Addr offset) get_target_address (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset)
{ {
return (Elf32_Addr *) ((char *) 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 /* 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 addresses can be fully resolved. Absolute addresses must be relocated
again by a PE32 relocator when loaded. */ again by a PE32 relocator when loaded. */
static void static void
relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections, relocate_addresses (Elf_Ehdr *e, Elf_Shdr *sections,
Elf32_Addr *section_addresses, Elf_Addr *section_addresses,
Elf32_Half section_entsize, Elf32_Half num_sections, Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab) const char *strtab)
{ {
Elf32_Half i; Elf_Half i;
Elf32_Shdr *s; Elf_Shdr *s;
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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_REL)) if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
(s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{ {
Elf32_Rel *r; Elf_Rela *r;
Elf32_Word rtab_size, r_size, num_rs; Elf_Word rtab_size, r_size, num_rs;
Elf32_Off rtab_offset; Elf_Off rtab_offset;
Elf32_Shdr *symtab_section; Elf_Shdr *symtab_section;
Elf32_Word target_section_index; Elf_Word target_section_index;
Elf32_Addr target_section_addr; Elf_Addr target_section_addr;
Elf32_Shdr *target_section; Elf_Shdr *target_section;
Elf32_Word j; Elf_Word j;
symtab_section = (Elf32_Shdr *) ((char *) sections symtab_section = (Elf_Shdr *) ((char *) sections
+ (grub_le_to_cpu32 (s->sh_link) + (grub_le_to_cpu32 (s->sh_link)
* section_entsize)); * section_entsize));
target_section_index = grub_le_to_cpu32 (s->sh_info); target_section_index = grub_le_to_cpu32 (s->sh_info);
target_section_addr = section_addresses[target_section_index]; target_section_addr = section_addresses[target_section_index];
target_section = (Elf32_Shdr *) ((char *) sections target_section = (Elf_Shdr *) ((char *) sections
+ (target_section_index + (target_section_index
* section_entsize)); * section_entsize));
@ -323,46 +371,84 @@ relocate_addresses (Elf32_Ehdr *e, Elf32_Shdr *sections,
rtab_offset = grub_le_to_cpu32 (s->sh_offset); rtab_offset = grub_le_to_cpu32 (s->sh_offset);
num_rs = rtab_size / r_size; 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 < num_rs;
j++, r = (Elf32_Rel *) ((char *) r + r_size)) j++, r = (Elf_Rela *) ((char *) r + r_size))
{ {
Elf32_Word info; Elf_Addr info;
Elf32_Addr offset; Elf_Addr offset;
Elf32_Addr sym_addr; Elf_Addr sym_addr;
Elf32_Addr *target; Elf_Addr *target, *value;
offset = grub_le_to_cpu32 (r->r_offset); offset = grub_le_to_cpu (r->r_offset);
target = get_target_address (e, target_section, offset); target = get_target_address (e, target_section, offset);
info = grub_le_to_cpu32 (r->r_info); info = grub_le_to_cpu (r->r_info);
sym_addr = get_symbol_address (e, symtab_section, sym_addr = get_symbol_address (e, symtab_section,
ELF32_R_SYM (info)); ELF_R_SYM (info));
switch (ELF32_R_TYPE (info)) value = (s->sh_type == grub_cpu_to_le32 (SHT_RELA)) ?
(Elf_Addr *) &r->r_addend : target;
switch (ELF_R_TYPE (info))
{ {
#if GRUB_TARGET_SIZEOF_VOID_P == 4
case R_386_NONE: case R_386_NONE:
break; break;
case R_386_32: case R_386_32:
/* This is absolute. */ /* This is absolute. */
*target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target) *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*value)
+ sym_addr); + sym_addr);
grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x", grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x",
*target, offset); *target, offset);
break; break;
case R_386_PC32: case R_386_PC32:
/* This is relative. */ /* 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 + sym_addr
- target_section_addr - offset); - target_section_addr - offset);
grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x", grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x",
*target, offset); *target, offset);
break; 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: default:
grub_util_error ("unknown relocation type %d", grub_util_error ("unknown relocation type %d",
ELF32_R_TYPE (info)); ELF_R_TYPE (info));
break; break;
} }
} }
@ -381,9 +467,9 @@ write_padding (FILE *out, size_t size)
/* Add a PE32's fixup entry for a relocation. Return the resulting address /* Add a PE32's fixup entry for a relocation. Return the resulting address
after having written to the file OUT. */ after having written to the file OUT. */
Elf32_Addr Elf_Addr
add_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type, 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) FILE *out)
{ {
struct grub_pe32_fixup_block *b = *block; struct grub_pe32_fixup_block *b = *block;
@ -399,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 /* Add as much padding as necessary to align the address
with a section boundary. */ with a section boundary. */
Elf32_Addr next_address; Elf_Addr next_address;
unsigned padding_size; unsigned padding_size;
size_t index; size_t index;
@ -472,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. */ /* Write out zeros to make space for the header. */
static Elf32_Addr static Elf_Addr
make_header_space (FILE *out) make_header_space (FILE *out)
{ {
Elf32_Addr addr; Elf_Addr addr;
addr = get_starting_section_address (); addr = get_starting_section_address ();
write_padding (out, addr); write_padding (out, addr);
@ -484,24 +570,24 @@ make_header_space (FILE *out)
} }
/* Write text sections. */ /* Write text sections. */
static Elf32_Addr static Elf_Addr
write_text_sections (FILE *out, Elf32_Addr current_address, write_text_sections (FILE *out, Elf_Addr current_address,
Elf32_Ehdr *e, Elf32_Shdr *sections, Elf_Ehdr *e, Elf_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections, Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab) const char *strtab)
{ {
Elf32_Half i; Elf_Half i;
Elf32_Shdr *s; Elf_Shdr *s;
Elf32_Addr addr; Elf_Addr addr;
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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)) 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);
Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset); Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf32_Word size = grub_le_to_cpu32 (s->sh_size); Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name); const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align) if (align)
@ -537,24 +623,24 @@ write_text_sections (FILE *out, Elf32_Addr current_address,
} }
/* Write data sections. */ /* Write data sections. */
static Elf32_Addr static Elf_Addr
write_data_sections (FILE *out, Elf32_Addr current_address, write_data_sections (FILE *out, Elf_Addr current_address,
Elf32_Ehdr *e, Elf32_Shdr *sections, Elf_Ehdr *e, Elf_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections, Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab) const char *strtab)
{ {
Elf32_Half i; Elf_Half i;
Elf32_Shdr *s; Elf_Shdr *s;
Elf32_Addr addr; Elf_Addr addr;
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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)) 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);
Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset); Elf_Off offset = grub_le_to_cpu32 (s->sh_offset);
Elf32_Word size = grub_le_to_cpu32 (s->sh_size); Elf_Word size = grub_le_to_cpu32 (s->sh_size);
const char *name = strtab + grub_le_to_cpu32 (s->sh_name); const char *name = strtab + grub_le_to_cpu32 (s->sh_name);
if (align) if (align)
@ -593,15 +679,15 @@ write_data_sections (FILE *out, Elf32_Addr current_address,
} }
/* Write modules. */ /* Write modules. */
static Elf32_Addr static Elf_Addr
make_mods_section (FILE *out, Elf32_Addr current_address, make_mods_section (FILE *out, Elf_Addr current_address,
const char *dir, char *mods[]) const char *dir, char *mods[])
{ {
struct grub_util_path_list *path_list; struct grub_util_path_list *path_list;
grub_size_t total_module_size; grub_size_t total_module_size;
struct grub_util_path_list *p; struct grub_util_path_list *p;
struct grub_module_info modinfo; struct grub_module_info modinfo;
Elf32_Addr addr; Elf_Addr addr;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
@ -665,26 +751,27 @@ make_mods_section (FILE *out, Elf32_Addr current_address,
} }
/* Make a .reloc section. */ /* Make a .reloc section. */
static Elf32_Addr static Elf_Addr
make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e,
Elf32_Addr *section_addresses, Elf32_Shdr *sections, Elf_Addr *section_addresses, Elf_Shdr *sections,
Elf32_Half section_entsize, Elf32_Half num_sections, Elf_Half section_entsize, Elf_Half num_sections,
const char *strtab) const char *strtab)
{ {
Elf32_Half i; Elf_Half i;
Elf32_Shdr *s; Elf_Shdr *s;
struct grub_pe32_fixup_block *fixup_block = 0; struct grub_pe32_fixup_block *fixup_block = 0;
for (i = 0, s = sections; for (i = 0, s = sections;
i < num_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_REL)) if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
(s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
{ {
Elf32_Rel *r; Elf_Rel *r;
Elf32_Word rtab_size, r_size, num_rs; Elf_Word rtab_size, r_size, num_rs;
Elf32_Off rtab_offset; Elf_Off rtab_offset;
Elf32_Addr section_address; Elf_Addr section_address;
Elf32_Word j; Elf_Word j;
grub_util_info ("translating the relocation section %s", grub_util_info ("translating the relocation section %s",
strtab + grub_le_to_cpu32 (s->sh_name)); strtab + grub_le_to_cpu32 (s->sh_name));
@ -696,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)]; 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 < num_rs;
j++, r = (Elf32_Rel *) ((char *) r + r_size)) j++, r = (Elf_Rel *) ((char *) r + r_size))
{ {
Elf32_Word info; Elf_Addr info;
Elf32_Addr offset; Elf_Addr offset;
offset = grub_le_to_cpu32 (r->r_offset); offset = grub_le_to_cpu32 (r->r_offset);
info = grub_le_to_cpu32 (r->r_info); info = grub_le_to_cpu32 (r->r_info);
/* Necessary to relocate only absolute addresses. */ /* 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; addr = section_address + offset;
grub_util_info ("adding a relocation entry for 0x%x", addr); grub_util_info ("adding a relocation entry for 0x%x", addr);
@ -718,6 +806,21 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
addr, 0, current_address, addr, 0, current_address,
out); 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
} }
} }
@ -729,9 +832,9 @@ make_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e,
/* Create the header. */ /* Create the header. */
static void static void
make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address, make_header (FILE *out, Elf_Addr text_address, Elf_Addr data_address,
Elf32_Addr mods_address, Elf32_Addr reloc_address, Elf_Addr mods_address, Elf_Addr reloc_address,
Elf32_Addr end_address, Elf32_Addr start_address) Elf_Addr end_address, Elf_Addr start_address)
{ {
struct grub_pe32_header header; struct grub_pe32_header header;
struct grub_pe32_coff_header *c; struct grub_pe32_coff_header *c;
@ -746,14 +849,22 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
/* The COFF file header. */ /* The COFF file header. */
c = &header.coff_header; c = &header.coff_header;
#if GRUB_TARGET_SIZEOF_VOID_P == 4
c->machine = grub_cpu_to_le16 (GRUB_PE32_MACHINE_I386); 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->num_sections = grub_cpu_to_le16 (4);
c->time = grub_cpu_to_le32 (time (0)); c->time = grub_cpu_to_le32 (time (0));
c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header)); c->optional_header_size = grub_cpu_to_le16 (sizeof (header.optional_header));
c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE c->characteristics = grub_cpu_to_le16 (GRUB_PE32_EXECUTABLE_IMAGE
| GRUB_PE32_LINE_NUMS_STRIPPED | GRUB_PE32_LINE_NUMS_STRIPPED
#if GRUB_TARGET_SIZEOF_VOID_P == 4
| GRUB_PE32_32BIT_MACHINE
#endif
| GRUB_PE32_LOCAL_SYMS_STRIPPED | GRUB_PE32_LOCAL_SYMS_STRIPPED
| GRUB_PE32_32BIT_MACHINE); | GRUB_PE32_DEBUG_STRIPPED);
/* The PE Optional header. */ /* The PE Optional header. */
o = &header.optional_header; o = &header.optional_header;
@ -763,7 +874,9 @@ make_header (FILE *out, Elf32_Addr text_address, Elf32_Addr data_address,
o->bss_size = 0; o->bss_size = 0;
o->entry_addr = grub_cpu_to_le32 (start_address); o->entry_addr = grub_cpu_to_le32 (start_address);
o->code_base = grub_cpu_to_le32 (text_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); o->data_base = grub_cpu_to_le32 (data_address);
#endif
o->image_base = 0; o->image_base = 0;
o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT); o->section_alignment = grub_cpu_to_le32 (GRUB_PE32_SECTION_ALIGNMENT);
o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT); o->file_alignment = grub_cpu_to_le32 (GRUB_PE32_FILE_ALIGNMENT);
@ -846,30 +959,31 @@ convert_elf (const char *dir, char *prefix, FILE *out, char *mods[])
char *kernel_image; char *kernel_image;
size_t kernel_size; size_t kernel_size;
const char *strtab; const char *strtab;
Elf32_Ehdr *e; Elf_Ehdr *e;
Elf32_Shdr *sections; Elf_Shdr *sections;
Elf32_Off section_offset; Elf_Off section_offset;
Elf32_Half section_entsize; Elf_Half section_entsize;
Elf32_Half num_sections; Elf_Half num_sections;
Elf32_Addr *section_addresses; Elf_Addr *section_addresses;
Elf32_Shdr *symtab_section; Elf_Shdr *symtab_section;
Elf32_Addr start_address; Elf_Addr start_address;
Elf32_Addr text_address, data_address, reloc_address, mods_address; Elf_Addr text_address, data_address, reloc_address, mods_address;
Elf32_Addr end_address; Elf_Addr end_address;
/* Get the kernel image and check the format. */ /* Get the kernel image and check the format. */
kernel_image = read_kernel_module (dir, prefix, &kernel_size); 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)) if (! check_elf_header (e, kernel_size))
grub_util_error ("invalid ELF header"); grub_util_error ("invalid ELF header");
section_offset = grub_cpu_to_le32 (e->e_shoff); section_offset = grub_cpu_to_le32 (e->e_shoff);
section_entsize = grub_cpu_to_le16 (e->e_shentsize); section_entsize = grub_cpu_to_le16 (e->e_shentsize);
num_sections = grub_cpu_to_le16 (e->e_shnum); num_sections = grub_cpu_to_le16 (e->e_shnum);
if (kernel_size < section_offset + section_entsize * num_sections) if (kernel_size < section_offset + section_entsize * num_sections)
grub_util_error ("invalid ELF format"); 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); strtab = find_strtab (e, sections, section_entsize);
/* Relocate sections then symbols in the virtual address space. */ /* Relocate sections then symbols in the virtual address space. */