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 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 . + */ + +#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_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 . + */ + +#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 ()) + +#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..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 . + */ + +#include + +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 . + */ + +#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; +} 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 #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 = "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