]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Working multi-terminal
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 24 Dec 2009 20:54:37 +0000 (21:54 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 24 Dec 2009 20:54:37 +0000 (21:54 +0100)
commands/handler.c
commands/terminal.c [new file with mode: 0644]
genhandlerlist.sh
include/grub/term.h
kern/term.c
term/i386/pc/console.c

index d65a703e4cc37b44684058b62f7ddbae6ef18dd9..60889dd5ebf7579abb33cfb9d5d67b04624ca3a4 100644 (file)
 #include <grub/command.h>
 
 static grub_err_t
-grub_cmd_handler (struct grub_command *cmd,
+grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)),
                  int argc, char **args)
 {
-  char *class_name;
   void *curr_item = 0;
   grub_handler_class_t head;
 
@@ -43,23 +42,19 @@ grub_cmd_handler (struct grub_command *cmd,
       return 0;
     }
 
-  class_name = (grub_strcmp (cmd->name, "handler")) ? (char *) cmd->name : 0;
-
   head = grub_handler_class_list;
-  if ((argc == 0) && (class_name == 0))
+  if (argc == 0)
     {
       grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item);
     }
   else
     {
+      char *class_name;
       grub_handler_class_t class;
 
-      if (class_name == 0)
-       {
-         class_name = args[0];
-         argc--;
-         args++;
-       }
+      class_name = args[0];
+      argc--;
+      args++;
 
       class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name);
       if (! class)
@@ -89,7 +84,7 @@ grub_cmd_handler (struct grub_command *cmd,
   return 0;
 }
 
-static grub_command_t cmd_handler, cmd_terminal_input, cmd_terminal_output;
+static grub_command_t cmd_handler;
 
 GRUB_MOD_INIT(handler)
 {
@@ -97,19 +92,9 @@ GRUB_MOD_INIT(handler)
     grub_register_command ("handler", grub_cmd_handler,
                           "handler [class [handler]]",
                           "List or select a handler.");
-  cmd_terminal_input =
-    grub_register_command ("terminal_input", grub_cmd_handler,
-                          "terminal_input [handler]",
-                          "List or select an input terminal.");
-  cmd_terminal_output =
-    grub_register_command ("terminal_output", grub_cmd_handler,
-                          "terminal_output [handler]",
-                          "List or select an output terminal.");
 }
 
 GRUB_MOD_FINI(handler)
 {
   grub_unregister_command (cmd_handler);
-  grub_unregister_command (cmd_terminal_input);
-  grub_unregister_command (cmd_terminal_output);
 }
diff --git a/commands/terminal.c b/commands/terminal.c
new file mode 100644 (file)
index 0000000..850d829
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ *  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/mm.h>
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/term.h>
+#include <grub/i18n.h>
+#include <grub/misc.h>
+
+grub_err_t
+grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
+                        int argc, char **args)
+{
+  int i;
+  grub_term_input_t term;
+
+  if (argc == 0)
+    {
+      grub_puts_ (N_ ("Active input terminals:"));
+      FOR_ACTIVE_TERM_INPUTS(term)
+       grub_printf ("%s ", term->name);
+      grub_printf ("\n");
+      grub_puts_ (N_ ("Available input terminals:"));
+      FOR_DISABLED_TERM_INPUTS(term)
+       grub_printf ("%s ", term->name);
+      grub_printf ("\n");
+      return GRUB_ERR_NONE;
+    }
+  i = 0;
+
+  if (grub_strcmp (args[0], "--append") == 0
+      || grub_strcmp (args[0], "--removed") == 0)
+    i++;
+
+  if (i == argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
+
+  for (; i < argc; i++)
+    {
+      FOR_DISABLED_TERM_INPUTS(term)
+       if (grub_strcmp (args[i], term->name) == 0)
+         break;
+      if (term == 0)
+       FOR_DISABLED_TERM_INPUTS(term)
+         if (grub_strcmp (args[i], term->name) == 0)
+           break;
+      if (term == 0)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
+                          args[i]);
+    }
+
+  if (grub_strcmp (args[0], "--append") == 0)
+    {
+      for (i = 1; i < argc; i++)
+       {
+         FOR_DISABLED_TERM_INPUTS(term)
+           if (grub_strcmp (args[i], term->name) == 0)
+             break;
+         if (term)
+           {
+             grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
+                               GRUB_AS_LIST (term));
+             if (term->init)
+               term->init ();
+             grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
+                             GRUB_AS_LIST (term));
+           }
+       }
+      return GRUB_ERR_NONE;
+    }
+
+  if (grub_strcmp (args[0], "--remove") == 0)
+    {
+      for (i = 1; i < argc; i++)
+       {
+         FOR_ACTIVE_TERM_INPUTS(term)
+           if (grub_strcmp (args[i], term->name) == 0)
+             break;
+         if (term)
+           {
+             if (!term->next && term == grub_term_inputs)
+               return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                                  "can't remove the last terminal");
+             grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
+                               GRUB_AS_LIST (term));
+             if (term->fini)
+               term->fini ();
+             grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
+                             GRUB_AS_LIST (term));
+           }
+       }
+      return GRUB_ERR_NONE;
+    }
+  for (i = 0; i < argc; i++)
+    {
+      FOR_DISABLED_TERM_INPUTS(term)
+       if (grub_strcmp (args[i], term->name) == 0)
+         break;
+      if (term)
+       {
+         grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
+                           GRUB_AS_LIST (term));
+         if (term->init)
+           term->init ();
+         grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
+                         GRUB_AS_LIST (term));
+       }       
+    }
+
+  FOR_ACTIVE_TERM_INPUTS(term)
+  {
+    for (i = 0; i < argc; i++)
+      if (grub_strcmp (args[i], term->name) == 0)
+       break;
+    if (i != argc)
+      {
+       if (!term->next && term == grub_term_inputs)
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            "can't remove the last terminal");
+       grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
+                         GRUB_AS_LIST (term));
+       if (term->fini)
+         term->fini ();
+       grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
+                       GRUB_AS_LIST (term));
+      }
+  }
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
+                        int argc, char **args)
+{
+  int i;
+  grub_term_output_t term;
+
+  if (argc == 0)
+    {
+      grub_puts_ (N_ ("Active output terminals:"));
+      FOR_ACTIVE_TERM_OUTPUTS(term)
+       grub_printf ("%s ", term->name);
+      grub_printf ("\n");
+      grub_puts_ (N_ ("Available output terminals:"));
+      FOR_DISABLED_TERM_OUTPUTS(term)
+       grub_printf ("%s ", term->name);
+      grub_printf ("\n");
+      return GRUB_ERR_NONE;
+    }
+  i = 0;
+
+  if (grub_strcmp (args[0], "--append") == 0
+      || grub_strcmp (args[0], "--removed") == 0)
+    i++;
+
+  if (i == argc)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
+
+  for (; i < argc; i++)
+    {
+      FOR_DISABLED_TERM_OUTPUTS(term)
+       if (grub_strcmp (args[i], term->name) == 0)
+         break;
+      if (term == 0)
+       FOR_DISABLED_TERM_OUTPUTS(term)
+         if (grub_strcmp (args[i], term->name) == 0)
+           break;
+      if (term == 0)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
+                          args[i]);
+    }
+
+  if (grub_strcmp (args[0], "--append") == 0)
+    {
+      for (i = 1; i < argc; i++)
+       {
+         FOR_DISABLED_TERM_OUTPUTS(term)
+           if (grub_strcmp (args[i], term->name) == 0)
+             break;
+         if (term)
+           {
+             grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
+                               GRUB_AS_LIST (term));
+             if (term->init)
+               term->init ();
+             grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
+                             GRUB_AS_LIST (term));
+           }
+       }
+      return GRUB_ERR_NONE;
+    }
+
+  if (grub_strcmp (args[0], "--remove") == 0)
+    {
+      for (i = 1; i < argc; i++)
+       {
+         FOR_ACTIVE_TERM_OUTPUTS(term)
+           if (grub_strcmp (args[i], term->name) == 0)
+             break;
+         if (term)
+           {
+             if (!term->next && term == grub_term_outputs)
+               return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                                  "can't remove the last terminal");
+             grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
+                               GRUB_AS_LIST (term));
+             if (term->fini)
+               term->fini ();
+             grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
+                             GRUB_AS_LIST (term));
+           }
+       }
+      return GRUB_ERR_NONE;
+    }
+  for (i = 0; i < argc; i++)
+    {
+      FOR_DISABLED_TERM_OUTPUTS(term)
+       if (grub_strcmp (args[i], term->name) == 0)
+         break;
+      if (term)
+       {
+         grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
+                           GRUB_AS_LIST (term));
+         if (term->init)
+           term->init ();
+         grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
+                         GRUB_AS_LIST (term));
+       }       
+    }
+
+  FOR_ACTIVE_TERM_OUTPUTS(term)
+  {
+    for (i = 0; i < argc; i++)
+      if (grub_strcmp (args[i], term->name) == 0)
+       break;
+    if (i != argc)
+      {
+       if (!term->next && term == grub_term_outputs)
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            "can't remove the last terminal");
+       grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
+                         GRUB_AS_LIST (term));
+       if (term->fini)
+         term->fini ();
+       grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
+                       GRUB_AS_LIST (term));
+      }
+  }
+
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd_terminal_input, cmd_terminal_output;
+
+GRUB_MOD_INIT(terminal)
+{
+  cmd_terminal_input =
+    grub_register_command ("terminal_input", grub_cmd_terminal_input,
+                          "terminal_input [--append|--remove] "
+                          "[TERMINAL1] [TERMINAL2] ...",
+                          "List or select an input terminal.");
+  cmd_terminal_output =
+    grub_register_command ("terminal_output", grub_cmd_terminal_output,
+                          "terminal_output [--append|--remove] "
+                          "[TERMINAL1] [TERMINAL2] ...",
+                          "List or select an output terminal.");
+}
+
+GRUB_MOD_FINI(terminal)
+{
+  grub_unregister_command (cmd_terminal_input);
+  grub_unregister_command (cmd_terminal_output);
+}
index 6446a98ff7c435b6032880e79e3af2240322c997..e4cb0d9de95aba3b24d6e4abdf571da20968c6a0 100644 (file)
@@ -16,8 +16,4 @@
 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;}"
+ -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}"
index bf6766af68e1b45634879a797652326cacf06a79..24bb503ba58c0b436692542f760b2ca6716b474a 100644 (file)
@@ -68,8 +68,6 @@ grub_term_color_state;
 #define GRUB_TERM_NO_EDIT      (1 << 1)
 /* Set when the terminal cannot do fancy things.  */
 #define GRUB_TERM_DUMB         (1 << 2)
-/* Terminal is used as general output.  */
-#define GRUB_TERM_ACTIVE       (1 << 3)
 /* Set when the terminal needs to be initialized.  */
 #define GRUB_TERM_NEED_INIT    (1 << 16)
 
@@ -197,37 +195,65 @@ struct grub_term_output
 };
 typedef struct grub_term_output *grub_term_output_t;
 
+extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
+extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
 extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
 extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
 
+static inline void
+grub_term_register_input_active (const char *name __attribute__ ((unused)),
+                                grub_term_input_t term)
+{
+  if (term->init)
+    term->init ();
+  grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
+}
+
 static inline void
 grub_term_register_input (const char *name __attribute__ ((unused)),
                          grub_term_input_t term)
 {
-  grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
+  grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
+                 GRUB_AS_LIST (term));
+}
+
+static inline void
+grub_term_register_output_active (const char *name __attribute__ ((unused)),
+                                 grub_term_output_t term)
+{
+  if (term->init)
+    term->init ();
+  grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term));
 }
 
 static inline void
 grub_term_register_output (const char *name __attribute__ ((unused)),
                           grub_term_output_t term)
 {
-  grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term));
+  grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
+                 GRUB_AS_LIST (term));
 }
 
 static inline void
 grub_term_unregister_input (grub_term_input_t term)
 {
   grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
+  grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
+                   GRUB_AS_LIST (term));
 }
 
 static inline void
 grub_term_unregister_output (grub_term_output_t term)
 {
   grub_list_remove (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term));
+  grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
+                   GRUB_AS_LIST (term));
 }
 
 #define FOR_ACTIVE_TERM_INPUTS(var) for (var = grub_term_inputs; var; var = var->next)
-#define FOR_ACTIVE_TERM_OUTPUTS(var) for (var = grub_term_outputs; var; var = var->next) if (grub_term_is_active (var))
+#define FOR_DISABLED_TERM_INPUTS(var) for (var = grub_term_inputs_disabled; var; var = var->next)
+#define FOR_ACTIVE_TERM_OUTPUTS(var) for (var = grub_term_outputs; var; var = var->next)
+#define FOR_DISABLED_TERM_OUTPUTS(var) for (var = grub_term_outputs_disabled; var; var = var->next)
 
 void EXPORT_FUNC(grub_putchar) (int c);
 void EXPORT_FUNC(grub_putcode) (grub_uint32_t code,
@@ -335,12 +361,6 @@ grub_term_setcursor (struct grub_term_output *term, int on)
     term->setcursor (on);
 }
 
-static inline int
-grub_term_is_active (struct grub_term_output *term)
-{
-  return !!(term->flags & GRUB_TERM_ACTIVE);
-}
-
 static inline grub_ssize_t 
 grub_term_getcharwidth (struct grub_term_output *term, grub_uint32_t c)
 {
index dbcac1b1977f6fcb82116ee295b14d4355d2d4be..51eee3b08d9776e071ad21939cd2ab91ac568418 100644 (file)
@@ -23,6 +23,8 @@
 #include <grub/env.h>
 #include <grub/cpu/time.h>
 
+struct grub_term_output *grub_term_outputs_disabled;
+struct grub_term_input *grub_term_inputs_disabled;
 struct grub_term_output *grub_term_outputs;
 struct grub_term_input *grub_term_inputs;
 
index 6f56fc0d75b17c8b2aaf516ef95d95fa9c183a4a..3c0fcccad6141745a4bfcd4ed2a775f1ab9245ed 100644 (file)
@@ -65,15 +65,14 @@ static struct grub_term_output grub_console_term_output =
     .setcolorstate = grub_console_setcolorstate,
     .setcolor = grub_console_setcolor,
     .getcolor = grub_console_getcolor,
-    .setcursor = grub_console_setcursor,
-    .flags = GRUB_TERM_ACTIVE,
+    .setcursor = grub_console_setcursor
   };
 
 void
 grub_console_init (void)
 {
-  grub_term_register_output ("console", &grub_console_term_output);
-  grub_term_register_input ("console", &grub_console_term_input);
+  grub_term_register_output_active ("console", &grub_console_term_output);
+  grub_term_register_input_active ("console", &grub_console_term_input);
 }
 
 void