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) {