]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
merge common serial and ofconsole code into terminfo
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 7 May 2010 13:44:43 +0000 (15:44 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 7 May 2010 13:44:43 +0000 (15:44 +0200)
include/grub/ieee1275/console.h [moved from include/grub/i386/ieee1275/console.h with 92% similarity]
include/grub/powerpc/ieee1275/console.h [deleted file]
include/grub/sparc64/ieee1275/console.h [deleted file]
include/grub/terminfo.h
kern/ieee1275/init.c
term/ieee1275/ofconsole.c
term/serial.c
term/terminfo.c
term/tparm.c

similarity index 92%
rename from include/grub/i386/ieee1275/console.h
rename to include/grub/ieee1275/console.h
index 854724ac1dcb459bc14534ad313b68ee3262f6a2..e054f54f547de46c0d77b2775158c4fc2eb9471d 100644 (file)
@@ -22,7 +22,8 @@
 #include <grub/symbol.h>
 
 /* Initialize the console system.  */
-void grub_console_init (void);
+void grub_console_init_early (void);
+void grub_console_init_lately (void);
 
 /* Finish the console system.  */
 void grub_console_fini (void);
diff --git a/include/grub/powerpc/ieee1275/console.h b/include/grub/powerpc/ieee1275/console.h
deleted file mode 100644 (file)
index ed2b720..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
- *
- *  GRUB is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  GRUB is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_CONSOLE_MACHINE_HEADER
-#define GRUB_CONSOLE_MACHINE_HEADER    1
-
-/* Initialize the console system.  */
-void grub_console_init (void);
-
-/* Finish the console system.  */
-void grub_console_fini (void);
-
-#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/sparc64/ieee1275/console.h b/include/grub/sparc64/ieee1275/console.h
deleted file mode 100644 (file)
index ed2b720..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2004,2005,2007  Free Software Foundation, Inc.
- *
- *  GRUB is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  GRUB is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef GRUB_CONSOLE_MACHINE_HEADER
-#define GRUB_CONSOLE_MACHINE_HEADER    1
-
-/* Initialize the console system.  */
-void grub_console_init (void);
-
-/* Finish the console system.  */
-void grub_console_fini (void);
-
-#endif /* ! GRUB_CONSOLE_MACHINE_HEADER */
index f078871d06848e4dcbca03a130f9c2cefab46f13..54872caa813bd793338a95a1c8427b9fc09f0d7e 100644 (file)
 #include <grub/types.h>
 #include <grub/term.h>
 
-char *EXPORT_FUNC(grub_terminfo_get_current) (void);
-grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (const char *);
-
-void EXPORT_FUNC(grub_terminfo_gotoxy) (grub_uint8_t x, grub_uint8_t y,
-                                       grub_term_output_t oterm);
-void EXPORT_FUNC(grub_terminfo_cls) (grub_term_output_t oterm);
-void EXPORT_FUNC(grub_terminfo_reverse_video_on) (grub_term_output_t oterm);
-void EXPORT_FUNC(grub_terminfo_reverse_video_off) (grub_term_output_t oterm);
-void EXPORT_FUNC(grub_terminfo_cursor_on) (grub_term_output_t oterm);
-void EXPORT_FUNC(grub_terminfo_cursor_off) (grub_term_output_t oterm);
+char *EXPORT_FUNC(grub_terminfo_get_current) (struct grub_term_output *term);
+grub_err_t EXPORT_FUNC(grub_terminfo_set_current) (struct grub_term_output *term,
+                                                                                               const char *);
 
 #define GRUB_TERMINFO_READKEY_MAX_LEN 4
-void EXPORT_FUNC(grub_terminfo_readkey) (int *keys, int *len, int (*readkey) (void));
+struct grub_terminfo_input_state
+{
+  int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN];
+  int npending;
+  int (*readkey) (void);
+};
+
+struct grub_terminfo_output_state
+{
+  struct grub_term_output *next;
+
+  char *name;
+
+  char *gotoxy;
+  char *cls;
+  char *reverse_video_on;
+  char *reverse_video_off;
+  char *cursor_on;
+  char *cursor_off;
+  char *setcolor;
+
+  grub_uint8_t normal_color;
+  grub_uint8_t highlight_color;
+
+  unsigned int xpos, ypos;
+
+  void (*put) (const int c);
+};
+
+void EXPORT_FUNC(grub_terminfo_gotoxy) (grub_term_output_t term,
+                                       grub_uint8_t x, grub_uint8_t y);
+void EXPORT_FUNC(grub_terminfo_cls) (grub_term_output_t term);
+grub_uint16_t EXPORT_FUNC (grub_terminfo_getxy) (struct grub_term_output *term);
+void EXPORT_FUNC (grub_terminfo_setcursor) (struct grub_term_output *term,
+                                           const int on);
+void EXPORT_FUNC (grub_terminfo_setcolorstate) (struct grub_term_output *term,
+                                 const grub_term_color_state state);
+
+
+int EXPORT_FUNC (grub_terminfo_checkkey) (struct grub_term_input *term);
+grub_err_t EXPORT_FUNC (grub_terminfo_input_init) (struct grub_term_input *term);
+int EXPORT_FUNC (grub_terminfo_getkey) (struct grub_term_input *term);
+void EXPORT_FUNC (grub_terminfo_putchar) (struct grub_term_output *term,
+                                         const struct grub_unicode_glyph *c);
+void EXPORT_FUNC (grub_terminfo_getcolor) (struct grub_term_output *term,
+                                          grub_uint8_t *normal_color,
+                                          grub_uint8_t *highlight_color);
+void EXPORT_FUNC (grub_terminfo_setcolor) (struct grub_term_output *term,
+                                          grub_uint8_t normal_color,
+                                          grub_uint8_t highlight_color);
+
+grub_err_t EXPORT_FUNC (grub_terminfo_output_register) (struct grub_term_output *term,
+                                                       const char *type);
+grub_err_t EXPORT_FUNC (grub_terminfo_output_unregister) (struct grub_term_output *term);
 
 #endif /* ! GRUB_TERMINFO_HEADER */
index b48df37bc5b67f6ed186c6713b395236d25fb038..1a408fb738a1a295264c866e5e7865b23d501dee 100644 (file)
@@ -28,7 +28,7 @@
 #include <grub/env.h>
 #include <grub/misc.h>
 #include <grub/time.h>
-#include <grub/machine/console.h>
+#include <grub/ieee1275/console.h>
 #include <grub/machine/kernel.h>
 #include <grub/cpu/kernel.h>
 #include <grub/ieee1275/ofdisk.h>
@@ -225,11 +225,12 @@ grub_machine_init (void)
 
   grub_ieee1275_init ();
 
-  grub_console_init ();
+  grub_console_init_early ();
 #ifdef __i386__
   grub_get_extended_memory ();
 #endif
   grub_claim_heap ();
+  grub_console_init_lately ();
   grub_ofdisk_init ();
 
   /* Process commandline.  */
index 590fa7f530d22c12cd8808b8255ff47c2ad5fef1..d143a6313ba3a1fbc24f52b58a2dc2be59541c96 100644 (file)
@@ -23,7 +23,7 @@
 #include <grub/mm.h>
 #include <grub/time.h>
 #include <grub/terminfo.h>
-#include <grub/machine/console.h>
+#include <grub/ieee1275/console.h>
 #include <grub/ieee1275/ieee1275.h>
 
 static grub_ieee1275_ihandle_t stdout_ihandle;
@@ -32,12 +32,6 @@ static grub_ieee1275_ihandle_t stdin_ihandle;
 static grub_uint8_t grub_ofconsole_width;
 static grub_uint8_t grub_ofconsole_height;
 
-static int grub_curr_x;
-static int grub_curr_y;
-
-static int grub_keybuf[GRUB_TERMINFO_READKEY_MAX_LEN];
-static int grub_buflen;
-
 struct color
 {
   int red;
@@ -58,102 +52,14 @@ static struct color colors[] =
     {0xFE, 0xFE, 0xFE}  // 7 = white
   };
 
-static grub_uint8_t grub_ofconsole_normal_color = 0x7;
-static grub_uint8_t grub_ofconsole_highlight_color = 0x70;
-
-/* Write control characters to the console.  */
-static void
-grub_ofconsole_writeesc (const char *str)
-{
-  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
-    return;
-
-  while (*str)
-    {
-      char chr = *(str++);
-      grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
-    }
-
-}
-
 static void
-grub_ofconsole_putchar (struct grub_term_output *term __attribute__ ((unused)),
-                       const struct grub_unicode_glyph *c)
+put (const int c)
 {
-  char chr;
+  char chr = c;
 
-  chr = c->base;
-
-  if (chr == '\n')
-    {
-      grub_curr_y++;
-      grub_curr_x = 0;
-    }
-  else if (chr == '\r')
-    {
-      grub_curr_x = 0;
-    }
-  else
-    {
-      grub_curr_x++;
-      if (grub_curr_x >= grub_ofconsole_width)
-        {
-         chr = '\n';
-         grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
-         chr = '\r';
-         grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
-         grub_curr_y++;
-         grub_curr_x = 1;
-        }
-    }
   grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
 }
 
-static void
-grub_ofconsole_setcolorstate (struct grub_term_output *term __attribute__ ((unused)),
-                             grub_term_color_state state)
-{
-  char setcol[256];
-  int fg;
-  int bg;
-
-  switch (state)
-    {
-    case GRUB_TERM_COLOR_STANDARD:
-    case GRUB_TERM_COLOR_NORMAL:
-      fg = grub_ofconsole_normal_color & 0x0f;
-      bg = grub_ofconsole_normal_color >> 4;
-      break;
-    case GRUB_TERM_COLOR_HIGHLIGHT:
-      fg = grub_ofconsole_highlight_color & 0x0f;
-      bg = grub_ofconsole_highlight_color >> 4;
-      break;
-    default:
-      return;
-    }
-
-  grub_snprintf (setcol, sizeof (setcol), "\e[3%dm\e[4%dm", fg, bg);
-  grub_ofconsole_writeesc (setcol);
-}
-
-static void
-grub_ofconsole_setcolor (struct grub_term_output *term __attribute__ ((unused)),
-                        grub_uint8_t normal_color,
-                        grub_uint8_t highlight_color)
-{
-  /* Discard bright bit.  */
-  grub_ofconsole_normal_color = normal_color & 0x77;
-  grub_ofconsole_highlight_color = highlight_color & 0x77;
-}
-
-static void
-grub_ofconsole_getcolor (struct grub_term_output *term __attribute__ ((unused)),
-                        grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
-{
-  *normal_color = grub_ofconsole_normal_color;
-  *highlight_color = grub_ofconsole_highlight_color;
-}
-
 static int
 readkey (void)
 {
@@ -166,39 +72,6 @@ readkey (void)
   return -1;
 }
 
-static int
-grub_ofconsole_checkkey (struct grub_term_input *term __attribute__ ((unused)))
-{
-  if (grub_buflen)
-    return grub_keybuf[0];
-
-  grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey);
-
-  if (grub_buflen)
-    return grub_keybuf[0];
-
-  return -1;
-}
-
-static int
-grub_ofconsole_getkey (struct grub_term_input *term __attribute__ ((unused)))
-{
-  int ret;
-  while (! grub_buflen)
-    grub_terminfo_readkey (grub_keybuf, &grub_buflen, readkey);
-
-  ret = grub_keybuf[0];
-  grub_buflen--;
-  grub_memmove (grub_keybuf, grub_keybuf + 1, grub_buflen);
-  return ret;
-}
-
-static grub_uint16_t
-grub_ofconsole_getxy (struct grub_term_output *term __attribute__ ((unused)))
-{
-  return (grub_curr_x << 8) | grub_curr_y;
-}
-
 static void
 grub_ofconsole_dimensions (void)
 {
@@ -241,44 +114,6 @@ grub_ofconsole_getwh (struct grub_term_output *term __attribute__ ((unused)))
   return (grub_ofconsole_width << 8) | grub_ofconsole_height;
 }
 
-static void
-grub_ofconsole_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
-                      grub_uint8_t x, grub_uint8_t y)
-{
-  if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
-    {
-      char s[256];
-      grub_curr_x = x;
-      grub_curr_y = y;
-
-      grub_snprintf (s, sizeof (s), "\e[%d;%dH", y + 1, x + 1);
-      grub_ofconsole_writeesc (s);
-    }
-  else
-    {
-      if ((y == grub_curr_y) && (x == grub_curr_x - 1))
-        {
-          char chr;
-
-          chr = '\b';
-          grub_ieee1275_write (stdout_ihandle, &chr, 1, 0);
-        }
-
-      grub_curr_x = x;
-      grub_curr_y = y;
-    }
-}
-
-static void
-grub_ofconsole_cls (struct grub_term_output *term)
-{
-  /* Clear the screen.  Using serial console, screen(1) only recognizes the
-   * ANSI escape sequence.  Using video console, Apple Open Firmware (version
-   * 3.1.1) only recognizes the literal ^L.  So use both.  */
-  grub_ofconsole_writeesc ("\f\e[2J");
-  grub_ofconsole_gotoxy (term, 0, 0);
-}
-
 static void
 grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused)),
                          int on)
@@ -290,14 +125,8 @@ grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused))
     grub_ieee1275_interpret ("cursor-off", 0);
 }
 
-static void
-grub_ofconsole_refresh (struct grub_term_output *term __attribute__ ((unused)))
-{
-  /* Do nothing, the current console state is ok.  */
-}
-
 static grub_err_t
-grub_ofconsole_init_input (struct grub_term_input *term __attribute__ ((unused)))
+grub_ofconsole_init_input (struct grub_term_input *term)
 {
   grub_ssize_t actual;
 
@@ -306,7 +135,7 @@ grub_ofconsole_init_input (struct grub_term_input *term __attribute__ ((unused))
       || actual != sizeof stdin_ihandle)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot find stdin");
 
-  return 0;
+  return grub_terminfo_input_init (term);
 }
 
 static grub_err_t
@@ -333,8 +162,8 @@ grub_ofconsole_init_output (struct grub_term_output *term)
        grub_ieee1275_set_color (stdout_ihandle, col, colors[col].red,
                                 colors[col].green, colors[col].blue);
 
-    /* Set the right fg and bg colors.  */
-      grub_ofconsole_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
+      /* Set the right fg and bg colors.  */
+      grub_terminfo_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
     }
 
   grub_ofconsole_dimensions ();
@@ -343,41 +172,73 @@ grub_ofconsole_init_output (struct grub_term_output *term)
 }
 
 \f
+
+struct grub_terminfo_input_state grub_ofconsole_terminfo_input =
+  {
+    .readkey = readkey
+  };
+
+struct grub_terminfo_output_state grub_ofconsole_terminfo_output =
+  {
+    .put = put
+  };
+
 static struct grub_term_input grub_ofconsole_term_input =
   {
     .name = "ofconsole",
     .init = grub_ofconsole_init_input,
-    .checkkey = grub_ofconsole_checkkey,
-    .getkey = grub_ofconsole_getkey,
+    .checkkey = grub_terminfo_checkkey,
+    .getkey = grub_terminfo_getkey,
+    .data = &grub_ofconsole_terminfo_input
   };
 
 static struct grub_term_output grub_ofconsole_term_output =
   {
     .name = "ofconsole",
     .init = grub_ofconsole_init_output,
-    .putchar = grub_ofconsole_putchar,
-    .getxy = grub_ofconsole_getxy,
+    .putchar = grub_terminfo_putchar,
+    .getxy = grub_terminfo_getxy,
     .getwh = grub_ofconsole_getwh,
-    .gotoxy = grub_ofconsole_gotoxy,
-    .cls = grub_ofconsole_cls,
-    .setcolorstate = grub_ofconsole_setcolorstate,
-    .setcolor = grub_ofconsole_setcolor,
-    .getcolor = grub_ofconsole_getcolor,
+    .gotoxy = grub_terminfo_gotoxy,
+    .cls = grub_terminfo_cls,
+    .setcolorstate = grub_terminfo_setcolorstate,
+    .setcolor = grub_terminfo_setcolor,
+    .getcolor = grub_terminfo_getcolor,
     .setcursor = grub_ofconsole_setcursor,
-    .refresh = grub_ofconsole_refresh,
-    .flags = GRUB_TERM_CODE_TYPE_ASCII
+    .flags = GRUB_TERM_CODE_TYPE_ASCII,
+    .data = &grub_ofconsole_terminfo_output
   };
 
+void grub_terminfo_fini (void);
+void grub_terminfo_init (void);
+
 void
-grub_console_init (void)
+grub_console_init_early (void)
 {
   grub_term_register_input ("ofconsole", &grub_ofconsole_term_input);
   grub_term_register_output ("ofconsole", &grub_ofconsole_term_output);
 }
 
+void
+grub_console_init_lately (void)
+{
+  const char *type;
+
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI))
+    type = "dumb";
+  else
+    type = "ieee1275";
+
+  grub_terminfo_init ();
+  grub_terminfo_output_register (&grub_ofconsole_term_output, type);
+}
+
 void
 grub_console_fini (void)
 {
   grub_term_unregister_input (&grub_ofconsole_term_input);
   grub_term_unregister_output (&grub_ofconsole_term_output);
+  grub_terminfo_output_unregister (&grub_ofconsole_term_output);
+
+  grub_terminfo_fini ();
 }
index 61bad192fd67f15cc5d7ee375f80750b4f8a8361..82bf6abb750a062000f5505081519bd067a1597d 100644 (file)
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
 
-#define TEXT_WIDTH     80
-#define TEXT_HEIGHT    24
-
-static unsigned int xpos, ypos;
-static unsigned int keep_track = 1;
 static unsigned int registered = 0;
 
-/* An input buffer.  */
-static int input_buf[GRUB_TERMINFO_READKEY_MAX_LEN];
-static int npending = 0;
-
-static struct grub_term_output grub_serial_term_output;
-
 /* Argument options.  */
 static const struct grub_arg_option options[] =
 {
@@ -152,35 +141,6 @@ serial_get_divisor (unsigned int speed)
   return 0;
 }
 
-/* The serial version of checkkey.  */
-static int
-grub_serial_checkkey (struct grub_term_input *term __attribute__ ((unused)))
-{
-  if (npending)
-    return input_buf[0];
-
-  grub_terminfo_readkey (input_buf, &npending, serial_hw_fetch);
-
-  if (npending)
-    return input_buf[0];
-
-  return -1;
-}
-
-/* The serial version of getkey.  */
-static int
-grub_serial_getkey (struct grub_term_input *term __attribute__ ((unused)))
-{
-  int ret;
-  while (! npending)
-    grub_terminfo_readkey (input_buf, &npending, serial_hw_fetch);
-
-  ret = input_buf[0];
-  npending--;
-  grub_memmove (input_buf, input_buf + 1, npending);
-  return ret;
-}
-
 /* Initialize a serial device. PORT is the port number for a serial device.
    SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
    19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
@@ -219,150 +179,56 @@ serial_hw_init (void)
 #endif
 
   /* Drain the input buffer.  */
-  while (grub_serial_checkkey (0) != -1)
-    (void) grub_serial_getkey (0);
+  while (serial_hw_fetch () != -1);
 
   /*  FIXME: should check if the serial terminal was found.  */
 
   return GRUB_ERR_NONE;
 }
 
-/* The serial version of putchar.  */
-static void
-grub_serial_putchar (struct grub_term_output *term __attribute__ ((unused)),
-                    const struct grub_unicode_glyph *c)
-{
-  /* Keep track of the cursor.  */
-  if (keep_track)
-    {
-      switch (c->base)
-       {
-       case '\a':
-         break;
-
-       case '\b':
-       case 127:
-         if (xpos > 0)
-           xpos--;
-         break;
-
-       case '\n':
-         if (ypos < TEXT_HEIGHT - 1)
-           ypos++;
-         break;
-
-       case '\r':
-         xpos = 0;
-         break;
-
-       default:
-         if ((c->base & 0xC0) == 0x80)
-           break;
-         if (xpos + c->estimated_width >= TEXT_WIDTH + 1)
-           {
-             xpos = 0;
-             if (ypos < TEXT_HEIGHT - 1)
-               ypos++;
-             serial_hw_put ('\r');
-             serial_hw_put ('\n');
-           }
-         xpos += c->estimated_width;
-         break;
-       }
-    }
-
-  serial_hw_put (c->base);
-}
-
 static grub_uint16_t
 grub_serial_getwh (struct grub_term_output *term __attribute__ ((unused)))
 {
+  const grub_uint8_t TEXT_WIDTH = 80;
+  const grub_uint8_t TEXT_HEIGHT = 24;
   return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
 }
 
-static grub_uint16_t
-grub_serial_getxy (struct grub_term_output *term __attribute__ ((unused)))
-{
-  return ((xpos << 8) | ypos);
-}
-
-static void
-grub_serial_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
-                   grub_uint8_t x, grub_uint8_t y)
-{
-  if (x > TEXT_WIDTH || y > TEXT_HEIGHT)
-    {
-      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y);
-    }
-  else
-    {
-      keep_track = 0;
-      grub_terminfo_gotoxy (x, y, &grub_serial_term_output);
-      keep_track = 1;
-
-      xpos = x;
-      ypos = y;
-    }
-}
-
-static void
-grub_serial_cls (struct grub_term_output *term __attribute__ ((unused)))
-{
-  keep_track = 0;
-  grub_terminfo_cls (&grub_serial_term_output);
-  keep_track = 1;
-
-  xpos = ypos = 0;
-}
-
-static void
-grub_serial_setcolorstate (struct grub_term_output *term __attribute__ ((unused)),
-                          const grub_term_color_state state)
-{
-  keep_track = 0;
-  switch (state)
-    {
-    case GRUB_TERM_COLOR_STANDARD:
-    case GRUB_TERM_COLOR_NORMAL:
-      grub_terminfo_reverse_video_off (&grub_serial_term_output);
-      break;
-    case GRUB_TERM_COLOR_HIGHLIGHT:
-      grub_terminfo_reverse_video_on (&grub_serial_term_output);
-      break;
-    default:
-      break;
-    }
-  keep_track = 1;
-}
+struct grub_terminfo_input_state grub_serial_terminfo_input =
+  {
+    .readkey = serial_hw_fetch
+  };
 
-static void
-grub_serial_setcursor (struct grub_term_output *term __attribute__ ((unused)),
-                      const int on)
-{
-  if (on)
-    grub_terminfo_cursor_on (&grub_serial_term_output);
-  else
-    grub_terminfo_cursor_off (&grub_serial_term_output);
-}
+struct grub_terminfo_output_state grub_serial_terminfo_output =
+  {
+    .put = serial_hw_put,
+    .normal_color = 0x7,
+    .highlight_color = 0x70
+  };
 
 static struct grub_term_input grub_serial_term_input =
 {
   .name = "serial",
-  .checkkey = grub_serial_checkkey,
-  .getkey = grub_serial_getkey,
+  .init = grub_terminfo_input_init,
+  .checkkey = grub_terminfo_checkkey,
+  .getkey = grub_terminfo_getkey,
+  .data = &grub_serial_terminfo_input
 };
 
 static struct grub_term_output grub_serial_term_output =
 {
   .name = "serial",
-  .putchar = grub_serial_putchar,
+  .putchar = grub_terminfo_putchar,
   .getwh = grub_serial_getwh,
-  .getxy = grub_serial_getxy,
-  .gotoxy = grub_serial_gotoxy,
-  .cls = grub_serial_cls,
-  .setcolorstate = grub_serial_setcolorstate,
-  .setcursor = grub_serial_setcursor,
+  .getxy = grub_terminfo_getxy,
+  .gotoxy = grub_terminfo_gotoxy,
+  .cls = grub_terminfo_cls,
+  .setcolorstate = grub_terminfo_setcolorstate,
+  .setcolor = grub_terminfo_setcolor,
+  .getcolor = grub_terminfo_getcolor,
+  .setcursor = grub_terminfo_setcursor,
   .flags = GRUB_TERM_CODE_TYPE_ASCII,
+  .data = &grub_serial_terminfo_output
 };
 
 \f
@@ -466,6 +332,7 @@ grub_cmd_serial (grub_extcmd_t cmd,
        {
          grub_term_register_input ("serial", &grub_serial_term_input);
          grub_term_register_output ("serial", &grub_serial_term_output);
+         grub_terminfo_output_register (&grub_serial_term_output, "vt100");
          registered = 1;
        }
     }
@@ -482,6 +349,7 @@ grub_cmd_serial (grub_extcmd_t cmd,
              /* If unable to restore settings, unregister terminal.  */
              grub_term_unregister_input (&grub_serial_term_input);
              grub_term_unregister_output (&grub_serial_term_output);
+             grub_terminfo_output_unregister (&grub_serial_term_output);
              registered = 0;
            }
        }
@@ -518,5 +386,6 @@ GRUB_MOD_FINI(serial)
     {
       grub_term_unregister_input (&grub_serial_term_input);
       grub_term_unregister_output (&grub_serial_term_output);
+      grub_terminfo_output_unregister (&grub_serial_term_output);
     }
 }
index eb14d47f1f148b1d1b27d00f62f766f234c39ac9..f0e234106134f512ba23a4a2e270513aa5e7c544 100644 (file)
 #include <grub/i18n.h>
 #include <grub/time.h>
 
-struct terminfo
-{
-  char *name;
-
-  char *gotoxy;
-  char *cls;
-  char *reverse_video_on;
-  char *reverse_video_off;
-  char *cursor_on;
-  char *cursor_off;
-};
-
-static struct terminfo term;
+static struct grub_term_output *terminfo_outputs;
 
 /* Get current terminfo name.  */
 char *
-grub_terminfo_get_current (void)
+grub_terminfo_get_current (struct grub_term_output *term)
 {
-  return term.name;
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+  return data->name;
 }
 
 /* Free *PTR and set *PTR to NULL, to prevent double-free.  */
@@ -63,10 +53,29 @@ grub_terminfo_free (char **ptr)
   *ptr = 0;
 }
 
+static void
+grub_terminfo_all_free (struct grub_term_output *term)
+{
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  /* Free previously allocated memory.  */
+  grub_terminfo_free (&data->name);
+  grub_terminfo_free (&data->gotoxy);
+  grub_terminfo_free (&data->cls);
+  grub_terminfo_free (&data->reverse_video_on);
+  grub_terminfo_free (&data->reverse_video_off);
+  grub_terminfo_free (&data->cursor_on);
+  grub_terminfo_free (&data->cursor_off);
+}
+
 /* Set current terminfo type.  */
 grub_err_t
-grub_terminfo_set_current (const char *str)
+grub_terminfo_set_current (struct grub_term_output *term,
+                          const char *str)
 {
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
   /* TODO
    * Lookup user specified terminfo type. If found, set term variables
    * as appropriate. Otherwise return an error.
@@ -84,93 +93,290 @@ grub_terminfo_set_current (const char *str)
    *  d. Your idea here.
    */
 
-  /* Free previously allocated memory.  */
-  grub_terminfo_free (&term.name);
-  grub_terminfo_free (&term.gotoxy);
-  grub_terminfo_free (&term.cls);
-  grub_terminfo_free (&term.reverse_video_on);
-  grub_terminfo_free (&term.reverse_video_off);
-  grub_terminfo_free (&term.cursor_on);
-  grub_terminfo_free (&term.cursor_off);
+  grub_terminfo_all_free (term);
 
   if (grub_strcmp ("vt100", str) == 0)
     {
-      term.name              = grub_strdup ("vt100");
-      term.gotoxy            = grub_strdup ("\e[%i%p1%d;%p2%dH");
-      term.cls               = grub_strdup ("\e[H\e[J");
-      term.reverse_video_on  = grub_strdup ("\e[7m");
-      term.reverse_video_off = grub_strdup ("\e[m");
-      term.cursor_on         = grub_strdup ("\e[?25h");
-      term.cursor_off        = grub_strdup ("\e[?25l");
+      data->name              = grub_strdup ("vt100");
+      data->gotoxy            = grub_strdup ("\e[%i%p1%d;%p2%dH");
+      data->cls               = grub_strdup ("\e[H\e[J");
+      data->reverse_video_on  = grub_strdup ("\e[7m");
+      data->reverse_video_off = grub_strdup ("\e[m");
+      data->cursor_on         = grub_strdup ("\e[?25h");
+      data->cursor_off        = grub_strdup ("\e[?25l");
+      data->setcolor          = NULL;
+      return grub_errno;
+    }
+
+  if (grub_strcmp ("vt100-color", str) == 0)
+    {
+      data->name              = grub_strdup ("vt100-color");
+      data->gotoxy            = grub_strdup ("\e[%i%p1%d;%p2%dH");
+      data->cls               = grub_strdup ("\e[H\e[J");
+      data->reverse_video_on  = grub_strdup ("\e[7m");
+      data->reverse_video_off = grub_strdup ("\e[m");
+      data->cursor_on         = grub_strdup ("\e[?25h");
+      data->cursor_off        = grub_strdup ("\e[?25l");
+      data->setcolor          = grub_strdup ("\e[3%p1%dm\e[4%p2%dm");
+      return grub_errno;
+    }
+
+  if (grub_strcmp ("ieee1275", str) == 0)
+    {
+      data->name              = grub_strdup ("ieee1275");
+      data->gotoxy            = grub_strdup ("\e[%i%p1%d;%p2%dH");
+      /* Clear the screen.  Using serial console, screen(1) only recognizes the
+       * ANSI escape sequence.  Using video console, Apple Open Firmware
+       * (version 3.1.1) only recognizes the literal ^L.  So use both.  */
+      data->cls               = grub_strdup ("\f\e[2J");
+      data->reverse_video_on  = grub_strdup ("\e[7m");
+      data->reverse_video_off = grub_strdup ("\e[m");
+      data->cursor_on         = grub_strdup ("\e[?25h");
+      data->cursor_off        = grub_strdup ("\e[?25l");
+      data->setcolor          = grub_strdup ("\e[3%p1%dm\e[4%p2%dm");
+      return grub_errno;
+    }
+
+  if (grub_strcmp ("dumb", str) == 0)
+    {
+      data->name              = grub_strdup ("dumb");
+      data->gotoxy            = NULL;
+      data->cls               = NULL;
+      data->reverse_video_on  = NULL;
+      data->reverse_video_off = NULL;
+      data->cursor_on         = NULL;
+      data->cursor_off        = NULL;
+      data->setcolor          = NULL;
       return grub_errno;
     }
 
   return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminfo type");
 }
 
+grub_err_t
+grub_terminfo_output_register (struct grub_term_output *term,
+                              const char *type)
+{
+  grub_err_t err;
+  struct grub_terminfo_output_state *data;
+
+  err = grub_terminfo_set_current (term, type);
+
+  if (err)
+    return err;
+
+  data = (struct grub_terminfo_output_state *) term->data;
+  data->next = terminfo_outputs;
+  terminfo_outputs = term;
+  
+  data->normal_color = 0x07;
+  data->highlight_color = 0x70;
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_terminfo_output_unregister (struct grub_term_output *term)
+{
+  struct grub_term_output **ptr;
+
+  for (ptr = &terminfo_outputs; *ptr;
+       ptr = &((struct grub_terminfo_output_state *) (*ptr)->data)->next)
+    if (*ptr == term)
+      {
+       grub_terminfo_all_free (term);
+       *ptr = ((struct grub_terminfo_output_state *) (*ptr)->data)->next;
+       return GRUB_ERR_NONE;
+      }
+  return grub_error (GRUB_ERR_BAD_ARGUMENT, "terminal not found");
+}
+
 /* Wrapper for grub_putchar to write strings.  */
 static void
-putstr (const char *str, grub_term_output_t oterm)
+putstr (struct grub_term_output *term, const char *str)
 {
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
   while (*str)
+    data->put (*str++);
+}
+
+grub_uint16_t
+grub_terminfo_getxy (struct grub_term_output *term)
+{
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  return ((data->xpos << 8) | data->ypos);
+}
+
+void
+grub_terminfo_gotoxy (struct grub_term_output *term,
+                     grub_uint8_t x, grub_uint8_t y)
+{
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  if (x > grub_term_width (term) || y > grub_term_height (term))
     {
-      struct grub_unicode_glyph c =
-       {
-         .base = *str++,
-         .variant = 0,
-         .attributes = 0,
-         .ncomb = 0,
-         .combining = 0
-       };
-      oterm->putchar (oterm, &c);
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y);
+      return;
+    }
+
+  if (data->gotoxy)
+    putstr (term, grub_terminfo_tparm (data->gotoxy, y, x));
+  else
+    {
+      if ((y == data->ypos) && (x == data->xpos - 1))
+       data->put ('\b');
     }
+
+  data->xpos = x;
+  data->ypos = y;
 }
 
-/* Move the cursor to the given position starting with "0".  */
+/* Clear the screen.  */
 void
-grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, grub_term_output_t oterm)
+grub_terminfo_cls (struct grub_term_output *term)
 {
-  putstr (grub_terminfo_tparm (term.gotoxy, y, x), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  putstr (term, grub_terminfo_tparm (data->cls));
+
+  data->xpos = data->ypos = 0;
 }
 
-/* Clear the screen.  */
 void
-grub_terminfo_cls (grub_term_output_t oterm)
+grub_terminfo_setcolor (struct grub_term_output *term,
+                       grub_uint8_t normal_color,
+                       grub_uint8_t highlight_color)
 {
-  putstr (grub_terminfo_tparm (term.cls), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  /* Discard bright bit.  */
+  data->normal_color = normal_color & 0x77;
+  data->highlight_color = highlight_color & 0x77;
 }
 
-/* Set reverse video mode on.  */
 void
-grub_terminfo_reverse_video_on (grub_term_output_t oterm)
+grub_terminfo_getcolor (struct grub_term_output *term,
+                       grub_uint8_t *normal_color,
+                       grub_uint8_t *highlight_color)
 {
-  putstr (grub_terminfo_tparm (term.reverse_video_on), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  *normal_color = data->normal_color;
+  *highlight_color = data->highlight_color;
 }
 
-/* Set reverse video mode off.  */
 void
-grub_terminfo_reverse_video_off (grub_term_output_t oterm)
+grub_terminfo_setcolorstate (struct grub_term_output *term,
+                            const grub_term_color_state state)
 {
-  putstr (grub_terminfo_tparm (term.reverse_video_off), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  if (data->setcolor)
+    {
+      int fg;
+      int bg;
+
+      switch (state)
+       {
+       case GRUB_TERM_COLOR_STANDARD:
+       case GRUB_TERM_COLOR_NORMAL:
+         fg = data->normal_color & 0x0f;
+         bg = data->normal_color >> 4;
+         break;
+       case GRUB_TERM_COLOR_HIGHLIGHT:
+         fg = data->highlight_color & 0x0f;
+         bg = data->highlight_color >> 4;
+         break;
+       default:
+         return;
+       }
+
+      putstr (term, grub_terminfo_tparm (data->setcolor, fg, bg));
+      return;
+    }
+
+  switch (state)
+    {
+    case GRUB_TERM_COLOR_STANDARD:
+    case GRUB_TERM_COLOR_NORMAL:
+      putstr (term, grub_terminfo_tparm (data->reverse_video_off));
+      break;
+    case GRUB_TERM_COLOR_HIGHLIGHT:
+      putstr (term, grub_terminfo_tparm (data->reverse_video_on));
+      break;
+    default:
+      break;
+    }
 }
 
-/* Show cursor.  */
 void
-grub_terminfo_cursor_on (grub_term_output_t oterm)
+grub_terminfo_setcursor (struct grub_term_output *term, const int on)
 {
-  putstr (grub_terminfo_tparm (term.cursor_on), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  if (on)
+    putstr (term, grub_terminfo_tparm (data->cursor_on));
+  else
+    putstr (term, grub_terminfo_tparm (data->cursor_off));
 }
 
-/* Hide cursor.  */
+/* The terminfo version of putchar.  */
 void
-grub_terminfo_cursor_off (grub_term_output_t oterm)
+grub_terminfo_putchar (struct grub_term_output *term,
+                      const struct grub_unicode_glyph *c)
 {
-  putstr (grub_terminfo_tparm (term.cursor_off), oterm);
+  struct grub_terminfo_output_state *data
+    = (struct grub_terminfo_output_state *) term->data;
+
+  /* Keep track of the cursor.  */
+  switch (c->base)
+    {
+    case '\a':
+      break;
+
+    case '\b':
+    case 127:
+      if (data->xpos > 0)
+       data->xpos--;
+    break;
+
+    case '\n':
+      if (data->ypos < grub_term_height (term) - 1)
+       data->ypos++;
+      break;
+
+    case '\r':
+      data->xpos = 0;
+      break;
+
+    default:
+      if (data->xpos + c->estimated_width >= grub_term_width (term) + 1)
+       {
+         data->xpos = 0;
+         if (data->ypos < grub_term_height (term) - 1)
+           data->ypos++;
+         data->put ('\r');
+         data->put ('\n');
+       }
+      data->xpos += c->estimated_width;
+      break;
+    }
+
+  data->put (c->base);
 }
 
 #define ANSI_C0 0x9b
 
-void
+static void
 grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void))
 {
   int c;
@@ -276,21 +482,80 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void))
 #undef CONTINUE_READ
 }
 
+/* The terminfo version of checkkey.  */
+int
+grub_terminfo_checkkey (struct grub_term_input *termi)
+{
+  struct grub_terminfo_input_state *data
+    = (struct grub_terminfo_input_state *) (termi->data);
+  if (data->npending)
+    return data->input_buf[0];
+
+  grub_terminfo_readkey (data->input_buf, &data->npending, data->readkey);
+
+  if (data->npending)
+    return data->input_buf[0];
+
+  return -1;
+}
+
+/* The terminfo version of getkey.  */
+int
+grub_terminfo_getkey (struct grub_term_input *termi)
+{
+  struct grub_terminfo_input_state *data
+    = (struct grub_terminfo_input_state *) (termi->data);
+  int ret;
+  while (! data->npending)
+    grub_terminfo_readkey (data->input_buf, &data->npending, data->readkey);
+
+  ret = data->input_buf[0];
+  data->npending--;
+  grub_memmove (data->input_buf, data->input_buf + 1, data->npending);
+  return ret;
+}
+
+grub_err_t
+grub_terminfo_input_init (struct grub_term_input *termi)
+{
+  struct grub_terminfo_input_state *data
+    = (struct grub_terminfo_input_state *) (termi->data);
+  data->npending = 0;
+
+  return GRUB_ERR_NONE;
+}
+
 /* GRUB Command.  */
 
 static grub_err_t
 grub_cmd_terminfo (grub_command_t cmd __attribute__ ((unused)),
                   int argc, char **args)
 {
+  struct grub_term_output *cur;
+
   if (argc == 0)
-  {
-    grub_printf ("Current terminfo type: %s\n", grub_terminfo_get_current());
-    return GRUB_ERR_NONE;
-  }
-  else if (argc != 1)
+    {
+      grub_printf ("Current terminfo types: \n");
+      for (cur = terminfo_outputs; cur;
+          cur = ((struct grub_terminfo_output_state *) cur->data)->next)
+       grub_printf ("%s: %s\n", cur->name,
+                    grub_terminfo_get_current(cur));
+
+      return GRUB_ERR_NONE;
+    }
+
+  if (argc == 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few parameters");
+  if (argc != 2)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters");
-  else
-    return grub_terminfo_set_current (args[0]);
+
+  for (cur = terminfo_outputs; cur;
+       cur = ((struct grub_terminfo_output_state *) cur->data)->next)
+    if (grub_strcmp (args[0], cur->name) == 0)
+      return grub_terminfo_set_current (cur, args[1]);
+  return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                    "no terminal %s found or it's not handled by terminfo",
+                    args[0]);
 }
 
 static grub_command_t cmd;
@@ -298,8 +563,7 @@ static grub_command_t cmd;
 GRUB_MOD_INIT(terminfo)
 {
   cmd = grub_register_command ("terminfo", grub_cmd_terminfo,
-                              N_("[TERM]"), N_("Set terminfo type."));
-  grub_terminfo_set_current ("vt100");
+                              N_("[TERM TYPE]"), N_("Set terminfo type of TERM  to TYPE."));
 }
 
 GRUB_MOD_FINI(terminfo)
index adf0b3a7c010744f5e21eeddab73662a617c38e5..076a192a5bf515c6cb98c1671565d935b54dadd9 100644 (file)
@@ -751,6 +751,9 @@ grub_terminfo_tparm (const char *string, ...)
     va_list ap;
     char *result;
 
+    if (!string)
+      return "";
+
     va_start (ap, string);
     result = tparam_internal (string, ap);
     va_end (ap);