diff --git a/Makefile.in b/Makefile.in index d6e55e7..b24ee2e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -139,7 +139,7 @@ include $(srcdir)/conf/$(target_cpu)-$(platform).mk ### General targets. CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) -pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst +pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst handler.lst moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk cat $(DEFSYMFILES) /dev/null \ | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ @@ -154,6 +154,9 @@ fs.lst: $(FSFILES) partmap.lst: $(PARTMAPFILES) cat $^ /dev/null | sort > $@ +handler.lst: $(HANDLERFILES) + cat $^ /dev/null | sort > $@ + ifeq (, $(UNIFONT_BDF)) else diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 7dfb854..bd20238 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -206,7 +206,7 @@ linux_mod_LDFLAGS = $(COMMON_LDFLAGS) # keep it simpler to update to different architectures. # normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/datetime.c \ - normal/completion.c normal/execute.c \ + normal/completion.c normal/execute.c normal/handler.c \ normal/function.c normal/lexer.c normal/main.c normal/menu.c \ normal/menu_text.c \ normal/color.c \ diff --git a/config.h.in b/config.h.in index 1a9ed68..e825f7c 100644 --- a/config.h.in +++ b/config.h.in @@ -4,9 +4,6 @@ prefixed with an asterisk */ #undef ABSOLUTE_WITHOUT_ASTERISK -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - /* Define it to \"addr32\" or \"addr32;\" to make GAS happy */ #undef ADDR32 @@ -121,52 +118,17 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS -/* Enable extensions on AIX 3, Interix. */ -#ifndef _ALL_SOURCE -# undef _ALL_SOURCE -#endif +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif -/* Enable threading extensions on Solaris. */ -#ifndef _POSIX_PTHREAD_SEMANTICS -# undef _POSIX_PTHREAD_SEMANTICS -#endif -/* Enable extensions on HP NonStop. */ -#ifndef _TANDEM_SOURCE -# undef _TANDEM_SOURCE -#endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ -#endif - - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -#undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES - -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE diff --git a/genhandlerlist.sh b/genhandlerlist.sh new file mode 100644 index 0000000..6446a98 --- /dev/null +++ b/genhandlerlist.sh @@ -0,0 +1,23 @@ +#! /bin/sh +# +# Copyright (C) 2009 Free Software Foundation, Inc. +# +# This script is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Read source code from stdin and detect command names. + +module=$1 + +grep -v "^#" | sed -n \ + -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" \ + -e "/grub_reader_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/reader.\1: $module/;p;}" \ + -e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_input.\1: $module/;p;}" \ + -e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_output.\1: $module/;p;}" \ + -e "/grub_menu_viewer_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/menu_viewer.\1: $module/;p;}" diff --git a/genmk.rb b/genmk.rb index 62e5066..c676a67 100644 --- a/genmk.rb +++ b/genmk.rb @@ -143,6 +143,7 @@ endif command = 'cmd-' + obj.suffix('lst') fs = 'fs-' + obj.suffix('lst') partmap = 'partmap-' + obj.suffix('lst') + handler = 'handler-' + obj.suffix('lst') dep = deps[i] flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end @@ -152,10 +153,11 @@ endif $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $< -include #{dep} -CLEANFILES += #{command} #{fs} #{partmap} +CLEANFILES += #{command} #{fs} #{partmap} #{handler} COMMANDFILES += #{command} FSFILES += #{fs} PARTMAPFILES += #{partmap} +HANDLERFILES += #{handler} #{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh set -e; \ @@ -172,6 +174,10 @@ PARTMAPFILES += #{partmap} $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ | sh $(srcdir)/genpartmaplist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) +#{handler}: #{src} $(#{src}_DEPENDENCIES) genhandlerlist.sh + set -e; \ + $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ + | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) " end.join('') diff --git a/include/grub/normal.h b/include/grub/normal.h index 27978dc..e62e433 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -26,6 +26,7 @@ #include #include #include +#include /* The maximum size of a command-line. */ #define GRUB_MAX_CMDLINE 1600 @@ -103,6 +104,10 @@ char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val) void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); void grub_wait_after_message (void); +char *grub_file_getline (grub_file_t file); +void read_handler_list (void); +void free_handler_list (void); + #ifdef GRUB_UTIL void grub_normal_init (void); void grub_normal_fini (void); diff --git a/include/grub/term.h b/include/grub/term.h index 6a35664..d12d0f0 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -219,13 +219,15 @@ extern struct grub_handler_class EXPORT_VAR(grub_term_input_class); extern struct grub_handler_class EXPORT_VAR(grub_term_output_class); static inline void -grub_term_register_input (grub_term_input_t term) +grub_term_register_input (const char *name __attribute__ ((unused)), + grub_term_input_t term) { grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term)); } static inline void -grub_term_register_output (grub_term_output_t term) +grub_term_register_output (const char *name __attribute__ ((unused)), + grub_term_output_t term) { grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term)); } diff --git a/normal/handler.c b/normal/handler.c new file mode 100755 index 0000000..f9c2bd6 --- /dev/null +++ b/normal/handler.c @@ -0,0 +1,229 @@ +/* handler.c - support handler loading */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct grub_handler_list +{ + struct grub_handler_list *next; + char *name; + grub_command_t cmd; +}; + +static grub_list_t handler_list; + +static grub_err_t +grub_handler_cmd (struct grub_command *cmd, + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + char *p; + grub_handler_class_t class; + grub_handler_t handler; + + p = grub_strchr (cmd->name, '.'); + if (! p) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid command name"); + + if (cmd->data) + { + if (! grub_dl_get (cmd->data)) + { + grub_dl_t mod; + + mod = grub_dl_load (cmd->data); + if (mod) + grub_dl_ref (mod); + else + return grub_errno; + } + grub_free (cmd->data); + cmd->data = 0; + } + + *p = 0; + class = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_handler_class_list), + cmd->name); + *p = '.'; + + if (! class) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found"); + + + handler = grub_named_list_find (GRUB_AS_NAMED_LIST (class->handler_list), + p + 1); + if (! handler) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found"); + + grub_handler_set_current (class, handler); + + return 0; +} + +static void +insert_handler (char *name, char *module) +{ + struct grub_handler_list *item; + char *data; + + item = grub_malloc (sizeof (*item)); + if (! item) + return; + + item->name = grub_strdup (name); + if (! item->name) + { + grub_free (item); + return; + } + + if (module) + { + data = grub_strdup (module); + if (! data) + { + grub_free (item->name); + grub_free (item); + return; + } + } + else + data = 0; + + item->cmd = grub_register_command (item->name, grub_handler_cmd, 0, + "Set active handler"); + if (! item->cmd) + { + grub_free (data); + grub_free (item->name); + grub_free (item); + return; + } + + item->cmd->data = data; + grub_list_push (&handler_list, GRUB_AS_LIST (item)); +} + +/* Read the file handler.lst for auto-loading. */ +void +read_handler_list (void) +{ + const char *prefix; + static int first_time = 1; + const char *class_name; + + auto int iterate_handler (grub_handler_t handler); + int iterate_handler (grub_handler_t handler) + { + char name[grub_strlen (class_name) + grub_strlen (handler->name) + 2]; + + grub_strcpy (name, class_name); + grub_strcat (name, "."); + grub_strcat (name, handler->name); + + insert_handler (name, 0); + return 0; + } + + auto int iterate_class (grub_handler_class_t class); + int iterate_class (grub_handler_class_t class) + { + class_name = class->name; + grub_list_iterate (GRUB_AS_LIST (class->handler_list), + (grub_list_hook_t) iterate_handler); + + return 0; + } + + /* Make sure that this function does not get executed twice. */ + if (! first_time) + return; + first_time = 0; + + prefix = grub_env_get ("prefix"); + if (prefix) + { + char *filename; + + filename = grub_malloc (grub_strlen (prefix) + sizeof ("/handler.lst")); + if (filename) + { + grub_file_t file; + + grub_sprintf (filename, "%s/handler.lst", prefix); + file = grub_file_open (filename); + if (file) + { + char *buf = 0; + for (;; grub_free(buf)) + { + char *p; + + buf = grub_file_getline (file); + + if (! buf) + break; + + if (! grub_isgraph (buf[0])) + continue; + + p = grub_strchr (buf, ':'); + if (! p) + continue; + + *p = '\0'; + while (*++p == ' ') + ; + + insert_handler (buf, p); + } + + grub_file_close (file); + } + else + grub_list_iterate (GRUB_AS_LIST (grub_handler_class_list), + (grub_list_hook_t) iterate_class); + grub_free (filename); + } + } + + /* Ignore errors. */ + grub_errno = GRUB_ERR_NONE; +} + +void +free_handler_list (void) +{ + struct grub_handler_list *item; + + while ((item = grub_list_pop (&handler_list)) != 0) + { + grub_free (item->cmd->data); + grub_unregister_command (item->cmd); + grub_free (item->name); + grub_free (item); + } +} diff --git a/normal/main.c b/normal/main.c index 9f906d8..5aaeb5f 100644 --- a/normal/main.c +++ b/normal/main.c @@ -37,8 +37,8 @@ static grub_fs_module_list_t fs_module_list = 0; #define GRUB_DEFAULT_HISTORY_SIZE 50 /* Read a line from the file FILE. */ -static char * -get_line (grub_file_t file) +char * +grub_file_getline (grub_file_t file) { char c; int pos = 0; @@ -310,7 +310,7 @@ read_config_file (const char *config, int nested) { currline++; - *line = get_line (file); + *line = grub_file_getline (file); if (! *line) return grub_errno; @@ -343,7 +343,7 @@ read_config_file (const char *config, int nested) int startline; char *cmdline; - cmdline = get_line (file); + cmdline = grub_file_getline (file); if (!cmdline) break; @@ -475,7 +475,7 @@ read_command_list (void) grub_command_t cmd; int prio = 0; - buf = get_line (file); + buf = grub_file_getline (file); if (! buf) break; @@ -594,7 +594,7 @@ read_fs_list (void) char *q; grub_fs_module_list_t fs_mod; - buf = get_line (file); + buf = grub_file_getline (file); if (! buf) break; @@ -650,6 +650,7 @@ grub_normal_execute (const char *config, int nested, int batch) read_command_list (); read_fs_list (); + read_handler_list (); if (config) { @@ -754,4 +755,5 @@ GRUB_MOD_FINI(normal) { grub_set_history (0); grub_unregister_command (cmd_normal); + free_handler_list (); } diff --git a/term/efi/console.c b/term/efi/console.c index 0bf2449..3322b8f 100644 --- a/term/efi/console.c +++ b/term/efi/console.c @@ -366,8 +366,8 @@ grub_console_init (void) return; } - grub_term_register_input (&grub_console_term_input); - grub_term_register_output (&grub_console_term_output); + grub_term_register_input ("console", &grub_console_term_input); + grub_term_register_output ("console", &grub_console_term_output); } void diff --git a/term/gfxterm.c b/term/gfxterm.c index dacecf4..4f74346 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -1155,7 +1155,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(term_gfxterm) { my_mod = mod; - grub_term_register_output (&grub_video_term); + grub_term_register_output ("gfxterm", &grub_video_term); cmd = grub_register_command ("background_image", grub_gfxterm_background_image_cmd, 0, "Load background image for active terminal"); diff --git a/term/i386/pc/at_keyboard.c b/term/i386/pc/at_keyboard.c index ff5246d..0b2a06d 100644 --- a/term/i386/pc/at_keyboard.c +++ b/term/i386/pc/at_keyboard.c @@ -226,7 +226,7 @@ static struct grub_term_input grub_at_keyboard_term = GRUB_MOD_INIT(at_keyboard) { - grub_term_register_input (&grub_at_keyboard_term); + grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); } GRUB_MOD_FINI(at_keyboard) diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 6c6be46..c880595 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_term_register_output ("console", &grub_console_term_output); + grub_term_register_input ("console", &grub_console_term_input); } void diff --git a/term/i386/pc/serial.c b/term/i386/pc/serial.c index eacff06..757a06c 100644 --- a/term/i386/pc/serial.c +++ b/term/i386/pc/serial.c @@ -577,8 +577,8 @@ grub_cmd_serial (grub_extcmd_t cmd, /* 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_term_register_input ("serial", &grub_serial_term_input); + grub_term_register_output ("serial", &grub_serial_term_output); registered = 1; } } diff --git a/term/i386/pc/vesafb.c b/term/i386/pc/vesafb.c index 75cbd75..edd0b1a 100644 --- a/term/i386/pc/vesafb.c +++ b/term/i386/pc/vesafb.c @@ -599,7 +599,7 @@ static struct grub_term_output grub_vesafb_term = GRUB_MOD_INIT(vesafb) { my_mod = mod; - grub_term_register_output (&grub_vesafb_term); + grub_term_register_output ("vesafb", &grub_vesafb_term); } GRUB_MOD_FINI(vesafb) diff --git a/term/i386/pc/vga.c b/term/i386/pc/vga.c index af880d5..dd2e25c 100644 --- a/term/i386/pc/vga.c +++ b/term/i386/pc/vga.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #define DEBUG_VGA 0 @@ -509,7 +508,7 @@ GRUB_MOD_INIT(vga) #ifndef GRUB_UTIL my_mod = mod; #endif - grub_term_register_output (&grub_vga_term); + grub_term_register_output ("vga", &grub_vga_term); } GRUB_MOD_FINI(vga) diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c index e067ed6..170f74d 100644 --- a/term/i386/pc/vga_text.c +++ b/term/i386/pc/vga_text.c @@ -168,7 +168,7 @@ static struct grub_term_output grub_vga_text_term = GRUB_MOD_INIT(vga_text) { - grub_term_register_output (&grub_vga_text_term); + grub_term_register_output ("vga_text", &grub_vga_text_term); } GRUB_MOD_FINI(vga_text) diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c index 70fda9a..0cc0924 100644 --- a/term/ieee1275/ofconsole.c +++ b/term/ieee1275/ofconsole.c @@ -420,8 +420,8 @@ 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_term_register_input ("ofconsole", &grub_ofconsole_term_input); + grub_term_register_output ("ofconsole", &grub_ofconsole_term_output); } void diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 07f7d08..6caa2ff 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -248,7 +248,7 @@ GRUB_MOD_INIT(usb_keyboard) (void) mod; /* To stop warning. */ grub_usb_hid (); - grub_term_register_input (&grub_usb_keyboard_term); + grub_term_register_input ("usb_keyboard", &grub_usb_keyboard_term); } GRUB_MOD_FINI(usb_keyboard)