2006-04-30 Yoshinori K. Okuji <okuji@enbug.org>
Extend the loader so that GRUB can accept a loader which comes back to GRUB when a loaded image exits. Also, this change adds support for a chainloader on EFI. * term/efi/console.c: Include grub/misc.h. (grub_console_checkkey): Display a scan code on the top for debugging. This will be removed once the EFI port gets stable. Correct the scan code mapping. * kern/efi/mm.c (sort_memory_map): Sort in a descending order to allocate memory from larger regions, in order to reduce the number of allocated regions. Otherwise, the MacOSX loader panics. (filter_memory_map): Avoid less than 1MB for compatibility with other loaders. (add_memory_regions): Allocate from the tail of a region, if possible, to avoid allocating a region near to 1MB, for the MacOSX loader. * kern/efi/init.c (grub_efi_set_prefix): Specify GRUB_EFI_IMAGE_HANDLE to grub_efi_get_loaded_image. * kern/efi/efi.c (grub_efi_get_loaded_image): Accept a new argument IMAGE_HANDLE and specify it to get a loaded image. (grub_arch_modules_addr): Specify GRUB_EFI_IMAGE_HANDLE to grub_efi_get_loaded_image. (grub_efi_get_filename): Divide the legnth by the size of grub_efi_char16_t. (grub_efi_get_device_path): New function. (grub_efi_print_device_path): Print End Device Path nodes. Divide the length by the size of grub_efi_char16_t for a file path device path node. * kern/loader.c (grub_loader_noreturn): New variable. (grub_loader_set): Accept a new argument NORETURN. Set GRUB_LOADER_NORETURN to NORETURN. All callers changed. (grub_loader_boot): If GRUB_LOADER_NORETURN is false, do not call grub_machine_fini. * include/grub/efi/efi.h (grub_efi_get_device_path): New prototype. (grub_efi_get_loaded_image): Take an argument to specify an image handle. * include/grub/loader.h (grub_loader_set): Added one more argument NORETURN. * disk/efi/efidisk.c (make_devices): Use grub_efi_get_device_path instead of grub_efi_open_protocol. (grub_efidisk_get_device_name): Likewise. (grub_efidisk_close): Print a newline. (grub_efidisk_get_device_handle): Fixed to use GRUB_EFI_DEVICE_PATH_SUBTYPE instead of GRUB_EFI_DEVICE_PATH_TYPE. * disk/efi/efidisk.c (device_path_guid): Moved to ... * kern/efi/efi.c (device_path_guid): ... here. * conf/i386-efi.rmk (pkgdata_MODULES): Added _chain.mod and chain.mod. (kernel_mod_HEADERS): Added efi/disk.h. (_chain_mod_SOURCES): New variable. (_chain_mod_CFLAGS): Likewise. (_chain_mod_LDFLAGS): Likewise. (chain_mod_SOURCES): Likewise. (chain_mod_CFLAGS): Likewise. (chain_mod_LDFLAGS): Likewise. * DISTLIST: Added include/grub/efi/chainloader.h, loader/efi/chainloader.c and loader/efi/chainloader_normal.c. * include/grub/efi/chainloader.h: New file. * loader/efi/chainloader.c: Likewise. * loader/efi/chainloader_normal.c: Likewise.
This commit is contained in:
parent
c0111d6e92
commit
7f362539b7
19 changed files with 743 additions and 64 deletions
77
ChangeLog
77
ChangeLog
|
@ -1,3 +1,80 @@
|
||||||
|
2006-04-30 Yoshinori K. Okuji <okuji@enbug.org>
|
||||||
|
|
||||||
|
Extend the loader so that GRUB can accept a loader which comes
|
||||||
|
back to GRUB when a loaded image exits. Also, this change adds
|
||||||
|
support for a chainloader on EFI.
|
||||||
|
|
||||||
|
* term/efi/console.c: Include grub/misc.h.
|
||||||
|
(grub_console_checkkey): Display a scan code on the top for
|
||||||
|
debugging. This will be removed once the EFI port gets stable.
|
||||||
|
Correct the scan code mapping.
|
||||||
|
|
||||||
|
* kern/efi/mm.c (sort_memory_map): Sort in a descending order to
|
||||||
|
allocate memory from larger regions, in order to reduce the number
|
||||||
|
of allocated regions. Otherwise, the MacOSX loader panics.
|
||||||
|
(filter_memory_map): Avoid less than 1MB for compatibility with
|
||||||
|
other loaders.
|
||||||
|
(add_memory_regions): Allocate from the tail of a region, if
|
||||||
|
possible, to avoid allocating a region near to 1MB, for the MacOSX
|
||||||
|
loader.
|
||||||
|
|
||||||
|
* kern/efi/init.c (grub_efi_set_prefix): Specify
|
||||||
|
GRUB_EFI_IMAGE_HANDLE to grub_efi_get_loaded_image.
|
||||||
|
|
||||||
|
* kern/efi/efi.c (grub_efi_get_loaded_image): Accept a new
|
||||||
|
argument IMAGE_HANDLE and specify it to get a loaded image.
|
||||||
|
(grub_arch_modules_addr): Specify GRUB_EFI_IMAGE_HANDLE to
|
||||||
|
grub_efi_get_loaded_image.
|
||||||
|
(grub_efi_get_filename): Divide the legnth by the size of
|
||||||
|
grub_efi_char16_t.
|
||||||
|
(grub_efi_get_device_path): New function.
|
||||||
|
(grub_efi_print_device_path): Print End Device Path nodes. Divide
|
||||||
|
the length by the size of grub_efi_char16_t for a file path device
|
||||||
|
path node.
|
||||||
|
|
||||||
|
* kern/loader.c (grub_loader_noreturn): New variable.
|
||||||
|
(grub_loader_set): Accept a new argument NORETURN. Set
|
||||||
|
GRUB_LOADER_NORETURN to NORETURN.
|
||||||
|
All callers changed.
|
||||||
|
(grub_loader_boot): If GRUB_LOADER_NORETURN is false, do not call
|
||||||
|
grub_machine_fini.
|
||||||
|
|
||||||
|
* include/grub/efi/efi.h (grub_efi_get_device_path): New
|
||||||
|
prototype.
|
||||||
|
(grub_efi_get_loaded_image): Take an argument to specify an image
|
||||||
|
handle.
|
||||||
|
|
||||||
|
* include/grub/loader.h (grub_loader_set): Added one more argument
|
||||||
|
NORETURN.
|
||||||
|
|
||||||
|
* disk/efi/efidisk.c (make_devices): Use grub_efi_get_device_path
|
||||||
|
instead of grub_efi_open_protocol.
|
||||||
|
(grub_efidisk_get_device_name): Likewise.
|
||||||
|
(grub_efidisk_close): Print a newline.
|
||||||
|
(grub_efidisk_get_device_handle): Fixed to use
|
||||||
|
GRUB_EFI_DEVICE_PATH_SUBTYPE instead of
|
||||||
|
GRUB_EFI_DEVICE_PATH_TYPE.
|
||||||
|
|
||||||
|
* disk/efi/efidisk.c (device_path_guid): Moved to ...
|
||||||
|
* kern/efi/efi.c (device_path_guid): ... here.
|
||||||
|
|
||||||
|
* conf/i386-efi.rmk (pkgdata_MODULES): Added _chain.mod and
|
||||||
|
chain.mod.
|
||||||
|
(kernel_mod_HEADERS): Added efi/disk.h.
|
||||||
|
(_chain_mod_SOURCES): New variable.
|
||||||
|
(_chain_mod_CFLAGS): Likewise.
|
||||||
|
(_chain_mod_LDFLAGS): Likewise.
|
||||||
|
(chain_mod_SOURCES): Likewise.
|
||||||
|
(chain_mod_CFLAGS): Likewise.
|
||||||
|
(chain_mod_LDFLAGS): Likewise.
|
||||||
|
|
||||||
|
* DISTLIST: Added include/grub/efi/chainloader.h,
|
||||||
|
loader/efi/chainloader.c and loader/efi/chainloader_normal.c.
|
||||||
|
|
||||||
|
* include/grub/efi/chainloader.h: New file.
|
||||||
|
* loader/efi/chainloader.c: Likewise.
|
||||||
|
* loader/efi/chainloader_normal.c: Likewise.
|
||||||
|
|
||||||
2006-04-30 Marco Gerards <marco@gnu.org>
|
2006-04-30 Marco Gerards <marco@gnu.org>
|
||||||
|
|
||||||
* commands/configfile.c (grub_cmd_source): New function.
|
* commands/configfile.c (grub_cmd_source): New function.
|
||||||
|
|
3
DISTLIST
3
DISTLIST
|
@ -113,6 +113,7 @@ include/grub/tparm.h
|
||||||
include/grub/types.h
|
include/grub/types.h
|
||||||
include/grub/video.h
|
include/grub/video.h
|
||||||
include/grub/efi/api.h
|
include/grub/efi/api.h
|
||||||
|
include/grub/efi/chainloader.h
|
||||||
include/grub/efi/console.h
|
include/grub/efi/console.h
|
||||||
include/grub/efi/console_control.h
|
include/grub/efi/console_control.h
|
||||||
include/grub/efi/disk.h
|
include/grub/efi/disk.h
|
||||||
|
@ -198,6 +199,8 @@ kern/sparc64/cache.S
|
||||||
kern/sparc64/dl.c
|
kern/sparc64/dl.c
|
||||||
kern/sparc64/ieee1275/init.c
|
kern/sparc64/ieee1275/init.c
|
||||||
kern/sparc64/ieee1275/openfw.c
|
kern/sparc64/ieee1275/openfw.c
|
||||||
|
loader/efi/chainloader.c
|
||||||
|
loader/efi/chainloader_normal.c
|
||||||
loader/i386/pc/chainloader.c
|
loader/i386/pc/chainloader.c
|
||||||
loader/i386/pc/chainloader_normal.c
|
loader/i386/pc/chainloader_normal.c
|
||||||
loader/i386/pc/linux.c
|
loader/i386/pc/linux.c
|
||||||
|
|
116
conf/i386-efi.mk
116
conf/i386-efi.mk
|
@ -111,7 +111,7 @@ genmoddep-util_genmoddep.d: util/genmoddep.c
|
||||||
#grub_install_SOURCES = util/efi/pc/grub-install.in
|
#grub_install_SOURCES = util/efi/pc/grub-install.in
|
||||||
|
|
||||||
# Modules.
|
# Modules.
|
||||||
pkgdata_MODULES = kernel.mod normal.mod
|
pkgdata_MODULES = kernel.mod normal.mod _chain.mod chain.mod
|
||||||
|
|
||||||
# For kernel.mod.
|
# For kernel.mod.
|
||||||
kernel_mod_EXPORTS = no
|
kernel_mod_EXPORTS = no
|
||||||
|
@ -612,7 +612,7 @@ fs-kernel_mod-disk_efi_efidisk.lst: disk/efi/efidisk.c genfslist.sh
|
||||||
kernel_mod_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
|
kernel_mod_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
|
||||||
file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h partition.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 types.h \
|
pc_partition.h rescue.h symbol.h term.h types.h \
|
||||||
i386/efi/time.h efi/efi.h efi/time.h
|
i386/efi/time.h efi/efi.h efi/time.h efi/disk.h
|
||||||
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
|
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
@ -954,4 +954,116 @@ normal_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For _chain.mod.
|
||||||
|
_chain_mod_SOURCES = loader/efi/chainloader.c
|
||||||
|
CLEANFILES += _chain.mod mod-_chain.o mod-_chain.c pre-_chain.o _chain_mod-loader_efi_chainloader.o und-_chain.lst
|
||||||
|
ifneq ($(_chain_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-_chain.lst
|
||||||
|
DEFSYMFILES += def-_chain.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += _chain_mod-loader_efi_chainloader.d
|
||||||
|
UNDSYMFILES += und-_chain.lst
|
||||||
|
|
||||||
|
_chain.mod: pre-_chain.o mod-_chain.o
|
||||||
|
-rm -f $@
|
||||||
|
$(CC) $(_chain_mod_LDFLAGS) $(LDFLAGS) -Wl,-r,-d -o $@ $^
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-_chain.o: _chain_mod-loader_efi_chainloader.o
|
||||||
|
-rm -f $@
|
||||||
|
$(CC) $(_chain_mod_LDFLAGS) $(LDFLAGS) -Wl,-r,-d -o $@ $^
|
||||||
|
|
||||||
|
mod-_chain.o: mod-_chain.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(_chain_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-_chain.c: moddep.lst genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh '_chain' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(_chain_mod_EXPORTS),no)
|
||||||
|
def-_chain.lst: pre-_chain.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 _chain/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-_chain.lst: pre-_chain.o
|
||||||
|
echo '_chain' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
_chain_mod-loader_efi_chainloader.o: loader/efi/chainloader.c
|
||||||
|
$(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(_chain_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
_chain_mod-loader_efi_chainloader.d: loader/efi/chainloader.c
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(_chain_mod_CFLAGS) -M $< | sed 's,chainloader\.o[ :]*,_chain_mod-loader_efi_chainloader.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
|
||||||
|
|
||||||
|
-include _chain_mod-loader_efi_chainloader.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-_chain_mod-loader_efi_chainloader.lst fs-_chain_mod-loader_efi_chainloader.lst
|
||||||
|
COMMANDFILES += cmd-_chain_mod-loader_efi_chainloader.lst
|
||||||
|
FSFILES += fs-_chain_mod-loader_efi_chainloader.lst
|
||||||
|
|
||||||
|
cmd-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c gencmdlist.sh
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(_chain_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh _chain > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-_chain_mod-loader_efi_chainloader.lst: loader/efi/chainloader.c genfslist.sh
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(_chain_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh _chain > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
_chain_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
_chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
|
# For chain.mod.
|
||||||
|
chain_mod_SOURCES = loader/efi/chainloader_normal.c
|
||||||
|
CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_efi_chainloader_normal.o und-chain.lst
|
||||||
|
ifneq ($(chain_mod_EXPORTS),no)
|
||||||
|
CLEANFILES += def-chain.lst
|
||||||
|
DEFSYMFILES += def-chain.lst
|
||||||
|
endif
|
||||||
|
MOSTLYCLEANFILES += chain_mod-loader_efi_chainloader_normal.d
|
||||||
|
UNDSYMFILES += und-chain.lst
|
||||||
|
|
||||||
|
chain.mod: pre-chain.o mod-chain.o
|
||||||
|
-rm -f $@
|
||||||
|
$(CC) $(chain_mod_LDFLAGS) $(LDFLAGS) -Wl,-r,-d -o $@ $^
|
||||||
|
$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@
|
||||||
|
|
||||||
|
pre-chain.o: chain_mod-loader_efi_chainloader_normal.o
|
||||||
|
-rm -f $@
|
||||||
|
$(CC) $(chain_mod_LDFLAGS) $(LDFLAGS) -Wl,-r,-d -o $@ $^
|
||||||
|
|
||||||
|
mod-chain.o: mod-chain.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
mod-chain.c: moddep.lst genmodsrc.sh
|
||||||
|
sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
ifneq ($(chain_mod_EXPORTS),no)
|
||||||
|
def-chain.lst: pre-chain.o
|
||||||
|
$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
und-chain.lst: pre-chain.o
|
||||||
|
echo 'chain' > $@
|
||||||
|
$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
|
||||||
|
|
||||||
|
chain_mod-loader_efi_chainloader_normal.o: loader/efi/chainloader_normal.c
|
||||||
|
$(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
chain_mod-loader_efi_chainloader_normal.d: loader/efi/chainloader_normal.c
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -M $< | sed 's,chainloader_normal\.o[ :]*,chain_mod-loader_efi_chainloader_normal.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@
|
||||||
|
|
||||||
|
-include chain_mod-loader_efi_chainloader_normal.d
|
||||||
|
|
||||||
|
CLEANFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst fs-chain_mod-loader_efi_chainloader_normal.lst
|
||||||
|
COMMANDFILES += cmd-chain_mod-loader_efi_chainloader_normal.lst
|
||||||
|
FSFILES += fs-chain_mod-loader_efi_chainloader_normal.lst
|
||||||
|
|
||||||
|
cmd-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c gencmdlist.sh
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh chain > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
fs-chain_mod-loader_efi_chainloader_normal.lst: loader/efi/chainloader_normal.c genfslist.sh
|
||||||
|
set -e; $(CC) -Iloader/efi -I$(srcdir)/loader/efi $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh chain > $@ || (rm -f $@; exit 1)
|
||||||
|
|
||||||
|
|
||||||
|
chain_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
|
chain_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
|
||||||
include $(srcdir)/conf/common.mk
|
include $(srcdir)/conf/common.mk
|
||||||
|
|
|
@ -67,7 +67,7 @@ genmoddep_SOURCES = util/genmoddep.c
|
||||||
#grub_install_SOURCES = util/efi/pc/grub-install.in
|
#grub_install_SOURCES = util/efi/pc/grub-install.in
|
||||||
|
|
||||||
# Modules.
|
# Modules.
|
||||||
pkgdata_MODULES = kernel.mod normal.mod
|
pkgdata_MODULES = kernel.mod normal.mod _chain.mod chain.mod
|
||||||
|
|
||||||
# For kernel.mod.
|
# For kernel.mod.
|
||||||
kernel_mod_EXPORTS = no
|
kernel_mod_EXPORTS = no
|
||||||
|
@ -80,7 +80,7 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
|
||||||
kernel_mod_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
|
kernel_mod_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
|
||||||
file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h partition.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 types.h \
|
pc_partition.h rescue.h symbol.h term.h types.h \
|
||||||
i386/efi/time.h efi/efi.h efi/time.h
|
i386/efi/time.h efi/efi.h efi/time.h efi/disk.h
|
||||||
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
|
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||||
|
@ -105,4 +105,14 @@ normal_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||||
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
|
||||||
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
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)
|
||||||
|
|
||||||
include $(srcdir)/conf/common.mk
|
include $(srcdir)/conf/common.mk
|
||||||
|
|
|
@ -41,7 +41,6 @@ struct grub_efidisk_data
|
||||||
/* GUIDs. */
|
/* GUIDs. */
|
||||||
static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
|
static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
|
||||||
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
|
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
|
||||||
static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
|
|
||||||
|
|
||||||
static struct grub_efidisk_data *fd_devices;
|
static struct grub_efidisk_data *fd_devices;
|
||||||
static struct grub_efidisk_data *hd_devices;
|
static struct grub_efidisk_data *hd_devices;
|
||||||
|
@ -159,8 +158,7 @@ make_devices (void)
|
||||||
grub_efi_block_io_t *bio;
|
grub_efi_block_io_t *bio;
|
||||||
grub_efi_disk_io_t *dio;
|
grub_efi_disk_io_t *dio;
|
||||||
|
|
||||||
dp = grub_efi_open_protocol (*handle, &device_path_guid,
|
dp = grub_efi_get_device_path (*handle);
|
||||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
||||||
if (! dp)
|
if (! dp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -556,7 +554,7 @@ static void
|
||||||
grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused)))
|
grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
/* EFI disks do not allocate extra memory, so nothing to do here. */
|
/* EFI disks do not allocate extra memory, so nothing to do here. */
|
||||||
grub_dprintf ("efidisk", "closing %s", disk->name);
|
grub_dprintf ("efidisk", "closing %s\n", disk->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -683,7 +681,7 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
|
||||||
|
|
||||||
if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path)
|
if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path)
|
||||||
== GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
|
== GRUB_EFI_MEDIA_DEVICE_PATH_TYPE)
|
||||||
&& (GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path)
|
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path)
|
||||||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)
|
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)
|
||||||
&& (grub_partition_get_start (disk->partition)
|
&& (grub_partition_get_start (disk->partition)
|
||||||
== hd.partition_start)
|
== hd.partition_start)
|
||||||
|
@ -718,8 +716,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
{
|
{
|
||||||
grub_efi_device_path_t *dp, *ldp;
|
grub_efi_device_path_t *dp, *ldp;
|
||||||
|
|
||||||
dp = grub_efi_open_protocol (handle, &device_path_guid,
|
dp = grub_efi_get_device_path (handle);
|
||||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
||||||
if (! dp)
|
if (! dp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
25
include/grub/efi/chainloader.h
Normal file
25
include/grub/efi/chainloader.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRUB_EFI_CHAINLOADER_HEADER
|
||||||
|
#define GRUB_EFI_CHAINLOADER_HEADER 1
|
||||||
|
|
||||||
|
void grub_chainloader_cmd (const char *filename);
|
||||||
|
|
||||||
|
#endif /* ! GRUB_EFI_CHAINLOADER_HEADER */
|
|
@ -49,9 +49,11 @@ EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size,
|
||||||
grub_efi_uintn_t *map_key,
|
grub_efi_uintn_t *map_key,
|
||||||
grub_efi_uintn_t *descriptor_size,
|
grub_efi_uintn_t *descriptor_size,
|
||||||
grub_efi_uint32_t *descriptor_version);
|
grub_efi_uint32_t *descriptor_version);
|
||||||
grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (void);
|
grub_efi_loaded_image_t *EXPORT_FUNC(grub_efi_get_loaded_image) (grub_efi_handle_t image_handle);
|
||||||
void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
|
void EXPORT_FUNC(grub_efi_print_device_path) (grub_efi_device_path_t *dp);
|
||||||
char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
|
char *EXPORT_FUNC(grub_efi_get_filename) (grub_efi_device_path_t *dp);
|
||||||
|
grub_efi_device_path_t *
|
||||||
|
EXPORT_FUNC(grub_efi_get_device_path) (grub_efi_handle_t handle);
|
||||||
|
|
||||||
void grub_efi_mm_init (void);
|
void grub_efi_mm_init (void);
|
||||||
void grub_efi_mm_fini (void);
|
void grub_efi_mm_fini (void);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* loader.h - OS loaders */
|
/* loader.h - OS loaders */
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc.
|
* Copyright (C) 2002,2003,2004,2006 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -26,11 +26,20 @@
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
|
|
||||||
|
/* Check if a loader is loaded. */
|
||||||
int EXPORT_FUNC(grub_loader_is_loaded) (void);
|
int EXPORT_FUNC(grub_loader_is_loaded) (void);
|
||||||
|
|
||||||
|
/* Set loader functions. NORETURN must be set to true, if BOOT won't return
|
||||||
|
to the original state. */
|
||||||
void EXPORT_FUNC(grub_loader_set) (grub_err_t (*boot) (void),
|
void EXPORT_FUNC(grub_loader_set) (grub_err_t (*boot) (void),
|
||||||
grub_err_t (*unload) (void));
|
grub_err_t (*unload) (void),
|
||||||
|
int noreturn);
|
||||||
|
|
||||||
|
/* Unset current loader, if any. */
|
||||||
void EXPORT_FUNC(grub_loader_unset) (void);
|
void EXPORT_FUNC(grub_loader_unset) (void);
|
||||||
|
|
||||||
|
/* Call the boot hook in current loader. This may or may not return,
|
||||||
|
depending on the setting by grub_loader_set. */
|
||||||
grub_err_t EXPORT_FUNC(grub_loader_boot) (void);
|
grub_err_t EXPORT_FUNC(grub_loader_boot) (void);
|
||||||
|
|
||||||
#endif /* ! GRUB_LOADER_HEADER */
|
#endif /* ! GRUB_LOADER_HEADER */
|
||||||
|
|
|
@ -36,6 +36,7 @@ grub_efi_system_table_t *grub_efi_system_table;
|
||||||
|
|
||||||
static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
|
static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
|
||||||
static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
|
static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
|
||||||
|
static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
|
grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration)
|
||||||
|
@ -144,9 +145,9 @@ grub_efi_stall (grub_efi_uintn_t microseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_efi_loaded_image_t *
|
grub_efi_loaded_image_t *
|
||||||
grub_efi_get_loaded_image (void)
|
grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
|
||||||
{
|
{
|
||||||
return grub_efi_open_protocol (grub_efi_image_handle,
|
return grub_efi_open_protocol (image_handle,
|
||||||
&loaded_image_guid,
|
&loaded_image_guid,
|
||||||
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
}
|
}
|
||||||
|
@ -189,7 +190,7 @@ grub_arch_modules_addr (void)
|
||||||
struct grub_module_info *info;
|
struct grub_module_info *info;
|
||||||
grub_uint16_t i;
|
grub_uint16_t i;
|
||||||
|
|
||||||
image = grub_efi_get_loaded_image ();
|
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
if (! image)
|
if (! image)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -248,7 +249,8 @@ grub_efi_get_filename (grub_efi_device_path_t *dp)
|
||||||
else
|
else
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
len = GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4;
|
len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||||
|
/ sizeof (grub_efi_char16_t));
|
||||||
p = grub_realloc (name, size + len * 4 + 1);
|
p = grub_realloc (name, size + len * 4 + 1);
|
||||||
if (! p)
|
if (! p)
|
||||||
{
|
{
|
||||||
|
@ -278,6 +280,13 @@ grub_efi_get_filename (grub_efi_device_path_t *dp)
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_efi_device_path_t *
|
||||||
|
grub_efi_get_device_path (grub_efi_handle_t handle)
|
||||||
|
{
|
||||||
|
return grub_efi_open_protocol (handle, &device_path_guid,
|
||||||
|
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Print the chain of Device Path nodes. This is mainly for debugging. */
|
/* Print the chain of Device Path nodes. This is mainly for debugging. */
|
||||||
void
|
void
|
||||||
grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
||||||
|
@ -294,12 +303,12 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
||||||
switch (subtype)
|
switch (subtype)
|
||||||
{
|
{
|
||||||
case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
|
case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
|
||||||
/* grub_printf ("/EndEntire\n"); */
|
grub_printf ("/EndEntire\n");
|
||||||
grub_putchar ('\n');
|
//grub_putchar ('\n');
|
||||||
break;
|
break;
|
||||||
case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
|
case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
|
||||||
/* grub_printf ("/EndThis\n"); */
|
grub_printf ("/EndThis\n");
|
||||||
grub_putchar ('\n');
|
//grub_putchar ('\n');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
|
grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
|
||||||
|
@ -633,9 +642,11 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
||||||
case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
|
case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
|
||||||
{
|
{
|
||||||
grub_efi_file_path_device_path_t *fp;
|
grub_efi_file_path_device_path_t *fp;
|
||||||
grub_uint8_t buf[(len - 4) * 4 + 1];
|
grub_uint8_t buf[(len - 4) * 2 + 1];
|
||||||
fp = (grub_efi_file_path_device_path_t *) dp;
|
fp = (grub_efi_file_path_device_path_t *) dp;
|
||||||
*grub_utf16_to_utf8 (buf, fp->path_name, len - 4) = '\0';
|
*grub_utf16_to_utf8 (buf, fp->path_name,
|
||||||
|
(len - 4) / sizeof (grub_efi_char16_t))
|
||||||
|
= '\0';
|
||||||
grub_printf ("/File(%s)", buf);
|
grub_printf ("/File(%s)", buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -46,7 +46,7 @@ grub_efi_set_prefix (void)
|
||||||
{
|
{
|
||||||
grub_efi_loaded_image_t *image;
|
grub_efi_loaded_image_t *image;
|
||||||
|
|
||||||
image = grub_efi_get_loaded_image ();
|
image = grub_efi_get_loaded_image (grub_efi_image_handle);
|
||||||
if (image)
|
if (image)
|
||||||
{
|
{
|
||||||
char *device;
|
char *device;
|
||||||
|
|
|
@ -184,23 +184,23 @@ sort_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||||
d1 < memory_map_end;
|
d1 < memory_map_end;
|
||||||
d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size))
|
d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size))
|
||||||
{
|
{
|
||||||
grub_efi_memory_descriptor_t *min_desc = d1;
|
grub_efi_memory_descriptor_t *max_desc = d1;
|
||||||
|
|
||||||
for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size);
|
for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size);
|
||||||
d2 < memory_map_end;
|
d2 < memory_map_end;
|
||||||
d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size))
|
d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size))
|
||||||
{
|
{
|
||||||
if (min_desc->num_pages > d2->num_pages)
|
if (max_desc->num_pages < d2->num_pages)
|
||||||
min_desc = d2;
|
max_desc = d2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_desc != d1)
|
if (max_desc != d1)
|
||||||
{
|
{
|
||||||
grub_efi_memory_descriptor_t tmp;
|
grub_efi_memory_descriptor_t tmp;
|
||||||
|
|
||||||
tmp = *d1;
|
tmp = *d1;
|
||||||
*d1 = *min_desc;
|
*d1 = *max_desc;
|
||||||
*min_desc = tmp;
|
*max_desc = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,16 +223,17 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||||
#if GRUB_HOST_SIZEOF_VOID_P < 8
|
#if GRUB_HOST_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->num_pages != 0)
|
&& desc->num_pages != 0)
|
||||||
{
|
{
|
||||||
grub_memcpy (filtered_desc, desc, desc_size);
|
grub_memcpy (filtered_desc, desc, desc_size);
|
||||||
|
|
||||||
/* Avoid the page at the address zero, because this is really
|
/* Avoid less than 1MB, because some loaders seem to be confused. */
|
||||||
confusing for C programs. */
|
if (desc->physical_start < 0x100000)
|
||||||
if (filtered_desc->physical_start == 0)
|
|
||||||
{
|
{
|
||||||
filtered_desc->physical_start = 0x1000;
|
desc->num_pages -= BYTES_TO_PAGES (0x100000
|
||||||
filtered_desc->num_pages--;
|
- desc->physical_start);
|
||||||
|
desc->physical_start = 0x100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GRUB_HOST_SIZEOF_VOID_P < 8
|
#if GRUB_HOST_SIZEOF_VOID_P < 8
|
||||||
|
@ -285,16 +286,21 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||||
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||||
{
|
{
|
||||||
grub_efi_uint64_t pages;
|
grub_efi_uint64_t pages;
|
||||||
|
grub_efi_physical_address_t start;
|
||||||
void *addr;
|
void *addr;
|
||||||
|
|
||||||
|
start = desc->physical_start;
|
||||||
pages = desc->num_pages;
|
pages = desc->num_pages;
|
||||||
if (pages > required_pages)
|
if (pages > required_pages)
|
||||||
pages = required_pages;
|
{
|
||||||
|
start += PAGES_TO_BYTES (pages - required_pages);
|
||||||
|
pages = required_pages;
|
||||||
|
}
|
||||||
|
|
||||||
addr = grub_efi_allocate_pages (desc->physical_start, pages);
|
addr = grub_efi_allocate_pages (start, pages);
|
||||||
if (! addr)
|
if (! addr)
|
||||||
grub_fatal ("cannot allocate conventional memory %p with %u pages",
|
grub_fatal ("cannot allocate conventional memory %p with %u pages",
|
||||||
(void *) ((grub_addr_t) desc->physical_start),
|
(void *) ((grub_addr_t) start),
|
||||||
(unsigned) pages);
|
(unsigned) pages);
|
||||||
|
|
||||||
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
|
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
|
||||||
|
@ -308,6 +314,27 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||||
grub_fatal ("too little memory");
|
grub_fatal ("too little memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Print the memory map. */
|
||||||
|
static void
|
||||||
|
print_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||||
|
grub_efi_uintn_t desc_size,
|
||||||
|
grub_efi_memory_descriptor_t *memory_map_end)
|
||||||
|
{
|
||||||
|
grub_efi_memory_descriptor_t *desc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (desc = memory_map, i = 0;
|
||||||
|
desc < memory_map_end;
|
||||||
|
desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size), i++)
|
||||||
|
{
|
||||||
|
grub_printf ("MD: t=%x, p=%llx, v=%llx, n=%llx, a=%llx\n",
|
||||||
|
desc->type, desc->physical_start, desc->virtual_start,
|
||||||
|
desc->num_pages, desc->attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_efi_mm_init (void)
|
grub_efi_mm_init (void)
|
||||||
{
|
{
|
||||||
|
@ -363,6 +390,19 @@ grub_efi_mm_init (void)
|
||||||
/* Allocate memory regions for GRUB's memory management. */
|
/* Allocate memory regions for GRUB's memory management. */
|
||||||
add_memory_regions (filtered_memory_map, desc_size,
|
add_memory_regions (filtered_memory_map, desc_size,
|
||||||
filtered_memory_map_end, required_pages);
|
filtered_memory_map_end, required_pages);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* For debug. */
|
||||||
|
map_size = MEMORY_MAP_SIZE;
|
||||||
|
|
||||||
|
if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0)
|
||||||
|
grub_fatal ("cannot get memory map");
|
||||||
|
|
||||||
|
grub_printf ("printing memory map\n");
|
||||||
|
print_memory_map (memory_map, desc_size,
|
||||||
|
NEXT_MEMORY_DESCRIPTOR (memory_map, map_size));
|
||||||
|
grub_abort ();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Release the memory maps. */
|
/* Release the memory maps. */
|
||||||
grub_efi_free_pages ((grub_addr_t) memory_map,
|
grub_efi_free_pages ((grub_addr_t) memory_map,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc.
|
* Copyright (C) 2002,2003,2004,2006 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software; you can redistribute it and/or modify
|
* GRUB is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
static grub_err_t (*grub_loader_boot_func) (void);
|
static grub_err_t (*grub_loader_boot_func) (void);
|
||||||
static grub_err_t (*grub_loader_unload_func) (void);
|
static grub_err_t (*grub_loader_unload_func) (void);
|
||||||
|
static int grub_loader_noreturn;
|
||||||
|
|
||||||
static int grub_loader_loaded;
|
static int grub_loader_loaded;
|
||||||
|
|
||||||
|
@ -36,14 +37,16 @@ grub_loader_is_loaded (void)
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_loader_set (grub_err_t (*boot) (void),
|
grub_loader_set (grub_err_t (*boot) (void),
|
||||||
grub_err_t (*unload) (void))
|
grub_err_t (*unload) (void),
|
||||||
|
int noreturn)
|
||||||
{
|
{
|
||||||
if (grub_loader_loaded && grub_loader_unload_func)
|
if (grub_loader_loaded && grub_loader_unload_func)
|
||||||
grub_loader_unload_func ();
|
grub_loader_unload_func ();
|
||||||
|
|
||||||
grub_loader_boot_func = boot;
|
grub_loader_boot_func = boot;
|
||||||
grub_loader_unload_func = unload;
|
grub_loader_unload_func = unload;
|
||||||
|
grub_loader_noreturn = noreturn;
|
||||||
|
|
||||||
grub_loader_loaded = 1;
|
grub_loader_loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +68,8 @@ grub_loader_boot (void)
|
||||||
if (! grub_loader_loaded)
|
if (! grub_loader_loaded)
|
||||||
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
||||||
|
|
||||||
grub_machine_fini ();
|
if (grub_loader_noreturn)
|
||||||
|
grub_machine_fini ();
|
||||||
|
|
||||||
return (grub_loader_boot_func) ();
|
return (grub_loader_boot_func) ();
|
||||||
}
|
}
|
||||||
|
|
315
loader/efi/chainloader.c
Normal file
315
loader/efi/chainloader.c
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
/* chainloader.c - boot another boot loader */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2002,2004,2006 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TODO: support load options. */
|
||||||
|
|
||||||
|
#include <grub/loader.h>
|
||||||
|
#include <grub/file.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/device.h>
|
||||||
|
#include <grub/disk.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/rescue.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/efi/api.h>
|
||||||
|
#include <grub/efi/efi.h>
|
||||||
|
#include <grub/efi/disk.h>
|
||||||
|
#include <grub/efi/chainloader.h>
|
||||||
|
|
||||||
|
static grub_dl_t my_mod;
|
||||||
|
|
||||||
|
static grub_efi_physical_address_t address;
|
||||||
|
static grub_efi_uintn_t pages;
|
||||||
|
static grub_efi_device_path_t *file_path;
|
||||||
|
static grub_efi_handle_t image_handle;
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_chainloader_unload (void)
|
||||||
|
{
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
|
||||||
|
b = grub_efi_system_table->boot_services;
|
||||||
|
b->unload_image (image_handle);
|
||||||
|
b->free_pages (address, pages);
|
||||||
|
grub_free (file_path);
|
||||||
|
|
||||||
|
grub_dl_unref (my_mod);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_chainloader_boot (void)
|
||||||
|
{
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
grub_efi_status_t status;
|
||||||
|
grub_efi_uintn_t exit_data_size;
|
||||||
|
grub_efi_char16_t *exit_data;
|
||||||
|
|
||||||
|
b = grub_efi_system_table->boot_services;
|
||||||
|
status = b->start_image (image_handle, &exit_data_size, &exit_data);
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
if (exit_data)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = grub_malloc (exit_data_size * 4 + 1);
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
*grub_utf16_to_utf8 ((grub_uint8_t *) buf,
|
||||||
|
exit_data, exit_data_size) = 0;
|
||||||
|
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, buf);
|
||||||
|
grub_free (buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, "unknown error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exit_data)
|
||||||
|
b->free_pool (exit_data);
|
||||||
|
|
||||||
|
grub_chainloader_unload ();
|
||||||
|
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||||
|
const char *str, grub_efi_uint16_t len)
|
||||||
|
{
|
||||||
|
grub_efi_char16_t *p;
|
||||||
|
grub_efi_uint16_t size;
|
||||||
|
|
||||||
|
fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
|
||||||
|
fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
|
||||||
|
size = len * sizeof (grub_efi_char16_t) + sizeof (*fp);
|
||||||
|
fp->header.length[0] = (grub_efi_uint8_t) (size & 0xff);
|
||||||
|
fp->header.length[1] = (grub_efi_uint8_t) (size >> 8);
|
||||||
|
for (p = fp->path_name; len > 0; len--, p++, str++)
|
||||||
|
{
|
||||||
|
/* FIXME: this assumes that the path is in ASCII. */
|
||||||
|
*p = (grub_efi_char16_t) (*str == '/' ? '\\' : *str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_efi_device_path_t *
|
||||||
|
make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||||
|
{
|
||||||
|
char *dir_start;
|
||||||
|
char *dir_end;
|
||||||
|
grub_size_t size;
|
||||||
|
grub_efi_device_path_t *d;
|
||||||
|
|
||||||
|
dir_start = grub_strchr (filename, ')');
|
||||||
|
if (! dir_start)
|
||||||
|
dir_start = (char *) filename;
|
||||||
|
else
|
||||||
|
dir_start++;
|
||||||
|
|
||||||
|
dir_end = grub_strrchr (dir_start, '/');
|
||||||
|
if (! dir_end)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FILENAME, "invalid EFI file path");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
d = dp;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
|
||||||
|
if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
|
||||||
|
break;
|
||||||
|
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_path = grub_malloc (size
|
||||||
|
+ ((grub_strlen (dir_start) + 1)
|
||||||
|
* sizeof (grub_efi_char16_t))
|
||||||
|
+ sizeof (grub_efi_file_path_device_path_t) * 2);
|
||||||
|
if (! file_path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
grub_memcpy (file_path, dp, size);
|
||||||
|
|
||||||
|
/* Fill the file path for the directory. */
|
||||||
|
d = (grub_efi_device_path_t *) ((char *) file_path
|
||||||
|
+ ((char *) d - (char *) dp));
|
||||||
|
grub_efi_print_device_path (d);
|
||||||
|
copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||||
|
dir_start, dir_end - dir_start);
|
||||||
|
|
||||||
|
/* Fill the file path for the file. */
|
||||||
|
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||||
|
copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||||
|
dir_end + 1, grub_strlen (dir_end + 1));
|
||||||
|
|
||||||
|
/* Fill the end of device path nodes. */
|
||||||
|
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||||
|
d->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
|
||||||
|
d->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
||||||
|
d->length[0] = sizeof (*d);
|
||||||
|
d->length[1] = 0;
|
||||||
|
|
||||||
|
return file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_chainloader_cmd (const char *filename)
|
||||||
|
{
|
||||||
|
grub_file_t file = 0;
|
||||||
|
grub_ssize_t size;
|
||||||
|
grub_efi_status_t status;
|
||||||
|
grub_efi_boot_services_t *b;
|
||||||
|
grub_efi_handle_t dev_handle = 0;
|
||||||
|
grub_device_t dev = 0;
|
||||||
|
grub_efi_device_path_t *dp = 0;
|
||||||
|
grub_efi_loaded_image_t *loaded_image;
|
||||||
|
|
||||||
|
grub_dl_ref (my_mod);
|
||||||
|
|
||||||
|
/* Initialize some global variables. */
|
||||||
|
address = 0;
|
||||||
|
image_handle = 0;
|
||||||
|
file_path = 0;
|
||||||
|
|
||||||
|
b = grub_efi_system_table->boot_services;
|
||||||
|
|
||||||
|
file = grub_file_open (filename);
|
||||||
|
if (! file)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Get the root device's device path. */
|
||||||
|
dev = grub_device_open (0);
|
||||||
|
if (! dev)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (dev->disk)
|
||||||
|
{
|
||||||
|
dev_handle = grub_efidisk_get_device_handle (dev->disk);
|
||||||
|
if (dev_handle)
|
||||||
|
dp = grub_efi_get_device_path (dev_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! dev->disk || ! dev_handle || ! dp)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_DEVICE, "not a valid root device");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_path = make_file_path (dp, filename);
|
||||||
|
if (! file_path)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
grub_printf ("file path: ");
|
||||||
|
grub_efi_print_device_path (file_path);
|
||||||
|
|
||||||
|
size = grub_file_size (file);
|
||||||
|
pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
|
||||||
|
|
||||||
|
status = b->allocate_pages (GRUB_EFI_ALLOCATE_ANY_PAGES,
|
||||||
|
GRUB_EFI_LOADER_CODE,
|
||||||
|
pages, &address);
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate %u pages", pages);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_file_read (file, (void *) ((grub_addr_t) address), size) != size)
|
||||||
|
{
|
||||||
|
if (grub_errno == GRUB_ERR_NONE)
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, "too small");
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = b->load_image (0, grub_efi_image_handle, file_path,
|
||||||
|
(void *) ((grub_addr_t) address), size,
|
||||||
|
&image_handle);
|
||||||
|
if (status != GRUB_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
if (status == GRUB_EFI_OUT_OF_RESOURCES)
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
|
||||||
|
else
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, "cannot load image");
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LoadImage does not set a device handler when the image is
|
||||||
|
loaded from memory, so it is necessary to set it explicitly here.
|
||||||
|
This is a mess. */
|
||||||
|
loaded_image = grub_efi_get_loaded_image (image_handle);
|
||||||
|
if (! loaded_image)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
loaded_image->device_handle = dev_handle;
|
||||||
|
|
||||||
|
grub_file_close (file);
|
||||||
|
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
|
||||||
|
if (dev)
|
||||||
|
grub_device_close (dev);
|
||||||
|
|
||||||
|
if (file)
|
||||||
|
grub_file_close (file);
|
||||||
|
|
||||||
|
if (file_path)
|
||||||
|
grub_free (file_path);
|
||||||
|
|
||||||
|
if (address)
|
||||||
|
b->free_pages (address, pages);
|
||||||
|
|
||||||
|
grub_dl_unref (my_mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_rescue_cmd_chainloader (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||||
|
else
|
||||||
|
grub_chainloader_cmd (argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char loader_name[] = "chainloader";
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(chainloader)
|
||||||
|
{
|
||||||
|
grub_rescue_register_command (loader_name,
|
||||||
|
grub_rescue_cmd_chainloader,
|
||||||
|
"load another boot loader");
|
||||||
|
my_mod = mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(chainloader)
|
||||||
|
{
|
||||||
|
grub_rescue_unregister_command (loader_name);
|
||||||
|
}
|
49
loader/efi/chainloader_normal.c
Normal file
49
loader/efi/chainloader_normal.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* chainloader_normal.c - boot another boot loader */
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2004,2006 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This program 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 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/efi/chainloader.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/normal.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
chainloader_command (struct grub_arg_list *state __attribute__ ((unused)),
|
||||||
|
int argc, char **args)
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||||
|
else
|
||||||
|
grub_chainloader_cmd (args[0]);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_INIT(chainloader_normal)
|
||||||
|
{
|
||||||
|
(void) mod; /* To stop warning. */
|
||||||
|
grub_register_command ("chainloader", chainloader_command,
|
||||||
|
GRUB_COMMAND_FLAG_BOTH,
|
||||||
|
"chainloader FILE",
|
||||||
|
"Prepare to boot another boot loader.", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI(chainloader_normal)
|
||||||
|
{
|
||||||
|
grub_unregister_command ("chainloader");
|
||||||
|
}
|
|
@ -114,7 +114,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload);
|
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
|
@ -275,7 +275,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
|
||||||
if (grub_errno == GRUB_ERR_NONE)
|
if (grub_errno == GRUB_ERR_NONE)
|
||||||
{
|
{
|
||||||
grub_linux_prot_size = prot_size;
|
grub_linux_prot_size = prot_size;
|
||||||
grub_loader_set (grub_linux_boot, grub_linux_unload);
|
grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
|
||||||
loaded = 1;
|
loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ grub_rescue_cmd_multiboot (int argc, char *argv[])
|
||||||
mbi->flags |= GRUB_MB_INFO_BOOT_LOADER_NAME;
|
mbi->flags |= GRUB_MB_INFO_BOOT_LOADER_NAME;
|
||||||
mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);
|
mbi->boot_loader_name = (grub_uint32_t) grub_strdup (PACKAGE_STRING);
|
||||||
|
|
||||||
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload);
|
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (file)
|
if (file)
|
||||||
|
|
|
@ -250,7 +250,7 @@ grub_rescue_cmd_linux (int argc, char *argv[])
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
grub_loader_set (grub_linux_boot, grub_linux_unload);
|
grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
|
||||||
initrd_addr = 0;
|
initrd_addr = 0;
|
||||||
loaded = 1;
|
loaded = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/term.h>
|
#include <grub/term.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/efi/efi.h>
|
#include <grub/efi/efi.h>
|
||||||
|
@ -70,12 +71,40 @@ grub_console_checkkey (void)
|
||||||
{
|
{
|
||||||
grub_efi_simple_input_interface_t *i;
|
grub_efi_simple_input_interface_t *i;
|
||||||
grub_efi_input_key_t key;
|
grub_efi_input_key_t key;
|
||||||
|
grub_efi_status_t status;
|
||||||
|
|
||||||
if (read_key >= 0)
|
if (read_key >= 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
i = grub_efi_system_table->con_in;
|
i = grub_efi_system_table->con_in;
|
||||||
if (i->read_key_stroke (i, &key) == GRUB_EFI_SUCCESS)
|
status = i->read_key_stroke (i, &key);
|
||||||
|
#if 1
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case GRUB_EFI_SUCCESS:
|
||||||
|
{
|
||||||
|
grub_uint16_t xy;
|
||||||
|
|
||||||
|
xy = grub_getxy ();
|
||||||
|
grub_gotoxy (0, 0);
|
||||||
|
grub_printf ("scan_code=%x,unicode_char=%x ",
|
||||||
|
(unsigned) key.scan_code,
|
||||||
|
(unsigned) key.unicode_char);
|
||||||
|
grub_gotoxy (xy >> 8, xy & 0xff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GRUB_EFI_NOT_READY:
|
||||||
|
//grub_printf ("not ready ");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//grub_printf ("device error ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (status == GRUB_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
switch (key.scan_code)
|
switch (key.scan_code)
|
||||||
{
|
{
|
||||||
|
@ -83,45 +112,41 @@ grub_console_checkkey (void)
|
||||||
read_key = key.unicode_char;
|
read_key = key.unicode_char;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
read_key = GRUB_CONSOLE_KEY_UP;
|
read_key = 16;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
read_key = GRUB_CONSOLE_KEY_DOWN;
|
read_key = 14;
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
read_key = GRUB_CONSOLE_KEY_RIGHT;
|
read_key = 6;
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
read_key = GRUB_CONSOLE_KEY_LEFT;
|
read_key = 2;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
read_key = GRUB_CONSOLE_KEY_HOME;
|
read_key = 1;
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
read_key = GRUB_CONSOLE_KEY_END;
|
read_key = 5;
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
read_key = GRUB_CONSOLE_KEY_IC;
|
|
||||||
break;
|
break;
|
||||||
case 0x08:
|
case 0x08:
|
||||||
read_key = GRUB_CONSOLE_KEY_DC;
|
read_key = 4;
|
||||||
break;
|
break;
|
||||||
case 0x09:
|
case 0x09:
|
||||||
read_key = GRUB_CONSOLE_KEY_PPAGE;
|
|
||||||
break;
|
break;
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
read_key = GRUB_CONSOLE_KEY_NPAGE;
|
break;
|
||||||
case 0x17:
|
case 0x17:
|
||||||
read_key = '\e';
|
read_key = '\e';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return read_key >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -147,7 +172,7 @@ grub_console_getkey (void)
|
||||||
{
|
{
|
||||||
status = b->wait_for_event (1, &(i->wait_for_key), &index);
|
status = 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 ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue