Hi, This new version of handler patch contain the following changes:
1, Register/unregister handler class automatically, so there is no need to usel grub_handler_class_register/grub_handler_class_unregister anymore. 2, Keep the original api function of term.c, so that there is no need to change modules depend on it. Inside term.c, it rely on the handler function to do the job. 3. Use a new method of compile time checking. Now, instead of using void*, it uses normal type, for example: void grub_handler_register (grub_handler_class_t class, grub_handler_t handler); Codes that calls grub_handler_register should looks like this: grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term)); macro GRUB_AS_HANDLER check the various fields required by grub_handler_t is at the same location as term, and then cast it to type grub_handler_t. Just as before, if the testing succeed, it wouldn't generate extra runtime code. If there is no objection, I'd commit this patch in a few days. 2009-02-14 Bean <bean12...@gmail.com> * commands/handler.c: New file. * include/grub/list.h: Likewise. * include/grub/handler.h: Likewise. * kern/list.c: Likewise. * kern/handler.c: Likewise. * kern/term.h: Include header file <grub/handler.h>. (grub_term_input): Move next field to the beginning. (grub_term_output): Likewise. (grub_term_iterate_input): Removed. (grub_term_iterate_output): Likewise. * kern/term.c (grub_term_list_input): Removed. (grub_term_list_output): Likewise. (grub_term_input_class): New variable. (grub_term_output_class): Likewise. (grub_cur_term_input): Change varaible as macro. (grub_cur_term_output): Likewise. (grub_term_register_input): Call underlying handler function to do the job. (grub_term_register_output): Likewise. (grub_term_unregister_input): Likewise. (grub_term_unregister_output): Likewise. (grub_term_set_current_input): Likewise. (grub_term_set_current_output): Likewise. (grub_term_iterate_input): Removed. (grub_term_iterate_output): Likewise. (grub_term_get_current_input): Use grub_term_input_class to retrive the current handler. (grub_term_get_current_output): Likewise. * conf/common.rmk (pkglib_MODULES): Replace terminal with handler. (terminal_mod_SOURCES): Likewise. (terminal_mod_CFLAGS): Likewise. (terminal_mod_LDFLAGS): Likewise. * conf/i386-pc.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_img_SOURCES): Add list.c and handler.c. (kernel_img_HEADERS): Add list.h and handler.h. * conf/i386-efi.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_mod_SOURCES): Add list.c and handler.c. (kernel_mod_HEADERS): Add list.h and handler.h. * conf/i386-coreboot.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_elf_SOURCES): Add list.c and handler.c. (kernel_elf_HEADERS): Add list.h and handler.h. * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_elf_SOURCES): Add list.c and handler.c. (kernel_elf_HEADERS): Add list.h and handler.h. * conf/x86_64-efi.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_mod_SOURCES): Add list.c and handler.c. (kernel_mod_HEADERS): Add list.h and handler.h. * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_elf_SOURCES): Add list.c and handler.c. (kernel_elf_HEADERS): Add list.h and handler.h. * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Replace terminal.c with handler.c. (kernel_elf_SOURCES): Add list.c and handler.c. (kernel_elf_HEADERS): Add list.h and handler.h. -- Bean
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 <http://www.gnu.org/licenses/>. + */ + +#include <grub/normal.h> +#include <grub/dl.h> +#include <grub/err.h> +#include <grub/misc.h> +#include <grub/handler.h> + +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 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..826fd2b --- /dev/null +++ b/include/grub/handler.h @@ -0,0 +1,63 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_HANDLER_HEADER +#define GRUB_HANDLER_HEADER 1 + +#include <grub/list.h> +#include <grub/err.h> + +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_iterate) (int (*hook) + (grub_handler_class_t item)); + +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); +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, + 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..59b352a --- /dev/null +++ b/include/grub/list.h @@ -0,0 +1,50 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_LIST_HEADER +#define GRUB_LIST_HEADER 1 + +#include <grub/symbol.h> +#include <grub/types.h> + +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 ()) + +#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 <grub/err.h> #include <grub/symbol.h> #include <grub/types.h> +#include <grub/handler.h> /* 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..b22d9af --- /dev/null +++ b/kern/handler.c @@ -0,0 +1,72 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#include <grub/handler.h> + +static grub_list_t grub_handler_class_list; + +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, grub_handler_t handler) +{ + int first_handler = (class->handler_list == 0); + + grub_list_push (&class->handler_list, GRUB_AS_LIST (handler)); + + if (first_handler) + { + grub_list_push (&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 (&class->handler_list, GRUB_AS_LIST (handler)); + + if (class->handler_list == 0) + grub_list_remove (&grub_handler_class_list, GRUB_AS_LIST (class)); +} + +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, 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..e553443 --- /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 <http://www.gnu.org/licenses/>. + */ + +#include <grub/list.h> + +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; +} diff --git a/kern/term.c b/kern/term.c index 8d5a23b..3de1db4 100644 --- a/kern/term.c +++ b/kern/term.c @@ -22,14 +22,6 @@ #include <grub/misc.h> #include <grub/env.h> -/* 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 = "input" + }; + +static struct grub_handler_class grub_term_output_class = + { + .name = "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
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel