From 976a4ea0365b7f7f55f8942e0cc39872bd177115 Mon Sep 17 00:00:00 2001 From: okuji Date: Wed, 19 Apr 2006 08:59:44 +0000 Subject: [PATCH] 2006-04-19 Yoshinori K. Okuji * DISTLIST: Added include/grub/efi/console.h, include/grub/efi/time.h, include/grub/i386/efi/kernel.h, kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. * include/grub/efi/console.h: New file. * include/grub/efi/time.h: Likewise. * include/grub/i386/efi/kernel.h: Likewise. * kern/efi/init.c: Likewise. * kern/efi/mm.c: Likewise. * term/efi/console.c: Likewise. * kern/i386/efi/init.c: Do not include grub/machine/time.h. (grub_stop): Removed. (grub_get_rtc): Likewise. (grub_machine_init): Simply call grub_efi_init. (grub_machine_fini): Call grub_efi_fini. * kern/efi/efi.c: Include grub/machine/time.h and grub/term.h. (grub_efi_output_string): Removed. (grub_efi_stall): New function. (grub_stop): Likewise. (grub_get_rtc): Likewise. * include/grub/efi/efi.h (grub_efi_output_string): Removed. (grub_efi_stall): New prototype. (grub_efi_allocate_pages): Likewise. (grub_efi_free_pages): Likewise. (grub_efi_get_memory_map): Likewise. (grub_efi_mm_init): Likewise. (grub_efi_mm_fini): Likewise. (grub_efi_init): Likewise. (grub_efi_fini): Likewise. * include/grub/i386/efi/time.h: Do not include grub/symbol.h. Include grub/efi/time.h. (GRUB_TICKS_PER_SECOND): Removed. (grub_get_rtc): Likewise. * include/grub/efi/api.h (struct grub_efi_memory_descriptor): Added padding. The EFI spec is buggy. (GRUB_EFI_BLACK): New macro. (GRUB_EFI_BLUE): Likewise. (GRUB_EFI_GREEN): Likewise. (GRUB_EFI_CYAN): Likewise. (GRUB_EFI_RED): Likewise. (GRUB_EFI_MAGENTA): Likewise. (GRUB_EFI_BROWN): Likewise. (GRUB_EFI_LIGHTGRAY): Likewise. (GRUB_EFI_BRIGHT): Likewise. (GRUB_EFI_DARKGRAY): Likewise. (GRUB_EFI_LIGHTBLUE): Likewise. (GRUB_EFI_LIGHTGREEN): Likewise. (GRUB_EFI_LIGHTCYAN): Likewise. (GRUB_EFI_LIGHTRED): Likewise. (GRUB_EFI_LIGHTMAGENTA): Likewise. (GRUB_EFI_YELLOW): Likewise. (GRUB_EFI_WHITE): Likewise. (GRUB_EFI_BACKGROUND_BLACK): Likewise. (GRUB_EFI_BACKGROUND_BLUE): Likewise. (GRUB_EFI_BACKGROUND_GREEN): Likewise. (GRUB_EFI_BACKGROUND_CYAN): Likewise. (GRUB_EFI_BACKGROUND_RED): Likewise. (GRUB_EFI_BACKGROUND_MAGENTA): Likewise. (GRUB_EFI_BACKGROUND_BROWN): Likewise. (GRUB_EFI_BACKGROUND_LIGHTGRAY): Likewise. (GRUB_EFI_TEXT_ATTR): Likewise. * conf/i386-efi.rmk (kernel_mod_SOURCES): Added kern/efi/efi.c, kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. (kernel_mod_HEADERS): Added efi/time.h. --- ChangeLog | 73 ++++++ DISTLIST | 6 + conf/i386-efi.mk | 68 +++++- conf/i386-efi.rmk | 5 +- include/grub/efi/api.h | 32 +++ include/grub/efi/console.h | 45 ++++ include/grub/efi/efi.h | 16 +- include/grub/efi/time.h | 32 +++ include/grub/i386/efi/kernel.h | 28 +++ include/grub/i386/efi/time.h | 13 +- kern/efi/efi.c | 47 ++-- kern/efi/init.c | 47 ++++ kern/efi/mm.c | 391 +++++++++++++++++++++++++++++++++ kern/i386/efi/init.c | 20 +- term/efi/console.c | 282 ++++++++++++++++++++++++ 15 files changed, 1053 insertions(+), 52 deletions(-) create mode 100644 include/grub/efi/console.h create mode 100644 include/grub/efi/time.h create mode 100644 include/grub/i386/efi/kernel.h create mode 100644 kern/efi/init.c create mode 100644 kern/efi/mm.c create mode 100644 term/efi/console.c diff --git a/ChangeLog b/ChangeLog index 1a8ab5625..f3d85b551 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,76 @@ +2006-04-19 Yoshinori K. Okuji + + * DISTLIST: Added include/grub/efi/console.h, + include/grub/efi/time.h, include/grub/i386/efi/kernel.h, + kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. + + * include/grub/efi/console.h: New file. + * include/grub/efi/time.h: Likewise. + * include/grub/i386/efi/kernel.h: Likewise. + * kern/efi/init.c: Likewise. + * kern/efi/mm.c: Likewise. + * term/efi/console.c: Likewise. + + * kern/i386/efi/init.c: Do not include grub/machine/time.h. + (grub_stop): Removed. + (grub_get_rtc): Likewise. + (grub_machine_init): Simply call grub_efi_init. + (grub_machine_fini): Call grub_efi_fini. + + * kern/efi/efi.c: Include grub/machine/time.h and grub/term.h. + (grub_efi_output_string): Removed. + (grub_efi_stall): New function. + (grub_stop): Likewise. + (grub_get_rtc): Likewise. + + * include/grub/efi/efi.h (grub_efi_output_string): Removed. + (grub_efi_stall): New prototype. + (grub_efi_allocate_pages): Likewise. + (grub_efi_free_pages): Likewise. + (grub_efi_get_memory_map): Likewise. + (grub_efi_mm_init): Likewise. + (grub_efi_mm_fini): Likewise. + (grub_efi_init): Likewise. + (grub_efi_fini): Likewise. + + * include/grub/i386/efi/time.h: Do not include + grub/symbol.h. Include grub/efi/time.h. + (GRUB_TICKS_PER_SECOND): Removed. + (grub_get_rtc): Likewise. + + * include/grub/efi/api.h (struct grub_efi_memory_descriptor): + Added padding. The EFI spec is buggy. + (GRUB_EFI_BLACK): New macro. + (GRUB_EFI_BLUE): Likewise. + (GRUB_EFI_GREEN): Likewise. + (GRUB_EFI_CYAN): Likewise. + (GRUB_EFI_RED): Likewise. + (GRUB_EFI_MAGENTA): Likewise. + (GRUB_EFI_BROWN): Likewise. + (GRUB_EFI_LIGHTGRAY): Likewise. + (GRUB_EFI_BRIGHT): Likewise. + (GRUB_EFI_DARKGRAY): Likewise. + (GRUB_EFI_LIGHTBLUE): Likewise. + (GRUB_EFI_LIGHTGREEN): Likewise. + (GRUB_EFI_LIGHTCYAN): Likewise. + (GRUB_EFI_LIGHTRED): Likewise. + (GRUB_EFI_LIGHTMAGENTA): Likewise. + (GRUB_EFI_YELLOW): Likewise. + (GRUB_EFI_WHITE): Likewise. + (GRUB_EFI_BACKGROUND_BLACK): Likewise. + (GRUB_EFI_BACKGROUND_BLUE): Likewise. + (GRUB_EFI_BACKGROUND_GREEN): Likewise. + (GRUB_EFI_BACKGROUND_CYAN): Likewise. + (GRUB_EFI_BACKGROUND_RED): Likewise. + (GRUB_EFI_BACKGROUND_MAGENTA): Likewise. + (GRUB_EFI_BACKGROUND_BROWN): Likewise. + (GRUB_EFI_BACKGROUND_LIGHTGRAY): Likewise. + (GRUB_EFI_TEXT_ATTR): Likewise. + + * conf/i386-efi.rmk (kernel_mod_SOURCES): Added kern/efi/efi.c, + kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. + (kernel_mod_HEADERS): Added efi/time.h. + 2006-04-18 Yoshinori K. Okuji * DISTLIST: Added conf/i386-efi.mk, conf/i386-efi.rmk, diff --git a/DISTLIST b/DISTLIST index adf6f88cb..c28486454 100644 --- a/DISTLIST +++ b/DISTLIST @@ -112,11 +112,14 @@ include/grub/tparm.h include/grub/types.h include/grub/video.h include/grub/efi/api.h +include/grub/efi/console.h include/grub/efi/console_control.h include/grub/efi/efi.h include/grub/efi/pe32.h +include/grub/efi/time.h include/grub/i386/setjmp.h include/grub/i386/types.h +include/grub/i386/efi/kernel.h include/grub/i386/efi/time.h include/grub/i386/pc/biosdisk.h include/grub/i386/pc/boot.h @@ -173,7 +176,9 @@ kern/parser.c kern/partition.c kern/rescue.c kern/term.c +kern/efi/init.c kern/efi/efi.c +kern/efi/mm.c kern/i386/dl.c kern/i386/efi/init.c kern/i386/efi/startup.S @@ -224,6 +229,7 @@ partmap/sun.c term/terminfo.c term/tparm.c term/gfxterm.c +term/efi/console.c term/i386/pc/console.c term/i386/pc/serial.c term/i386/pc/vesafb.c diff --git a/conf/i386-efi.mk b/conf/i386-efi.mk index 9f0fbde72..5edf40409 100644 --- a/conf/i386-efi.mk +++ b/conf/i386-efi.mk @@ -119,13 +119,14 @@ kernel_mod_SOURCES = kern/i386/efi/startup.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/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ - kern/env.c symlist.c kern/efi/efi.c -CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o und-kernel.lst + kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ + term/efi/console.c +CLEANFILES += kernel.mod mod-kernel.o mod-kernel.c pre-kernel.o kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o und-kernel.lst ifneq ($(kernel_mod_EXPORTS),no) CLEANFILES += def-kernel.lst DEFSYMFILES += def-kernel.lst endif -MOSTLYCLEANFILES += kernel_mod-kern_i386_efi_startup.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_i386_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d +MOSTLYCLEANFILES += kernel_mod-kern_i386_efi_startup.d kernel_mod-kern_main.d kernel_mod-kern_device.d kernel_mod-kern_disk.d kernel_mod-kern_dl.d kernel_mod-kern_file.d kernel_mod-kern_fs.d kernel_mod-kern_err.d kernel_mod-kern_misc.d kernel_mod-kern_mm.d kernel_mod-kern_loader.d kernel_mod-kern_rescue.d kernel_mod-kern_term.d kernel_mod-kern_i386_dl.d kernel_mod-kern_i386_efi_init.d kernel_mod-kern_parser.d kernel_mod-kern_partition.d kernel_mod-kern_env.d kernel_mod-symlist.d kernel_mod-kern_efi_efi.d kernel_mod-kern_efi_init.d kernel_mod-kern_efi_mm.d kernel_mod-term_efi_console.d UNDSYMFILES += und-kernel.lst kernel.mod: pre-kernel.o mod-kernel.o @@ -133,7 +134,7 @@ kernel.mod: pre-kernel.o mod-kernel.o $(LD) $(kernel_mod_LDFLAGS) $(LDFLAGS) -r -d -o $@ $^ $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ -pre-kernel.o: kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o +pre-kernel.o: kernel_mod-kern_i386_efi_startup.o kernel_mod-kern_main.o kernel_mod-kern_device.o kernel_mod-kern_disk.o kernel_mod-kern_dl.o kernel_mod-kern_file.o kernel_mod-kern_fs.o kernel_mod-kern_err.o kernel_mod-kern_misc.o kernel_mod-kern_mm.o kernel_mod-kern_loader.o kernel_mod-kern_rescue.o kernel_mod-kern_term.o kernel_mod-kern_i386_dl.o kernel_mod-kern_i386_efi_init.o kernel_mod-kern_parser.o kernel_mod-kern_partition.o kernel_mod-kern_env.o kernel_mod-symlist.o kernel_mod-kern_efi_efi.o kernel_mod-kern_efi_init.o kernel_mod-kern_efi_mm.o kernel_mod-term_efi_console.o -rm -f $@ $(LD) $(kernel_mod_LDFLAGS) -r -d -o $@ $^ @@ -532,10 +533,67 @@ fs-kernel_mod-kern_efi_efi.lst: kern/efi/efi.c genfslist.sh set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) +kernel_mod-kern_efi_init.o: kern/efi/init.c + $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $< + +kernel_mod-kern_efi_init.d: kern/efi/init.c + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -M $< | sed 's,init\.o[ :]*,kernel_mod-kern_efi_init.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_mod-kern_efi_init.d + +CLEANFILES += cmd-kernel_mod-kern_efi_init.lst fs-kernel_mod-kern_efi_init.lst +COMMANDFILES += cmd-kernel_mod-kern_efi_init.lst +FSFILES += fs-kernel_mod-kern_efi_init.lst + +cmd-kernel_mod-kern_efi_init.lst: kern/efi/init.c gencmdlist.sh + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1) + +fs-kernel_mod-kern_efi_init.lst: kern/efi/init.c genfslist.sh + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) + + +kernel_mod-kern_efi_mm.o: kern/efi/mm.c + $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $< + +kernel_mod-kern_efi_mm.d: kern/efi/mm.c + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -M $< | sed 's,mm\.o[ :]*,kernel_mod-kern_efi_mm.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_mod-kern_efi_mm.d + +CLEANFILES += cmd-kernel_mod-kern_efi_mm.lst fs-kernel_mod-kern_efi_mm.lst +COMMANDFILES += cmd-kernel_mod-kern_efi_mm.lst +FSFILES += fs-kernel_mod-kern_efi_mm.lst + +cmd-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c gencmdlist.sh + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1) + +fs-kernel_mod-kern_efi_mm.lst: kern/efi/mm.c genfslist.sh + set -e; $(CC) -Ikern/efi -I$(srcdir)/kern/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) + + +kernel_mod-term_efi_console.o: term/efi/console.c + $(CC) -Iterm/efi -I$(srcdir)/term/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -c -o $@ $< + +kernel_mod-term_efi_console.d: term/efi/console.c + set -e; $(CC) -Iterm/efi -I$(srcdir)/term/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -M $< | sed 's,console\.o[ :]*,kernel_mod-term_efi_console.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include kernel_mod-term_efi_console.d + +CLEANFILES += cmd-kernel_mod-term_efi_console.lst fs-kernel_mod-term_efi_console.lst +COMMANDFILES += cmd-kernel_mod-term_efi_console.lst +FSFILES += fs-kernel_mod-term_efi_console.lst + +cmd-kernel_mod-term_efi_console.lst: term/efi/console.c gencmdlist.sh + set -e; $(CC) -Iterm/efi -I$(srcdir)/term/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh kernel > $@ || (rm -f $@; exit 1) + +fs-kernel_mod-term_efi_console.lst: term/efi/console.c genfslist.sh + set -e; $(CC) -Iterm/efi -I$(srcdir)/term/efi $(CPPFLAGS) $(CFLAGS) $(kernel_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh kernel > $@ || (rm -f $@; exit 1) + + 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 \ pc_partition.h rescue.h symbol.h term.h types.h \ - i386/efi/time.h efi/efi.h + i386/efi/time.h efi/efi.h efi/time.h kernel_mod_CFLAGS = $(COMMON_CFLAGS) kernel_mod_ASFLAGS = $(COMMON_ASFLAGS) kernel_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 6805a3ad5..9e93e78d2 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -75,11 +75,12 @@ kernel_mod_SOURCES = kern/i386/efi/startup.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/i386/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ - kern/env.c symlist.c kern/efi/efi.c + kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ + term/efi/console.c 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 \ pc_partition.h rescue.h symbol.h term.h types.h \ - i386/efi/time.h efi/efi.h + i386/efi/time.h efi/efi.h efi/time.h kernel_mod_CFLAGS = $(COMMON_CFLAGS) kernel_mod_ASFLAGS = $(COMMON_ASFLAGS) kernel_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index ef44b9d4c..6de22329e 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -213,9 +213,12 @@ struct grub_efi_guid } __attribute__ ((aligned(8))); typedef struct grub_efi_guid grub_efi_guid_t; +/* XXX although the spec does not specify the padding, this actually + must have the padding! */ struct grub_efi_memory_descriptor { grub_efi_uint32_t type; + grub_efi_uint32_t padding; grub_efi_physical_address_t physical_start; grub_efi_virtual_address_t virtual_start; grub_efi_uint64_t num_pages; @@ -632,6 +635,35 @@ struct grub_efi_simple_text_output_interface }; typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; +#define GRUB_EFI_BLACK 0x00 +#define GRUB_EFI_BLUE 0x01 +#define GRUB_EFI_GREEN 0x02 +#define GRUB_EFI_CYAN 0x03 +#define GRUB_EFI_RED 0x04 +#define GRUB_EFI_MAGENTA 0x05 +#define GRUB_EFI_BROWN 0x06 +#define GRUB_EFI_LIGHTGRAY 0x07 +#define GRUB_EFI_BRIGHT 0x08 +#define GRUB_EFI_DARKGRAY 0x08 +#define GRUB_EFI_LIGHTBLUE 0x09 +#define GRUB_EFI_LIGHTGREEN 0x0A +#define GRUB_EFI_LIGHTCYAN 0x0B +#define GRUB_EFI_LIGHTRED 0x0C +#define GRUB_EFI_LIGHTMAGENTA 0x0D +#define GRUB_EFI_YELLOW 0x0E +#define GRUB_EFI_WHITE 0x0F + +#define GRUB_EFI_BACKGROUND_BLACK 0x00 +#define GRUB_EFI_BACKGROUND_BLUE 0x10 +#define GRUB_EFI_BACKGROUND_GREEN 0x20 +#define GRUB_EFI_BACKGROUND_CYAN 0x30 +#define GRUB_EFI_BACKGROUND_RED 0x40 +#define GRUB_EFI_BACKGROUND_MAGENTA 0x50 +#define GRUB_EFI_BACKGROUND_BROWN 0x60 +#define GRUB_EFI_BACKGROUND_LIGHTGRAY 0x70 + +#define GRUB_EFI_TEXT_ATTR(fg, bg) ((fg) | ((bg) << 4)) + struct grub_efi_system_table { grub_efi_table_header_t hdr; diff --git a/include/grub/efi/console.h b/include/grub/efi/console.h new file mode 100644 index 000000000..95c80a51d --- /dev/null +++ b/include/grub/efi/console.h @@ -0,0 +1,45 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,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_CONSOLE_HEADER +#define GRUB_EFI_CONSOLE_HEADER 1 + +/* Define scan codes. */ +#define GRUB_CONSOLE_KEY_LEFT 0x4B00 +#define GRUB_CONSOLE_KEY_RIGHT 0x4D00 +#define GRUB_CONSOLE_KEY_UP 0x4800 +#define GRUB_CONSOLE_KEY_DOWN 0x5000 +#define GRUB_CONSOLE_KEY_IC 0x5200 +#define GRUB_CONSOLE_KEY_DC 0x5300 +#define GRUB_CONSOLE_KEY_BACKSPACE 0x0008 +#define GRUB_CONSOLE_KEY_HOME 0x4700 +#define GRUB_CONSOLE_KEY_END 0x4F00 +#define GRUB_CONSOLE_KEY_NPAGE 0x4900 +#define GRUB_CONSOLE_KEY_PPAGE 0x5100 + +#include +#include + +/* Initialize the console system. */ +void grub_console_init (void); + +/* Finish the console system. */ +void grub_console_fini (void); + +#endif /* ! GRUB_EFI_CONSOLE_HEADER */ diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index d07ed7d72..1d28f1fd4 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -30,7 +30,21 @@ void *EXPORT_FUNC(grub_efi_locate_protocol) (grub_efi_guid_t *protocol, void *registration); int EXPORT_FUNC(grub_efi_set_text_mode) (int on); void EXPORT_FUNC(grub_efi_exit) (void) __attribute__((noreturn)); -int EXPORT_FUNC(grub_efi_output_string) (const char *str); +void EXPORT_FUNC(grub_efi_stall) (grub_efi_uintn_t microseconds); +void *EXPORT_FUNC(grub_efi_allocate_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +void EXPORT_FUNC(grub_efi_free_pages) (grub_efi_physical_address_t address, + grub_efi_uintn_t pages); +int EXPORT_FUNC(grub_efi_get_memory_map) (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version); + +void grub_efi_mm_init (void); +void grub_efi_mm_fini (void); +void grub_efi_init (void); +void grub_efi_fini (void); /* Variables. */ extern grub_efi_system_table_t *EXPORT_VAR(grub_efi_system_table); diff --git a/include/grub/efi/time.h b/include/grub/efi/time.h new file mode 100644 index 000000000..8527e649b --- /dev/null +++ b/include/grub/efi/time.h @@ -0,0 +1,32 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef GRUB_EFI_TIME_HEADER +#define GRUB_EFI_TIME_HEADER 1 + +#include + +/* This is destined to overflow when one minute passes by. */ +#define GRUB_TICKS_PER_SECOND ((1UL << 31) / 60 / 60 * 2) + +/* Return the real time in ticks. */ +grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void); + +#endif /* ! GRUB_EFI_TIME_HEADER */ diff --git a/include/grub/i386/efi/kernel.h b/include/grub/i386/efi/kernel.h new file mode 100644 index 000000000..de802787e --- /dev/null +++ b/include/grub/i386/efi/kernel.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003 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_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[]; + +#endif /* ! GRUB_MACHINE_KERNEL_HEADER */ + diff --git a/include/grub/i386/efi/time.h b/include/grub/i386/efi/time.h index 885ad498d..4db68ec7e 100644 --- a/include/grub/i386/efi/time.h +++ b/include/grub/i386/efi/time.h @@ -18,14 +18,9 @@ * MA 02110-1301, USA. */ -#ifndef KERNEL_TIME_HEADER -#define KERNEL_TIME_HEADER 1 +#ifndef GRUB_MACHINE_TIME_HEADER +#define GRUB_MACHINE_TIME_HEADER 1 -#include +#include -#define GRUB_TICKS_PER_SECOND 1193 - -/* Return the real time in ticks. */ -grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void); - -#endif /* ! KERNEL_TIME_HEADER */ +#endif /* ! GRUB_MACHINE_TIME_HEADER */ diff --git a/kern/efi/efi.c b/kern/efi/efi.c index 228ded759..299de11c6 100644 --- a/kern/efi/efi.c +++ b/kern/efi/efi.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* The handle of GRUB itself. Filled in by the startup code. */ grub_efi_handle_t grub_efi_image_handle; @@ -75,23 +77,34 @@ grub_efi_exit (void) 0, 0); } -int -grub_efi_output_string (const char *str) +void +grub_efi_stall (grub_efi_uintn_t microseconds) { - grub_efi_simple_text_output_interface_t *o; - grub_size_t len = grub_strlen (str); - grub_efi_char16_t utf16_str[len + 1]; - grub_efi_status_t status; - - /* XXX Assume that STR is all ASCII characters. */ - do - { - utf16_str[len] = str[len]; - } - while (len--); - - o = grub_efi_system_table->con_out; - status = o->output_string (o, utf16_str); - return status >= 0; + grub_efi_system_table->boot_services->stall (microseconds); } +void +grub_stop (void) +{ + grub_printf ("\nPress any key to abort.\n"); + grub_getkey (); + + grub_efi_fini (); + grub_efi_exit (); +} + +grub_uint32_t +grub_get_rtc (void) +{ + grub_efi_time_t time; + grub_efi_runtime_services_t *r; + + r = grub_efi_system_table->runtime_services; + if (r->get_time (&time, 0) != GRUB_EFI_SUCCESS) + /* What is possible in this case? */ + return 0; + + return (((time.minute * 60 + time.second) * 1000 + + time.nanosecond / 1000000) + * GRUB_TICKS_PER_SECOND / 1000); +} diff --git a/kern/efi/init.c b/kern/efi/init.c new file mode 100644 index 000000000..699845970 --- /dev/null +++ b/kern/efi/init.c @@ -0,0 +1,47 @@ +/* init.c - generic EFI initialization and finalization */ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +void +grub_efi_init (void) +{ + /* First of all, initialize the console so that GRUB can display + messages. */ + grub_console_init (); + + /* Initialize the memory management system. */ + grub_efi_mm_init (); + + /* FIXME: this must be set to something meaningful. */ + grub_env_set ("prefix", grub_prefix); +} + +void +grub_efi_fini (void) +{ + grub_efi_mm_fini (); + grub_console_fini (); +} diff --git a/kern/efi/mm.c b/kern/efi/mm.c new file mode 100644 index 000000000..534432c4e --- /dev/null +++ b/kern/efi/mm.c @@ -0,0 +1,391 @@ +/* mm.c - generic EFI memory management */ +/* + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#define NEXT_MEMORY_DESCRIPTOR(desc, size) \ + ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) + +#define BYTES_TO_PAGES(bytes) ((bytes) >> 12) +#define PAGES_TO_BYTES(pages) ((pages) << 12) + +/* The size of a memory map obtained from the firmware. This must be + a multiplier of 4KB. */ +#define MEMORY_MAP_SIZE 0x1000 + +/* Maintain the list of allocated pages. */ +struct allocated_page +{ + grub_efi_physical_address_t addr; + grub_efi_uint64_t num_pages; +}; + +#define ALLOCATED_PAGES_SIZE 0x1000 +#define MAX_ALLOCATED_PAGES \ + (ALLOCATED_PAGES_SIZE / sizeof (struct allocated_page)) + +static struct allocated_page *allocated_pages = 0; + +/* The minimum and maximum heap size for GRUB itself. */ +#define MIN_HEAP_SIZE 0x100000 +#define MAX_HEAP_SIZE (16 * 0x100000) + + +/* Allocate pages. Return the pointer to the first of allocated pages. */ +void * +grub_efi_allocate_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + grub_efi_allocate_type_t type; + grub_efi_status_t status; + grub_efi_boot_services_t *b; + +#if GRUB_HOST_SIZEOF_VOID_P < 8 + /* Limit the memory access to less than 4GB for 32-bit platforms. */ + if (address > 0xffffffff) + return 0; + + if (address == 0) + { + type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; + address = 0xffffffff; + } + else + type = GRUB_EFI_ALLOCATE_ADDRESS; +#else + if (address == 0) + type = GRUB_EFI_ALLOCATE_ANY_PAGES; + else + type = GRUB_EFI_ALLOCATE_ADDRESS; +#endif + + b = grub_efi_system_table->boot_services; + status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address); + if (status != GRUB_EFI_SUCCESS) + return 0; + + if (address == 0) + { + /* Uggh, the address 0 was allocated... This is too annoying, + so reallocate another one. */ + address = 0xffffffff; + status = b->allocate_pages (type, GRUB_EFI_LOADER_DATA, pages, &address); + grub_efi_free_pages (0, pages); + if (status != GRUB_EFI_SUCCESS) + return 0; + } + + if (allocated_pages) + { + unsigned i; + + for (i = 0; i < MAX_ALLOCATED_PAGES; i++) + if (allocated_pages[i].addr == 0) + { + allocated_pages[i].addr = address; + allocated_pages[i].num_pages = pages; + break; + } + + if (i == MAX_ALLOCATED_PAGES) + grub_fatal ("too many page allocations"); + } + + return (void *) ((grub_addr_t) address); +} + +/* Free pages starting from ADDRESS. */ +void +grub_efi_free_pages (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + grub_efi_boot_services_t *b; + + if (allocated_pages + && ((grub_efi_physical_address_t) ((grub_addr_t) allocated_pages) + != address)) + { + unsigned i; + + for (i = 0; i < MAX_ALLOCATED_PAGES; i++) + if (allocated_pages[i].addr == address) + { + allocated_pages[i].addr = 0; + break; + } + } + + b = grub_efi_system_table->boot_services; + b->free_pages (address, pages); +} + +/* Get the memory map as defined in the EFI spec. Return 1 if successful, + return 0 if partial, or return -1 if an error occurs. */ +int +grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, + grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t *map_key, + grub_efi_uintn_t *descriptor_size, + grub_efi_uint32_t *descriptor_version) +{ + grub_efi_status_t status; + grub_efi_boot_services_t *b; + grub_efi_uintn_t key; + grub_efi_uint32_t version; + + /* Allow some parameters to be missing. */ + if (! map_key) + map_key = &key; + if (! descriptor_version) + descriptor_version = &version; + + b = grub_efi_system_table->boot_services; + status = b->get_memory_map (memory_map_size, memory_map, map_key, + descriptor_size, descriptor_version); + if (status == GRUB_EFI_SUCCESS) + return 1; + else if (status == GRUB_EFI_BUFFER_TOO_SMALL) + return 0; + else + return -1; +} + +/* Sort the memory map in place. */ +static void +sort_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 *d1; + grub_efi_memory_descriptor_t *d2; + + for (d1 = memory_map; + d1 < memory_map_end; + d1 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size)) + { + grub_efi_memory_descriptor_t *min_desc = d1; + + for (d2 = NEXT_MEMORY_DESCRIPTOR (d1, desc_size); + d2 < memory_map_end; + d2 = NEXT_MEMORY_DESCRIPTOR (d2, desc_size)) + { + if (min_desc->num_pages > d2->num_pages) + min_desc = d2; + } + + if (min_desc != d1) + { + grub_efi_memory_descriptor_t tmp; + + tmp = *d1; + *d1 = *min_desc; + *min_desc = tmp; + } + } +} + +/* Filter the descriptors. GRUB needs only available memory. */ +static grub_efi_memory_descriptor_t * +filter_memory_map (grub_efi_memory_descriptor_t *memory_map, + grub_efi_memory_descriptor_t *filtered_memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end) +{ + grub_efi_memory_descriptor_t *desc; + grub_efi_memory_descriptor_t *filtered_desc; + + for (desc = memory_map, filtered_desc = filtered_memory_map; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY +#if GRUB_HOST_SIZEOF_VOID_P < 8 + && desc->physical_start <= 0xffffffff +#endif + && desc->num_pages != 0) + { + grub_memcpy (filtered_desc, desc, desc_size); + + /* Avoid the page at the address zero, because this is really + confusing for C programs. */ + if (filtered_desc->physical_start == 0) + { + filtered_desc->physical_start = 0x1000; + filtered_desc->num_pages--; + } + +#if GRUB_HOST_SIZEOF_VOID_P < 8 + if (BYTES_TO_PAGES (filtered_desc->physical_start) + + filtered_desc->num_pages + > BYTES_TO_PAGES (0x100000000LL)) + filtered_desc->num_pages + = (BYTES_TO_PAGES (0x100000000LL) + - BYTES_TO_PAGES (filtered_desc->physical_start)); +#endif + + if (filtered_desc->num_pages == 0) + continue; + + filtered_desc = NEXT_MEMORY_DESCRIPTOR (filtered_desc, desc_size); + } + } + + return filtered_desc; +} + +/* Return the total number of pages. */ +static grub_efi_uint64_t +get_total_pages (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; + grub_efi_uint64_t total = 0; + + for (desc = memory_map; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + total += desc->num_pages; + + return total; +} + +/* Add memory regions. */ +static void +add_memory_regions (grub_efi_memory_descriptor_t *memory_map, + grub_efi_uintn_t desc_size, + grub_efi_memory_descriptor_t *memory_map_end, + grub_efi_uint64_t required_pages) +{ + grub_efi_memory_descriptor_t *desc; + + for (desc = memory_map; + desc < memory_map_end; + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + { + grub_efi_uint64_t pages; + void *addr; + + pages = desc->num_pages; + if (pages > required_pages) + pages = required_pages; + + addr = grub_efi_allocate_pages (desc->physical_start, pages); + if (! addr) + grub_fatal ("cannot allocate conventional memory %p with %u pages", + (void *) ((grub_addr_t) desc->physical_start), + (unsigned) pages); + + grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); + + required_pages -= pages; + if (required_pages == 0) + break; + } + + if (required_pages > 0) + grub_fatal ("too little memory"); +} + +void +grub_efi_mm_init (void) +{ + grub_efi_memory_descriptor_t *memory_map; + grub_efi_memory_descriptor_t *memory_map_end; + grub_efi_memory_descriptor_t *filtered_memory_map; + grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t map_size; + grub_efi_uintn_t desc_size; + grub_efi_uint64_t total_pages; + grub_efi_uint64_t required_pages; + + /* First of all, allocate pages to maintain allocations. */ + allocated_pages + = grub_efi_allocate_pages (0, BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); + if (! allocated_pages) + grub_fatal ("cannot allocate memory"); + + grub_memset (allocated_pages, 0, ALLOCATED_PAGES_SIZE); + + /* Prepare a memory region to store two memory maps. */ + memory_map = grub_efi_allocate_pages (0, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + if (! memory_map) + grub_fatal ("cannot allocate memory"); + + filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE); + + /* Obtain descriptors for available memory. */ + 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"); + + memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, + desc_size, memory_map_end); + + /* By default, request a quarter of the available memory. */ + total_pages = get_total_pages (filtered_memory_map, desc_size, + filtered_memory_map_end); + required_pages = (total_pages >> 2); + if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) + required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); + else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) + required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); + + /* Sort the filtered descriptors, so that GRUB can allocate pages + from smaller regions. */ + sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); + + /* Allocate memory regions for GRUB's memory management. */ + add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, required_pages); + + /* Release the memory maps. */ + grub_efi_free_pages ((grub_addr_t) memory_map, + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); +} + +void +grub_efi_mm_fini (void) +{ + if (allocated_pages) + { + unsigned i; + + for (i = 0; i < MAX_ALLOCATED_PAGES; i++) + { + struct allocated_page *p; + + p = allocated_pages + i; + if (p->addr != 0) + grub_efi_free_pages ((grub_addr_t) p->addr, p->num_pages); + } + + grub_efi_free_pages ((grub_addr_t) allocated_pages, + BYTES_TO_PAGES (ALLOCATED_PAGES_SIZE)); + } +} diff --git a/kern/i386/efi/init.c b/kern/i386/efi/init.c index c19262208..364f78bbd 100644 --- a/kern/i386/efi/init.c +++ b/kern/i386/efi/init.c @@ -27,33 +27,17 @@ #include #include #include -#include - -void -grub_stop (void) -{ - grub_efi_exit (); -} - -grub_uint32_t -grub_get_rtc (void) -{ - return 0; /* FIXME */ -} void grub_machine_init (void) { - grub_efi_set_text_mode (1); - grub_efi_output_string ("test!\r\n"); - - /* Stop immediately at the moment... */ - grub_stop (); + grub_efi_init (); } void grub_machine_fini (void) { + grub_efi_fini (); } void diff --git a/term/efi/console.c b/term/efi/console.c new file mode 100644 index 000000000..e4de7f59a --- /dev/null +++ b/term/efi/console.c @@ -0,0 +1,282 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +static grub_uint8_t +grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW, + GRUB_EFI_BACKGROUND_BLACK); +static grub_uint8_t +grub_console_normal_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_LIGHTGRAY, + GRUB_EFI_BACKGROUND_BLACK); +static grub_uint8_t +grub_console_highlight_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_WHITE, + GRUB_EFI_BACKGROUND_BLACK); + +static int read_key = -1; + +static void +grub_console_putchar (grub_uint32_t c) +{ + grub_efi_char16_t str[2]; + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + + /* For now, do not try to use a surrogate pair. */ + if (c > 0xffff) + c = '?'; + + str[0] = (grub_efi_char16_t) (c & 0xffff); + str[1] = 0; + + /* Should this test be cached? */ + if (c > 0x7f && o->test_string (o, str) != GRUB_EFI_SUCCESS) + return; + + o->output_string (o, str); +} + +static grub_ssize_t +grub_console_getcharwidth (grub_uint32_t c __attribute__ ((unused))) +{ + /* For now, every printable character has the width 1. */ + return 1; +} + +static int +grub_console_checkkey (void) +{ + grub_efi_simple_input_interface_t *i; + grub_efi_input_key_t key; + + if (read_key >= 0) + return 1; + + i = grub_efi_system_table->con_in; + if (i->read_key_stroke (i, &key) == GRUB_EFI_SUCCESS) + { + switch (key.scan_code) + { + case 0x00: + read_key = key.unicode_char; + break; + case 0x01: + read_key = GRUB_CONSOLE_KEY_UP; + break; + case 0x02: + read_key = GRUB_CONSOLE_KEY_DOWN; + break; + case 0x03: + read_key = GRUB_CONSOLE_KEY_RIGHT; + break; + case 0x04: + read_key = GRUB_CONSOLE_KEY_LEFT; + break; + case 0x05: + read_key = GRUB_CONSOLE_KEY_HOME; + break; + case 0x06: + read_key = GRUB_CONSOLE_KEY_END; + break; + case 0x07: + read_key = GRUB_CONSOLE_KEY_IC; + break; + case 0x08: + read_key = GRUB_CONSOLE_KEY_DC; + break; + case 0x09: + read_key = GRUB_CONSOLE_KEY_PPAGE; + break; + case 0x0a: + read_key = GRUB_CONSOLE_KEY_NPAGE; + case 0x17: + read_key = '\e'; + break; + default: + return 0; + } + + return 1; + } + + return 0; +} + +static int +grub_console_getkey (void) +{ + grub_efi_simple_input_interface_t *i; + grub_efi_boot_services_t *b; + grub_efi_uintn_t index; + grub_efi_status_t status; + int key; + + if (read_key >= 0) + { + key = read_key; + read_key = -1; + return key; + } + + i = grub_efi_system_table->con_in; + b = grub_efi_system_table->boot_services; + + do + { + status = b->wait_for_event (1, &(i->wait_for_key), &index); + if (status != GRUB_EFI_SUCCESS) + return -1; + + grub_console_checkkey (); + } + while (read_key < 0); + + key = read_key; + read_key = -1; + return key; +} + +static grub_uint16_t +grub_console_getwh (void) +{ + grub_efi_simple_text_output_interface_t *o; + grub_efi_uintn_t columns, rows; + + o = grub_efi_system_table->con_out; + if (o->query_mode (o, o->mode->mode, &columns, &rows) != GRUB_EFI_SUCCESS) + { + /* Why does this fail? */ + columns = 80; + rows = 25; + } + + return ((columns << 8) | rows); +} + +static grub_uint16_t +grub_console_getxy (void) +{ + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + return ((o->mode->cursor_column << 8) | o->mode->cursor_row); +} + +static void +grub_console_gotoxy (grub_uint8_t x, grub_uint8_t y) +{ + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + o->set_cursor_position (o, x, y); +} + +static void +grub_console_cls (void) +{ + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + o->clear_screen (o); +} + +static void +grub_console_setcolorstate (grub_term_color_state state) +{ + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + + switch (state) { + case GRUB_TERM_COLOR_STANDARD: + o->set_attributes (o, grub_console_standard_color); + break; + case GRUB_TERM_COLOR_NORMAL: + o->set_attributes (o, grub_console_normal_color); + break; + case GRUB_TERM_COLOR_HIGHLIGHT: + o->set_attributes (o, grub_console_highlight_color); + break; + default: + break; + } +} + +static void +grub_console_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color) +{ + grub_console_normal_color = normal_color; + grub_console_highlight_color = highlight_color; +} + +static void +grub_console_setcursor (int on) +{ + grub_efi_simple_text_output_interface_t *o; + + o = grub_efi_system_table->con_out; + o->enable_cursor (o, on); +} + +static struct grub_term grub_console_term = + { + .name = "console", + .init = 0, + .fini = 0, + .putchar = grub_console_putchar, + .getcharwidth = grub_console_getcharwidth, + .checkkey = grub_console_checkkey, + .getkey = grub_console_getkey, + .getwh = grub_console_getwh, + .getxy = grub_console_getxy, + .gotoxy = grub_console_gotoxy, + .cls = grub_console_cls, + .setcolorstate = grub_console_setcolorstate, + .setcolor = grub_console_setcolor, + .setcursor = grub_console_setcursor, + .flags = 0, + .next = 0 + }; + +void +grub_console_init (void) +{ + /* FIXME: it is necessary to consider the case where no console control + is present but the default is already in text mode. */ + if (! grub_efi_set_text_mode (1)) + { + grub_error (GRUB_ERR_BAD_DEVICE, "cannot set text mode"); + return; + } + + grub_term_register (&grub_console_term); + grub_term_set_current (&grub_console_term); +} + +void +grub_console_fini (void) +{ + grub_term_unregister (&grub_console_term); +}