+2006-04-19 Yoshinori K. Okuji <okuji@enbug.org>
+
+ * 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 <okuji@enbug.org>
* DISTLIST: Added conf/i386-efi.mk, conf/i386-efi.rmk,
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
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
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
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
$(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 $@ $^
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)
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)
} __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;
};
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;
--- /dev/null
+/*
+ * 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 <grub/types.h>
+#include <grub/symbol.h>
+
+/* Initialize the console system. */
+void grub_console_init (void);
+
+/* Finish the console system. */
+void grub_console_fini (void);
+
+#endif /* ! GRUB_EFI_CONSOLE_HEADER */
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);
--- /dev/null
+/*
+ * 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 <grub/symbol.h>
+
+/* 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 */
--- /dev/null
+/*
+ * 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 */
+
* 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 <grub/symbol.h>
+#include <grub/efi/time.h>
-#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 */
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/console_control.h>
+#include <grub/machine/time.h>
+#include <grub/term.h>
/* The handle of GRUB itself. Filled in by the startup code. */
grub_efi_handle_t grub_efi_image_handle;
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;
+ grub_efi_system_table->boot_services->stall (microseconds);
+}
- /* XXX Assume that STR is all ASCII characters. */
- do
- {
- utf16_str[len] = str[len];
- }
- while (len--);
+void
+grub_stop (void)
+{
+ grub_printf ("\nPress any key to abort.\n");
+ grub_getkey ();
- o = grub_efi_system_table->con_out;
- status = o->output_string (o, utf16_str);
- return status >= 0;
+ 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);
+}
--- /dev/null
+/* 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 <grub/efi/efi.h>
+#include <grub/efi/console.h>
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/machine/kernel.h>
+
+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 ();
+}
--- /dev/null
+/* 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 <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+
+#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));
+ }
+}
#include <grub/cache.h>
#include <grub/kernel.h>
#include <grub/efi/efi.h>
-#include <grub/machine/time.h>
-
-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
--- /dev/null
+/*
+ * 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 <grub/term.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/efi/efi.h>
+#include <grub/efi/api.h>
+#include <grub/efi/console.h>
+
+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);
+}