diff --git a/commands/handler.c b/commands/handler.c
new file mode 100644
index 0000000..d6c9b70
--- /dev/null
+++ b/commands/handler.c
@@ -0,0 +1,132 @@
+/* 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
+#include
+
+static grub_err_t
+grub_cmd_handler_generic (int argc, char **args, char *class_name)
+{
+ char *find_name;
+ void *find_result;
+ void *curr_item = 0;
+ grub_handler_class_t head;
+
+ auto int list_item (grub_named_list_t item);
+ int list_item (grub_named_list_t item)
+ {
+ if (item == curr_item)
+ grub_putchar ('*');
+
+ grub_printf ("%s\n", item->name);
+
+ return 0;
+ }
+
+ head = grub_handler_class_get_head ();
+ if ((argc == 0) && (class_name == 0))
+ {
+ grub_list_iterate (head, (grub_list_hook_t) list_item);
+ }
+ else
+ {
+ grub_handler_class_t class;
+
+ if (class_name == 0)
+ {
+ class_name = args[0];
+ argc--;
+ args++;
+ }
+
+ class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name);
+ if (! class)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found");
+
+ if (argc == 0)
+ {
+ curr_item = class->cur_handler;
+ grub_list_iterate (class->handler_list,
+ (grub_list_hook_t) list_item);
+ }
+ else
+ {
+ grub_handler_t handler;
+
+ handler =
+ grub_named_list_find (GRUB_AS_NAMED_LIST (class->handler_list),
+ args[0]);
+
+ if (! handler)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found");
+
+ grub_handler_set_current (class, handler);
+ }
+ }
+
+ return 0;
+}
+
+static grub_err_t
+grub_cmd_handler (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ return grub_cmd_handler_generic (argc, args, 0);
+}
+
+static grub_err_t
+grub_cmd_terminal_input (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ return grub_cmd_handler_generic (argc, args, "terminal_input");
+}
+
+static grub_err_t
+grub_cmd_terminal_output (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc, char **args)
+{
+ return grub_cmd_handler_generic (argc, args, "terminal_output");
+}
+
+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_register_command ("terminal_input", grub_cmd_terminal_input,
+ GRUB_COMMAND_FLAG_BOTH,
+ "terminal_input [handler]",
+ "List or select a handler", 0);
+ grub_register_command ("terminal_output", grub_cmd_terminal_output,
+ GRUB_COMMAND_FLAG_BOTH,
+ "terminal_output [handler]",
+ "List or select a handler", 0);
+}
+
+GRUB_MOD_FINI(handler)
+{
+ grub_unregister_command ("terminal_input");
+ grub_unregister_command ("terminal_output");
+ grub_unregister_command ("handler");
+}
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 b97483b..4938665 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 3814abb..7ae9c5e 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 \
@@ -88,14 +88,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 903113e..16a3fba 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 3ef351e..9e83bda 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 51e7c07..bedd4e0 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 640ceda..18c108e 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 \
@@ -76,8 +76,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
@@ -86,7 +86,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
@@ -187,10 +187,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 5b108d2..07bf1a6 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 \
@@ -90,14 +90,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..3808116
--- /dev/null
+++ b/include/grub/handler.h
@@ -0,0 +1,60 @@
+/* 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_handler_t handler_list;
+ grub_handler_t cur_handler;
+};
+typedef struct grub_handler_class *grub_handler_class_t;
+
+grub_handler_class_t EXPORT_FUNC(grub_handler_class_get_head) (void);
+
+void EXPORT_FUNC(grub_handler_register) (grub_handler_class_t class,
+ grub_handler_t handler);
+void EXPORT_FUNC(grub_handler_unregister) (grub_handler_class_t class,
+ grub_handler_t handler);
+grub_err_t EXPORT_FUNC(grub_handler_set_current) (grub_handler_class_t class,
+ grub_handler_t handler);
+
+#define GRUB_AS_HANDLER(ptr) \
+ ((GRUB_FIELD_MATCH (ptr, grub_handler_t, next) && \
+ GRUB_FIELD_MATCH (ptr, grub_handler_t, name) && \
+ GRUB_FIELD_MATCH (ptr, grub_handler_t, init) && \
+ GRUB_FIELD_MATCH (ptr, grub_handler_t, fini)) ? \
+ (grub_handler_t) ptr : grub_assert_fail ())
+
+#endif /* ! GRUB_HANDLER_HEADER */
diff --git a/include/grub/list.h b/include/grub/list.h
new file mode 100644
index 0000000..b2af3b8
--- /dev/null
+++ b/include/grub/list.h
@@ -0,0 +1,69 @@
+/* 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, grub_list_t item);
+void * EXPORT_FUNC(grub_list_pop) (grub_list_t *head);
+void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, grub_list_t 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_FIELD_MATCH(ptr, type, field) \
+ ((char *) &(ptr)->field == (char *) &((type) (ptr))->field)
+
+#define GRUB_AS_LIST(ptr) \
+ (GRUB_FIELD_MATCH (ptr, grub_list_t, next) ? \
+ (grub_list_t) ptr : grub_assert_fail ())
+
+#define GRUB_AS_LIST_P(pptr) \
+ (GRUB_FIELD_MATCH (*pptr, grub_list_t, next) ? \
+ (grub_list_t *) (void *) pptr : grub_assert_fail ())
+
+struct grub_named_list
+{
+ struct grub_named_list *next;
+ const char *name;
+};
+typedef struct grub_named_list *grub_named_list_t;
+
+void * EXPORT_FUNC(grub_named_list_find) (grub_named_list_t head,
+ const char *name);
+
+#define GRUB_AS_NAMED_LIST(ptr) \
+ ((GRUB_FIELD_MATCH (ptr, grub_named_list_t, next) && \
+ GRUB_FIELD_MATCH (ptr, grub_named_list_t, name))? \
+ (grub_named_list_t) ptr : grub_assert_fail ())
+
+#endif /* ! GRUB_LIST_HEADER */
diff --git a/include/grub/term.h b/include/grub/term.h
index 13835bb..8ac8bc5 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,9 +212,6 @@ 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;
@@ -218,8 +219,6 @@ 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);
diff --git a/kern/handler.c b/kern/handler.c
new file mode 100644
index 0000000..b271702
--- /dev/null
+++ b/kern/handler.c
@@ -0,0 +1,70 @@
+/* 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_handler_class_t grub_handler_class_list;
+
+grub_handler_class_t
+grub_handler_class_get_head (void)
+{
+ return grub_handler_class_list;
+}
+
+void
+grub_handler_register (grub_handler_class_t class, grub_handler_t handler)
+{
+ int first_handler = (class->handler_list == 0);
+
+ grub_list_push (GRUB_AS_LIST_P (&class->handler_list),
+ GRUB_AS_LIST (handler));
+
+ if (first_handler)
+ {
+ grub_list_push (GRUB_AS_LIST_P (&grub_handler_class_list),
+ GRUB_AS_LIST (class));
+ grub_handler_set_current (class, handler);
+ }
+}
+
+void
+grub_handler_unregister (grub_handler_class_t class, grub_handler_t handler)
+{
+ grub_list_remove (GRUB_AS_LIST_P (&class->handler_list),
+ GRUB_AS_LIST (handler));
+
+ if (class->handler_list == 0)
+ grub_list_remove (GRUB_AS_LIST_P (&grub_handler_class_list),
+ GRUB_AS_LIST (class));
+}
+
+grub_err_t
+grub_handler_set_current (grub_handler_class_t class, grub_handler_t handler)
+{
+ if (class->cur_handler && class->cur_handler->fini)
+ if ((class->cur_handler->fini) () != GRUB_ERR_NONE)
+ return grub_errno;
+
+ if (handler->init)
+ if ((handler->init) () != GRUB_ERR_NONE)
+ return grub_errno;
+
+ class->cur_handler = handler;
+ return GRUB_ERR_NONE;
+}
diff --git a/kern/list.c b/kern/list.c
new file mode 100644
index 0000000..b22218e
--- /dev/null
+++ b/kern/list.c
@@ -0,0 +1,84 @@
+/* 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
+#include
+
+void
+grub_list_push (grub_list_t *head, grub_list_t item)
+{
+ 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, grub_list_t 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;
+}
+
+void *
+grub_named_list_find (grub_named_list_t head, const char *name)
+{
+ grub_named_list_t result = 0;
+
+ auto int list_find (grub_named_list_t item);
+ int list_find (grub_named_list_t item)
+ {
+ if (! grub_strcmp (item->name, name))
+ {
+ result = item;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_find);
+ return result;
+}
diff --git a/kern/term.c b/kern/term.c
index 8d5a23b..b23a00e 100644
--- a/kern/term.c
+++ b/kern/term.c
@@ -22,14 +22,6 @@
#include
#include
-/* The list of terminals. */
-static grub_term_input_t grub_term_list_input;
-static grub_term_output_t grub_term_list_output;
-
-/* The current terminal. */
-static grub_term_input_t grub_cur_term_input;
-static grub_term_output_t grub_cur_term_output;
-
/* The amount of lines counted by the pager. */
static int grub_more_lines;
@@ -39,98 +31,58 @@ static int grub_more;
/* The current cursor state. */
static int cursor_state = 1;
+static struct grub_handler_class grub_term_input_class =
+ {
+ .name = "terminal_input"
+ };
+
+static struct grub_handler_class grub_term_output_class =
+ {
+ .name = "terminal_output"
+ };
+
+#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)
+
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);
+ grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (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);
+ grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (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;
- }
+ grub_handler_unregister (&grub_term_input_class, GRUB_AS_HANDLER (term));
}
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_handler_unregister (&grub_term_output_class, GRUB_AS_HANDLER (term));
}
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;
+ return grub_handler_set_current (&grub_term_input_class,
+ GRUB_AS_HANDLER (term));
}
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;
+ return grub_handler_set_current (&grub_term_output_class,
+ GRUB_AS_HANDLER (term));
}
grub_term_input_t