diff --git a/commands/handler.c b/commands/handler.c
new file mode 100644
index 0000000..04f89f8
--- /dev/null
+++ b/commands/handler.c
@@ -0,0 +1,105 @@
+/* handler.c - test module for dynamic loading */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+static grub_err_t
+grub_cmd_handler (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ char *find_name;
+ void *find_result;
+ void *curr_item = 0;
+
+ auto int list_item (grub_handler_class_t item);
+ int list_item (grub_handler_class_t item)
+ {
+ if (item == curr_item)
+ grub_putchar ('*');
+
+ grub_printf ("%s\n", item->name);
+
+ return 0;
+ }
+
+ auto int find_item (grub_handler_class_t item);
+ int find_item (grub_handler_class_t item)
+ {
+ if (! grub_strcmp (item->name, find_name))
+ {
+ find_result = item;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (argc == 0)
+ {
+ grub_handler_class_iterate (list_item);
+ }
+ else
+ {
+ grub_handler_class_t class;
+
+ find_name = args[0];
+ find_result = 0;
+ grub_handler_class_iterate (find_item);
+ if (! find_result)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found");
+
+ class = find_result;
+
+ if (argc == 1)
+ {
+ curr_item = class->cur_handler;
+ grub_handler_iterate (find_result, (grub_list_hook_t) list_item);
+ }
+ else
+ {
+ find_name = args[1];
+ find_result = 0;
+ grub_handler_iterate (class, (grub_list_hook_t) find_item);
+
+ if (! find_result)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found");
+
+ grub_handler_set_current (class, find_result);
+ }
+ }
+
+ return 0;
+}
+
+GRUB_MOD_INIT(handler)
+{
+ (void)mod; /* To stop warning. */
+ grub_register_command ("handler", grub_cmd_handler, GRUB_COMMAND_FLAG_BOTH,
+ "handler [class [handler]]",
+ "List or select a handler", 0);
+}
+
+GRUB_MOD_FINI(handler)
+{
+ grub_unregister_command ("hello");
+}
diff --git a/conf/common.rmk b/conf/common.rmk
index dfd481a..9a62ac3 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -330,7 +330,7 @@ scsi_mod_CFLAGS = $(COMMON_CFLAGS)
scsi_mod_LDFLAGS = $(COMMON_LDFLAGS)
# Commands.
-pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod \
+pkglib_MODULES += hello.mod boot.mod handler.mod ls.mod \
cmp.mod cat.mod help.mod search.mod \
loopback.mod fs_uuid.mod configfile.mod echo.mod \
terminfo.mod test.mod blocklist.mod hexdump.mod \
@@ -346,10 +346,10 @@ boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For terminal.mod.
-terminal_mod_SOURCES = commands/terminal.c
-terminal_mod_CFLAGS = $(COMMON_CFLAGS)
-terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For handler.mod.
+handler_mod_SOURCES = commands/handler.c
+handler_mod_CFLAGS = $(COMMON_CFLAGS)
+handler_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For ls.mod.
ls_mod_SOURCES = commands/ls.c
diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
index f26bf4a..d837281 100644
--- a/conf/i386-coreboot.rmk
+++ b/conf/i386-coreboot.rmk
@@ -17,7 +17,7 @@ kernel_elf_SOURCES = kern/i386/coreboot/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/time.c \
+ kern/time.c kern/list.c kern/handler.c \
kern/i386/dl.c kern/parser.c kern/partition.c \
kern/i386/tsc.c kern/i386/pit.c \
kern/generic/rtc_get_time_ms.c \
@@ -30,7 +30,7 @@ kernel_elf_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
machine/boot.h machine/console.h machine/init.h \
- machine/memory.h machine/loader.h
+ machine/memory.h machine/loader.h list.h handler.h
kernel_elf_CFLAGS = $(COMMON_CFLAGS)
kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x8200,-Bstatic
@@ -57,7 +57,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/echo.c commands/help.c \
- commands/terminal.c commands/ls.c commands/test.c \
+ commands/handler.c commands/ls.c commands/test.c \
commands/search.c commands/blocklist.c commands/hexdump.c \
lib/hexdump.c commands/i386/cpuid.c \
disk/host.c disk/loopback.c \
diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
index dc0547e..fe83f71 100644
--- a/conf/i386-efi.rmk
+++ b/conf/i386-efi.rmk
@@ -34,7 +34,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/help.c \
- commands/terminal.c commands/ls.c commands/test.c \
+ commands/handler.c commands/ls.c commands/test.c \
commands/search.c commands/hexdump.c lib/hexdump.c \
commands/halt.c commands/reboot.c \
commands/i386/cpuid.c \
@@ -87,14 +87,14 @@ kernel_mod_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.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/efi/init.c kern/efi/mm.c \
term/efi/console.c disk/efi/efidisk.c \
- kern/time.c \
+ kern/time.c kern/list.c kern/handler.c \
kern/i386/tsc.c kern/i386/pit.c \
kern/generic/rtc_get_time_ms.c \
kern/generic/millisleep.c
kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
- efi/efi.h efi/time.h efi/disk.h
+ efi/efi.h efi/time.h efi/disk.h list.h handler.h
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
index 90fc2f0..3a8886f 100644
--- a/conf/i386-ieee1275.rmk
+++ b/conf/i386-ieee1275.rmk
@@ -20,7 +20,7 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
kern/i386/dl.c kern/parser.c kern/partition.c \
kern/env.c \
- kern/time.c \
+ kern/time.c kern/list.c kern/handler.c \
kern/generic/millisleep.c \
kern/ieee1275/ieee1275.c \
term/ieee1275/ofconsole.c \
@@ -29,7 +29,8 @@ kernel_elf_SOURCES = kern/i386/ieee1275/startup.S kern/i386/ieee1275/init.c \
kernel_elf_HEADERS = arg.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
- ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h
+ ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \
+ list.h handler.h
kernel_elf_CFLAGS = $(COMMON_CFLAGS)
kernel_elf_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic
@@ -55,7 +56,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/echo.c commands/help.c \
- commands/terminal.c commands/ls.c commands/test.c \
+ commands/handler.c commands/ls.c commands/test.c \
commands/search.c commands/blocklist.c commands/hexdump.c \
lib/hexdump.c commands/halt.c commands/reboot.c \
commands/i386/cpuid.c \
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 2fd03b5..7abfa58 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -42,7 +42,7 @@ cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,7C00
kernel_img_SOURCES = kern/i386/pc/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/time.c \
+ kern/time.c kern/list.c kern/handler.c \
kern/i386/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
kern/parser.c kern/partition.c \
kern/i386/tsc.c kern/i386/pit.c \
@@ -56,7 +56,7 @@ kernel_img_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
- machine/kernel.h machine/pxe.h
+ machine/kernel.h machine/pxe.h list.h handler.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS) -Wl,-Ttext,$(GRUB_MEMORY_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)
@@ -114,7 +114,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/echo.c commands/help.c \
- commands/terminal.c commands/ls.c commands/test.c \
+ commands/handler.c commands/ls.c commands/test.c \
commands/search.c commands/blocklist.c commands/hexdump.c \
lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c \
commands/i386/cpuid.c \
diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
index b48f303..17e92bf 100644
--- a/conf/powerpc-ieee1275.rmk
+++ b/conf/powerpc-ieee1275.rmk
@@ -40,7 +40,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/help.c \
- commands/search.c commands/terminal.c commands/test.c \
+ commands/search.c commands/handler.c commands/test.c \
commands/ls.c commands/blocklist.c commands/hexdump.c \
lib/hexdump.c commands/halt.c commands/reboot.c \
disk/loopback.c \
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index ce133e9..3a28e94 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -44,7 +44,7 @@ grub_mkimage_SOURCES = util/sparc64/ieee1275/grub-mkimage.c util/misc.c \
# For grub-emu
#grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
# commands/configfile.c commands/default.c commands/help.c \
-# commands/search.c commands/terminal.c commands/ls.c \
+# commands/search.c commands/handler.c commands/ls.c \
# commands/timeout.c commands/test.c \
# commands/halt.c commands/reboot.c \
# disk/loopback.c \
@@ -75,8 +75,8 @@ kernel_elf_SOURCES = kern/sparc64/ieee1275/init.c kern/ieee1275/ieee1275.c \
kern/sparc64/ieee1275/openfw.c disk/ieee1275/ofdisk.c \
kern/partition.c kern/env.c kern/sparc64/dl.c symlist.c \
kern/generic/millisleep.c kern/generic/get_time_ms.c \
- kern/sparc64/cache.S kern/parser.c
-kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h
+ kern/sparc64/cache.S kern/parser.c kern/list.c kern/handler.c
+kernel_elf_HEADERS = grub/sparc64/ieee1275/ieee1275.h list.h handler.h
kernel_elf_CFLAGS = $(COMMON_CFLAGS)
kernel_elf_ASFLAGS = $(COMMON_ASFLAGS)
kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-melf64_sparc
@@ -85,7 +85,7 @@ kernel_elf_LDFLAGS = -mno-app-regs -nostdlib -Wl,-N,-Ttext,0x200000,-Bstatic,-me
#_linux.mod linux.mod
pkglib_MODULES = fat.mod ufs.mod ext2.mod minix.mod \
hfs.mod jfs.mod normal.mod hello.mod font.mod ls.mod \
- boot.mod cmp.mod cat.mod terminal.mod fshelp.mod amiga.mod apple.mod \
+ boot.mod cmp.mod cat.mod handler.mod fshelp.mod amiga.mod apple.mod \
pc.mod suspend.mod loopback.mod help.mod reboot.mod halt.mod sun.mod \
configfile.mod search.mod gzio.mod xfs.mod \
affs.mod sfs.mod acorn.mod
@@ -185,10 +185,10 @@ boot_mod_SOURCES = commands/boot.c
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
-# For terminal.mod.
-terminal_mod_SOURCES = commands/terminal.c
-terminal_mod_CFLAGS = $(COMMON_CFLAGS)
-terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For handler.mod.
+handler_mod_SOURCES = commands/handler.c
+handler_mod_CFLAGS = $(COMMON_CFLAGS)
+handler_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For ls.mod.
ls_mod_SOURCES = commands/ls.c
diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
index 973260b..66b3d1a 100644
--- a/conf/x86_64-efi.rmk
+++ b/conf/x86_64-efi.rmk
@@ -36,7 +36,7 @@ grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c
util/grub-emu.c_DEPENDENCIES = grub_emu_init.h
grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \
commands/configfile.c commands/help.c \
- commands/terminal.c commands/ls.c commands/test.c \
+ commands/handler.c commands/ls.c commands/test.c \
commands/search.c commands/hexdump.c lib/hexdump.c \
commands/halt.c commands/reboot.c \
commands/i386/cpuid.c \
@@ -89,14 +89,14 @@ kernel_mod_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
kern/x86_64/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
- kern/time.c \
+ kern/time.c kern/list.c kern/handler.c \
kern/i386/tsc.c kern/i386/pit.c \
kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c \
term/efi/console.c disk/efi/efidisk.c
kernel_mod_HEADERS = arg.h boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h pc_partition.h rescue.h symbol.h term.h time.h types.h \
- efi/efi.h efi/time.h efi/disk.h machine/loader.h
+ efi/efi.h efi/time.h efi/disk.h machine/loader.h list.h handler.h
kernel_mod_CFLAGS = $(COMMON_CFLAGS)
kernel_mod_ASFLAGS = $(COMMON_ASFLAGS)
kernel_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff --git a/include/grub/handler.h b/include/grub/handler.h
new file mode 100644
index 0000000..26c98d3
--- /dev/null
+++ b/include/grub/handler.h
@@ -0,0 +1,69 @@
+/* handler.h - header for grub handler */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_HANDLER_HEADER
+#define GRUB_HANDLER_HEADER 1
+
+#include
+#include
+
+struct grub_handler
+{
+ struct grub_handler *next;
+ const char *name;
+ grub_err_t (*init) (void);
+ grub_err_t (*fini) (void);
+};
+typedef struct grub_handler *grub_handler_t;
+
+struct grub_handler_class
+{
+ struct grub_handler_class *next;
+ const char *name;
+ grub_list_t handler_list;
+ struct grub_handler *cur_handler;
+};
+typedef struct grub_handler_class *grub_handler_class_t;
+
+void EXPORT_FUNC(grub_handler_class_register) (grub_handler_class_t class);
+void EXPORT_FUNC(grub_handler_class_unregister) (grub_handler_class_t class);
+void EXPORT_FUNC(grub_handler_class_iterate) (int (*hook)
+ (grub_handler_class_t item));
+
+void EXPORT_FUNC(grub_handler_register) (grub_handler_class_t class,
+ void *handler);
+void EXPORT_FUNC(grub_handler_unregister) (grub_handler_class_t class,
+ void *handler);
+void EXPORT_FUNC(grub_handler_iterate) (grub_handler_class_t class,
+ grub_list_hook_t hook);
+grub_err_t EXPORT_FUNC(grub_handler_set_current) (grub_handler_class_t class,
+ void *handler);
+void * EXPORT_FUNC(grub_handler_get_current) (grub_handler_class_t class);
+
+#define GRUB_ASSERT_IS_HANDLER(type) \
+ { \
+ struct type t1; \
+ struct grub_handler t2; \
+ GRUB_ASSERT_CHECK_FIELD (next); \
+ GRUB_ASSERT_CHECK_FIELD (name); \
+ GRUB_ASSERT_CHECK_FIELD (init); \
+ GRUB_ASSERT_CHECK_FIELD (fini); \
+ }
+
+#endif /* ! GRUB_HANDLER_HEADER */
diff --git a/include/grub/list.h b/include/grub/list.h
new file mode 100644
index 0000000..7620937
--- /dev/null
+++ b/include/grub/list.h
@@ -0,0 +1,56 @@
+/* list.h - header for grub list */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#ifndef GRUB_LIST_HEADER
+#define GRUB_LIST_HEADER 1
+
+#include
+#include
+
+struct grub_list
+{
+ struct grub_list *next;
+};
+typedef struct grub_list *grub_list_t;
+
+typedef int (*grub_list_hook_t) (grub_list_t item);
+
+void EXPORT_FUNC(grub_list_push) (grub_list_t *head, void *item);
+void * EXPORT_FUNC(grub_list_pop) (grub_list_t *head);
+void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, void *item);
+void EXPORT_FUNC(grub_list_iterate) (grub_list_t head,
+ grub_list_hook_t hook);
+
+/* This function doesn't exist, so if assertion is false for some reason, the
+ linker would fail. */
+extern void grub_assert_fail (void);
+
+#define GRUB_ASSERT_CHECK_FIELD(field) \
+ if ((char *) &t1. field - (char *) &t1 != \
+ (char *) &t2. field - (char *) &t2) \
+ grub_assert_fail ();
+
+#define GRUB_ASSERT_IS_LIST(type) \
+ { \
+ struct type t1; \
+ struct grub_list t2; \
+ GRUB_ASSERT_CHECK_FIELD (next); \
+ }
+
+#endif /* ! GRUB_LIST_HEADER */
diff --git a/include/grub/term.h b/include/grub/term.h
index 13835bb..fbe890d 100644
--- a/include/grub/term.h
+++ b/include/grub/term.h
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
/* These are used to represent the various color states we use. */
typedef enum
@@ -139,6 +140,9 @@ grub_term_color_state;
struct grub_term_input
{
+ /* The next terminal. */
+ struct grub_term_input *next;
+
/* The terminal name. */
const char *name;
@@ -153,14 +157,14 @@ struct grub_term_input
/* Get a character. */
int (*getkey) (void);
-
- /* The next terminal. */
- struct grub_term_input *next;
};
typedef struct grub_term_input *grub_term_input_t;
struct grub_term_output
{
+ /* The next terminal. */
+ struct grub_term_output *next;
+
/* The terminal name. */
const char *name;
@@ -208,24 +212,9 @@ struct grub_term_output
/* The feature flags defined above. */
grub_uint32_t flags;
-
- /* The next terminal. */
- struct grub_term_output *next;
};
typedef struct grub_term_output *grub_term_output_t;
-void EXPORT_FUNC(grub_term_register_input) (grub_term_input_t term);
-void EXPORT_FUNC(grub_term_register_output) (grub_term_output_t term);
-void EXPORT_FUNC(grub_term_unregister_input) (grub_term_input_t term);
-void EXPORT_FUNC(grub_term_unregister_output) (grub_term_output_t term);
-void EXPORT_FUNC(grub_term_iterate_input) (int (*hook) (grub_term_input_t term));
-void EXPORT_FUNC(grub_term_iterate_output) (int (*hook) (grub_term_output_t term));
-
-grub_err_t EXPORT_FUNC(grub_term_set_current_input) (grub_term_input_t term);
-grub_err_t EXPORT_FUNC(grub_term_set_current_output) (grub_term_output_t term);
-grub_term_input_t EXPORT_FUNC(grub_term_get_current_input) (void);
-grub_term_output_t EXPORT_FUNC(grub_term_get_current_output) (void);
-
void EXPORT_FUNC(grub_putchar) (int c);
void EXPORT_FUNC(grub_putcode) (grub_uint32_t code);
grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code);
@@ -248,6 +237,15 @@ void EXPORT_FUNC(grub_set_more) (int onoff);
/* For convenience. */
#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff)
+extern struct grub_handler_class EXPORT_VAR(grub_term_input_class);
+extern struct grub_handler_class EXPORT_VAR(grub_term_output_class);
+
+#define grub_cur_term_input \
+ ((grub_term_input_t) grub_term_input_class.cur_handler)
+
+#define grub_cur_term_output \
+ ((grub_term_output_t) grub_term_output_class.cur_handler)
+
#endif /* ! ASM_FILE */
#endif /* ! GRUB_TERM_HEADER */
diff --git a/kern/handler.c b/kern/handler.c
new file mode 100644
index 0000000..203d7b0
--- /dev/null
+++ b/kern/handler.c
@@ -0,0 +1,88 @@
+/* handler.c - grub handler function*/
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+
+static grub_list_t grub_handler_class_list;
+
+void
+grub_handler_class_register (grub_handler_class_t class)
+{
+ GRUB_ASSERT_IS_LIST (grub_handler_class);
+ grub_list_push (&grub_handler_class_list, class);
+}
+
+void
+grub_handler_class_unregister (grub_handler_class_t class)
+{
+ grub_list_remove (&grub_handler_class_list, class);
+}
+
+void
+grub_handler_class_iterate (int (*hook) (grub_handler_class_t item))
+{
+ grub_list_iterate (grub_handler_class_list, (grub_list_hook_t) hook);
+}
+
+void
+grub_handler_register (grub_handler_class_t class, void *handler)
+{
+ int first_handler = (class->cur_handler == 0);
+
+ GRUB_ASSERT_IS_LIST (grub_handler);
+ grub_list_push (&class->handler_list, handler);
+
+ if (first_handler)
+ grub_handler_set_current (class, handler);
+}
+
+void
+grub_handler_unregister (grub_handler_class_t class, void *handler)
+{
+ grub_list_remove (&class->handler_list, handler);
+}
+
+void
+grub_handler_iterate (grub_handler_class_t class, grub_list_hook_t hook)
+{
+ grub_list_iterate (class->handler_list, hook);
+}
+
+grub_err_t
+grub_handler_set_current (grub_handler_class_t class, void *handler)
+{
+ grub_handler_t new_handler = handler;
+
+ if (class->cur_handler && class->cur_handler->fini)
+ if ((class->cur_handler->fini) () != GRUB_ERR_NONE)
+ return grub_errno;
+
+ if (new_handler->init)
+ if ((new_handler->init) () != GRUB_ERR_NONE)
+ return grub_errno;
+
+ class->cur_handler = new_handler;
+ return GRUB_ERR_NONE;
+}
+
+void *
+grub_handler_get_current (grub_handler_class_t class)
+{
+ return class->cur_handler;
+}
diff --git a/kern/list.c b/kern/list.c
new file mode 100644
index 0000000..cdeeecf
--- /dev/null
+++ b/kern/list.c
@@ -0,0 +1,62 @@
+/* list.c - grub list function*/
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see .
+ */
+
+#include
+
+void
+grub_list_push (grub_list_t *head, void *item)
+{
+ ((grub_list_t) item)->next = *head;
+ *head = item;
+}
+
+void *
+grub_list_pop (grub_list_t *head)
+{
+ grub_list_t item;
+
+ item = *head;
+ if (item)
+ *head = item->next;
+
+ return item;
+}
+
+void
+grub_list_remove (grub_list_t *head, void *item)
+{
+ grub_list_t *p, q;
+
+ for (p = head, q = *p; q; p = &(q->next), q = q->next)
+ if (q == item)
+ {
+ *p = q->next;
+ break;
+ }
+}
+
+void
+grub_list_iterate (grub_list_t head, grub_list_hook_t hook)
+{
+ grub_list_t p;
+
+ for (p = head; p; p = p->next)
+ if (hook (p))
+ break;
+}
diff --git a/kern/main.c b/kern/main.c
index 40300b2..000374c 100644
--- a/kern/main.c
+++ b/kern/main.c
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
void
grub_module_iterate (int (*hook) (struct grub_module_header *header))
@@ -60,7 +61,7 @@ grub_load_modules (void)
{
/* Not an ELF module, skip. */
if (header->type != OBJ_TYPE_ELF)
- return 0;
+ return 0;
if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
(header->size - sizeof (struct grub_module_header))))
@@ -126,6 +127,12 @@ grub_load_normal_mode (void)
void
grub_main (void)
{
+ /* Register handler classes. */
+ GRUB_ASSERT_IS_HANDLER(grub_term_input);
+ GRUB_ASSERT_IS_HANDLER(grub_term_output);
+ grub_handler_class_register (&grub_term_input_class);
+ grub_handler_class_register (&grub_term_output_class);
+
/* First of all, initialize the machine. */
grub_machine_init ();
diff --git a/kern/misc.c b/kern/misc.c
index 641bd7a..97a61f2 100644
--- a/kern/misc.c
+++ b/kern/misc.c
@@ -1063,11 +1063,11 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
void
grub_abort (void)
{
- if (grub_term_get_current_output ())
+ if (grub_cur_term_output)
{
grub_printf ("\nAborted.");
- if (grub_term_get_current_input ())
+ if (grub_cur_term_input)
{
grub_printf (" Press any key to exit.");
grub_getkey ();
diff --git a/kern/term.c b/kern/term.c
index 8d5a23b..524b79d 100644
--- a/kern/term.c
+++ b/kern/term.c
@@ -21,14 +21,17 @@
#include
#include
#include
+#include
-/* The list of terminals. */
-static grub_term_input_t grub_term_list_input;
-static grub_term_output_t grub_term_list_output;
+struct grub_handler_class grub_term_input_class =
+ {
+ .name = "input"
+ };
-/* The current terminal. */
-static grub_term_input_t grub_cur_term_input;
-static grub_term_output_t grub_cur_term_output;
+struct grub_handler_class grub_term_output_class =
+ {
+ .name = "output"
+ };
/* The amount of lines counted by the pager. */
static int grub_more_lines;
@@ -39,112 +42,6 @@ static int grub_more;
/* The current cursor state. */
static int cursor_state = 1;
-void
-grub_term_register_input (grub_term_input_t term)
-{
- term->next = grub_term_list_input;
- grub_term_list_input = term;
- if (! grub_cur_term_input)
- grub_term_set_current_input (term);
-}
-
-void
-grub_term_register_output (grub_term_output_t term)
-{
- term->next = grub_term_list_output;
- grub_term_list_output = term;
- if (! grub_cur_term_output)
- grub_term_set_current_output (term);
-}
-
-void
-grub_term_unregister_input (grub_term_input_t term)
-{
- grub_term_input_t *p, q;
-
- for (p = &grub_term_list_input, q = *p; q; p = &(q->next), q = q->next)
- if (q == term)
- {
- *p = q->next;
- break;
- }
-}
-
-void
-grub_term_unregister_output (grub_term_output_t term)
-{
- grub_term_output_t *p, q;
-
- for (p = &grub_term_list_output, q = *p; q; p = &(q->next), q = q->next)
- if (q == term)
- {
- *p = q->next;
- break;
- }
-}
-
-void
-grub_term_iterate_input (int (*hook) (grub_term_input_t term))
-{
- grub_term_input_t p;
-
- for (p = grub_term_list_input; p; p = p->next)
- if (hook (p))
- break;
-}
-
-void
-grub_term_iterate_output (int (*hook) (grub_term_output_t term))
-{
- grub_term_output_t p;
-
- for (p = grub_term_list_output; p; p = p->next)
- if (hook (p))
- break;
-}
-
-grub_err_t
-grub_term_set_current_input (grub_term_input_t term)
-{
- if (grub_cur_term_input && grub_cur_term_input->fini)
- if ((grub_cur_term_input->fini) () != GRUB_ERR_NONE)
- return grub_errno;
-
- if (term->init)
- if ((term->init) () != GRUB_ERR_NONE)
- return grub_errno;
-
- grub_cur_term_input = term;
- return GRUB_ERR_NONE;
-}
-
-grub_err_t
-grub_term_set_current_output (grub_term_output_t term)
-{
- if (grub_cur_term_output && grub_cur_term_output->fini)
- if ((grub_cur_term_output->fini) () != GRUB_ERR_NONE)
- return grub_errno;
-
- if (term->init)
- if ((term->init) () != GRUB_ERR_NONE)
- return grub_errno;
-
- grub_cur_term_output = term;
- return GRUB_ERR_NONE;
-}
-
-grub_term_input_t
-grub_term_get_current_input (void)
-{
- return grub_cur_term_input;
-}
-
-grub_term_output_t
-grub_term_get_current_output (void)
-{
- return grub_cur_term_output;
-}
-
/* Put a Unicode character. */
void
grub_putcode (grub_uint32_t code)
diff --git a/term/efi/console.c b/term/efi/console.c
index 0bf2449..0974fdf 100644
--- a/term/efi/console.c
+++ b/term/efi/console.c
@@ -366,13 +366,13 @@ grub_console_init (void)
return;
}
- grub_term_register_input (&grub_console_term_input);
- grub_term_register_output (&grub_console_term_output);
+ grub_handler_register (&grub_term_output_class, &grub_console_term_output);
+ grub_handler_register (&grub_term_input_class, &grub_console_term_input);
}
void
grub_console_fini (void)
{
- grub_term_unregister_input (&grub_console_term_input);
- grub_term_unregister_output (&grub_console_term_output);
+ grub_handler_unregister (&grub_term_input_class, &grub_console_term_input);
+ grub_handler_unregister (&grub_term_output_class, &grub_console_term_output);
}
diff --git a/term/gfxterm.c b/term/gfxterm.c
index abb1b9e..ad2edec 100644
--- a/term/gfxterm.c
+++ b/term/gfxterm.c
@@ -1164,7 +1164,7 @@ static struct grub_term_output grub_video_term =
GRUB_MOD_INIT(term_gfxterm)
{
my_mod = mod;
- grub_term_register_output (&grub_video_term);
+ grub_handler_register (&grub_term_output_class, &grub_video_term);
grub_register_command ("background_image",
grub_gfxterm_background_image_cmd,
@@ -1177,5 +1177,5 @@ GRUB_MOD_INIT(term_gfxterm)
GRUB_MOD_FINI(term_gfxterm)
{
grub_unregister_command ("bgimage");
- grub_term_unregister_output (&grub_video_term);
+ grub_handler_unregister (&grub_term_output_class, &grub_video_term);
}
diff --git a/term/i386/pc/at_keyboard.c b/term/i386/pc/at_keyboard.c
index ff5246d..5b67303 100644
--- a/term/i386/pc/at_keyboard.c
+++ b/term/i386/pc/at_keyboard.c
@@ -226,10 +226,10 @@ static struct grub_term_input grub_at_keyboard_term =
GRUB_MOD_INIT(at_keyboard)
{
- grub_term_register_input (&grub_at_keyboard_term);
+ grub_handler_register (&grub_term_input_class, &grub_at_keyboard_term);
}
GRUB_MOD_FINI(at_keyboard)
{
- grub_term_unregister_input (&grub_at_keyboard_term);
+ grub_handler_unregister (&grub_term_input_class, &grub_at_keyboard_term);
}
diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c
index 6c6be46..5769fd8 100644
--- a/term/i386/pc/console.c
+++ b/term/i386/pc/console.c
@@ -46,8 +46,8 @@ static struct grub_term_output grub_console_term_output =
void
grub_console_init (void)
{
- grub_term_register_output (&grub_console_term_output);
- grub_term_register_input (&grub_console_term_input);
+ grub_handler_register (&grub_term_output_class, &grub_console_term_output);
+ grub_handler_register (&grub_term_input_class, &grub_console_term_input);
}
void
@@ -55,8 +55,8 @@ grub_console_fini (void)
{
/* This is to make sure the console is restored to text mode before
we boot. */
- grub_term_set_current_output (&grub_console_term_output);
+ grub_handler_set_current (&grub_term_output_class, &grub_console_term_output);
- grub_term_unregister_input (&grub_console_term_input);
- grub_term_unregister_output (&grub_console_term_output);
+ grub_handler_unregister (&grub_term_input_class, &grub_console_term_input);
+ grub_handler_unregister (&grub_term_output_class, &grub_console_term_output);
}
diff --git a/term/i386/pc/serial.c b/term/i386/pc/serial.c
index 03a46ba..5368188 100644
--- a/term/i386/pc/serial.c
+++ b/term/i386/pc/serial.c
@@ -577,8 +577,8 @@ grub_cmd_serial (struct grub_arg_list *state,
/* Register terminal if not yet registered. */
if (registered == 0)
{
- grub_term_register_input (&grub_serial_term_input);
- grub_term_register_output (&grub_serial_term_output);
+ grub_handler_register (&grub_term_input_class, &grub_serial_term_input);
+ grub_handler_register (&grub_term_output_class, &grub_serial_term_output);
registered = 1;
}
}
@@ -593,8 +593,8 @@ grub_cmd_serial (struct grub_arg_list *state,
if (serial_hw_init () != GRUB_ERR_NONE)
{
/* If unable to restore settings, unregister terminal. */
- grub_term_unregister_input (&grub_serial_term_input);
- grub_term_unregister_output (&grub_serial_term_output);
+ grub_handler_unregister (&grub_term_input_class, &grub_serial_term_input);
+ grub_handler_unregister (&grub_term_output_class, &grub_serial_term_output);
registered = 0;
}
}
@@ -621,7 +621,7 @@ GRUB_MOD_FINI(serial)
grub_unregister_command ("serial");
if (registered == 1) /* Unregister terminal only if registered. */
{
- grub_term_unregister_input (&grub_serial_term_input);
- grub_term_unregister_output (&grub_serial_term_output);
+ grub_handler_unregister (&grub_term_input_class, &grub_serial_term_input);
+ grub_handler_unregister (&grub_term_output_class, &grub_serial_term_output);
}
}
diff --git a/term/i386/pc/vga.c b/term/i386/pc/vga.c
index d32c86e..2f22c5d 100644
--- a/term/i386/pc/vga.c
+++ b/term/i386/pc/vga.c
@@ -510,10 +510,10 @@ GRUB_MOD_INIT(vga)
#ifndef GRUB_UTIL
my_mod = mod;
#endif
- grub_term_register_output (&grub_vga_term);
+ grub_handler_register (&grub_term_output_class, &grub_vga_term);
}
GRUB_MOD_FINI(vga)
{
- grub_term_unregister_output (&grub_vga_term);
+ grub_handler_unregister (&grub_term_output_class, &grub_vga_term);
}
diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c
index e067ed6..c292cd5 100644
--- a/term/i386/pc/vga_text.c
+++ b/term/i386/pc/vga_text.c
@@ -168,10 +168,10 @@ static struct grub_term_output grub_vga_text_term =
GRUB_MOD_INIT(vga_text)
{
- grub_term_register_output (&grub_vga_text_term);
+ grub_handler_register (&grub_term_output_class, &grub_vga_text_term);
}
GRUB_MOD_FINI(vga_text)
{
- grub_term_unregister_output (&grub_vga_text_term);
+ grub_handler_unregister (&grub_term_output_class, &grub_vga_text_term);
}
diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c
index 70fda9a..54bc2cc 100644
--- a/term/ieee1275/ofconsole.c
+++ b/term/ieee1275/ofconsole.c
@@ -420,13 +420,13 @@ static struct grub_term_output grub_ofconsole_term_output =
void
grub_console_init (void)
{
- grub_term_register_input (&grub_ofconsole_term_input);
- grub_term_register_output (&grub_ofconsole_term_output);
+ grub_handler_register (&grub_term_output_class, &grub_ofconsole_term_output);
+ grub_handler_register (&grub_term_input_class, &grub_ofconsole_term_input);
}
void
grub_console_fini (void)
{
- grub_term_unregister_input (&grub_ofconsole_term_input);
- grub_term_unregister_output (&grub_ofconsole_term_output);
+ grub_handler_unregister (&grub_term_input_class, &grub_ofconsole_term_input);
+ grub_handler_unregister (&grub_term_output_class, &grub_ofconsole_term_output);
}
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index 475d12d..18f5725 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
@@ -28,6 +29,9 @@
#include
#include
+struct grub_handler_class grub_term_input_class;
+struct grub_handler_class grub_term_output_class;
+
void
grub_putchar (int c)
{
@@ -40,18 +44,6 @@ grub_refresh (void)
fflush (stdout);
}
-void *
-grub_term_get_current_input (void)
-{
- return 0;
-}
-
-void *
-grub_term_get_current_output (void)
-{
- return 0;
-}
-
int
grub_getkey (void)
{
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
index ca25425..720734a 100644
--- a/util/grub-fstest.c
+++ b/util/grub-fstest.c
@@ -41,6 +41,9 @@
#include
#include
+struct grub_handler_class grub_term_input_class;
+struct grub_handler_class grub_term_output_class;
+
void
grub_putchar (int c)
{
@@ -53,18 +56,6 @@ grub_getkey (void)
return -1;
}
-grub_term_input_t
-grub_term_get_current_input (void)
-{
- return 0;
-}
-
-grub_term_output_t
-grub_term_get_current_output (void)
-{
- return 0;
-}
-
void
grub_refresh (void)
{
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 402b758..d2b5128 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -54,6 +54,9 @@ enum {
int print = PRINT_FS;
static unsigned int argument_is_device = 0;
+struct grub_handler_class grub_term_input_class;
+struct grub_handler_class grub_term_output_class;
+
void
grub_putchar (int c)
{
@@ -66,18 +69,6 @@ grub_getkey (void)
return -1;
}
-grub_term_input_t
-grub_term_get_current_input (void)
-{
- return 0;
-}
-
-grub_term_output_t
-grub_term_get_current_output (void)
-{
- return 0;
-}
-
void
grub_refresh (void)
{
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index ccbb465..3b8f446 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -62,6 +62,9 @@ struct boot_blocklist
grub_uint16_t segment;
} __attribute__ ((packed));
+struct grub_handler_class grub_term_input_class;
+struct grub_handler_class grub_term_output_class;
+
void
grub_putchar (int c)
{
@@ -74,18 +77,6 @@ grub_getkey (void)
return -1;
}
-grub_term_input_t
-grub_term_get_current_input (void)
-{
- return 0;
-}
-
-grub_term_output_t
-grub_term_get_current_output (void)
-{
- return 0;
-}
-
void
grub_refresh (void)
{