]> git.proxmox.com Git - grub2.git/commitdiff
2009-06-04 Vladimir Serbinenko <phcoder@gmail.com>
authorphcoder <phcoder@localhost>
Thu, 4 Jun 2009 18:22:45 +0000 (18:22 +0000)
committerphcoder <phcoder@localhost>
Thu, 4 Jun 2009 18:22:45 +0000 (18:22 +0000)
gfxpayload support

* commands/videotest.c (grub_cmd_videotest): use grub_video_set_mode
* include/grub/video.h (GRUB_VIDEO_MODE_TYPE_PURE_TEXT): new definition
(grub_video_setup): remove
(grub_video_set_mode): new prototype
* loader/i386/linux.c (DEFAULT_VIDEO_MODE): new definition
(vid_mode): remove
(linux_vesafb_res): compile only on PCBIOS
(grub_linux_boot): support gfxpayload
* loader/i386/pc/xnu.c (video_hook): new function
(grub_xnu_set_video): support gfxpayload
* term/gfxterm.c (DEFAULT_VIDEO_WIDTH): removed
(DEFAULT_VIDEO_HEIGHT): likewise
(DEFAULT_VIDEO_FLAGS): likewise
(DEFAULT_VIDEO_MODE): new definition
(video_hook): new function
(grub_gfxterm_init): use grub_video_set_mode
* util/grub.d/30_os-prober.in: remove explicit modesetting before
loading xnu
* video/video.c (grub_video_setup): removed
(grub_video_set_mode): new function based on grub_gfxterm_init and
grub_video_setup

ChangeLog
commands/videotest.c
include/grub/video.h
loader/i386/linux.c
loader/i386/pc/xnu.c
term/gfxterm.c
util/grub.d/30_os-prober.in
video/video.c

index 45e92c8cc5f4a708b4a6c959d0162bd519f52704..23f629638729415b15f190f4458bc839ae5bbfb4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2009-06-04  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       gfxpayload support
+
+       * commands/videotest.c (grub_cmd_videotest): use grub_video_set_mode
+       * include/grub/video.h (GRUB_VIDEO_MODE_TYPE_PURE_TEXT): new definition
+       (grub_video_setup): remove
+       (grub_video_set_mode): new prototype
+       * loader/i386/linux.c (DEFAULT_VIDEO_MODE): new definition
+       (vid_mode): remove
+       (linux_vesafb_res): compile only on PCBIOS
+       (grub_linux_boot): support gfxpayload
+       * loader/i386/pc/xnu.c (video_hook): new function
+       (grub_xnu_set_video): support gfxpayload
+       * term/gfxterm.c (DEFAULT_VIDEO_WIDTH): removed
+       (DEFAULT_VIDEO_HEIGHT): likewise
+       (DEFAULT_VIDEO_FLAGS): likewise
+       (DEFAULT_VIDEO_MODE): new definition
+       (video_hook): new function
+       (grub_gfxterm_init): use grub_video_set_mode
+       * util/grub.d/30_os-prober.in: remove explicit modesetting before 
+       loading xnu
+       * video/video.c (grub_video_setup): removed
+       (grub_video_set_mode): new function based on grub_gfxterm_init and 
+       grub_video_setup
+
 2009-06-04  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Avoid calling biosdisk in drivemap
index db7f704ed65f31b49a2fa319ce7af15188b1b096..6fe4b9bd1e560031bdb0e9c10e2b7e64642bf234 100644 (file)
@@ -30,8 +30,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
                     int argc __attribute__ ((unused)),
                     char **args __attribute__ ((unused)))
 {
-  if (grub_video_setup (1024, 768,
-                        GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != GRUB_ERR_NONE)
+  if (grub_video_set_mode ("1024x768;800x600;640x480", 0) != GRUB_ERR_NONE)
     return grub_errno;
 
   grub_video_color_t color;
index cb73dae216e4021631922264a45082f752c1ea57..3b276553c54bd49df5d5301f5a2807e47216ee6a 100644 (file)
@@ -34,6 +34,7 @@ struct grub_video_render_target;
 struct grub_video_bitmap;
 
 /* Defines used to describe video mode or rendering target.  */
+#define GRUB_VIDEO_MODE_TYPE_PURE_TEXT         0x00000040
 #define GRUB_VIDEO_MODE_TYPE_ALPHA             0x00000020
 #define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED   0x00000010
 #define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP       0x00000004
@@ -236,9 +237,6 @@ void grub_video_register (grub_video_adapter_t adapter);
 void grub_video_unregister (grub_video_adapter_t adapter);
 void grub_video_iterate (int (*hook) (grub_video_adapter_t adapter));
 
-grub_err_t grub_video_setup (unsigned int width, unsigned int height,
-                             unsigned int mode_type);
-
 grub_err_t grub_video_restore (void);
 
 grub_err_t grub_video_get_info (struct grub_video_mode_info *mode_info);
@@ -299,4 +297,8 @@ grub_err_t grub_video_set_active_render_target (struct grub_video_render_target
 
 grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target);
 
+grub_err_t grub_video_set_mode (char *modestring,
+                               int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
+                                                             struct grub_video_mode_info *mode_info));
+
 #endif /* ! GRUB_VIDEO_HEADER */
index ca44fb46f8428f10b2d40b17c0022ca70bdf7ba4..e3726ec8125b28f14d703cb6a3ef491d6aa6e0c0 100644 (file)
    into Linux, and therefore can benefit from seamless mode transition between
    GRUB and Linux (saving boot time and visual glitches).  Official GRUB, OTOH,
    needs to be conservative.  */
-#ifndef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
-#define GRUB_ASSUME_LINUX_HAS_FB_SUPPORT 0
+#ifdef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
+#define DEFAULT_VIDEO_MODE "keep,1024x768,800x600,640x480"
+#else
+#define DEFAULT_VIDEO_MODE "text"
 #endif
 
 static grub_dl_t my_mod;
@@ -94,8 +96,7 @@ static struct idt_descriptor idt_desc =
     0
   };
 
-static grub_uint16_t vid_mode;
-
+#ifdef GRUB_MACHINE_PCBIOS
 struct linux_vesafb_res
 {
   grub_uint16_t width;
@@ -262,6 +263,7 @@ struct linux_vesafb_mode linux_vesafb_modes[] =
     { VGA_800_500, 24 },       /* 0x372 */
     { VGA_800_500, 32 },       /* 0x373 */
   };
+#endif
 
 static inline grub_size_t
 page_align (grub_size_t size)
@@ -442,49 +444,37 @@ grub_linux_boot (void)
 {
   struct linux_kernel_params *params;
   int e820_num;
-  
+  grub_err_t err;
+  char *modevar, *tmp;
+
   params = real_mode_mem;
 
-  if (vid_mode == GRUB_LINUX_VID_MODE_NORMAL || vid_mode == GRUB_LINUX_VID_MODE_EXTENDED)
-    grub_video_restore ();
-  else if (vid_mode)
+  modevar = grub_env_get ("gfxpayload");
+
+  /* Now all graphical modes are acceptable. 
+     May change in future if we have modes without framebuffer.  */
+  if (modevar && *modevar != 0)
     {
-      struct linux_vesafb_mode *linux_mode;
-      int depth, flags;
-      
-      flags = 0;
-      linux_mode = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START];
-      depth = linux_mode->depth;
-      
-      /* If we have 8 or less bits, then assume that it is indexed color mode.  */
-      if ((depth <= 8) && (depth != -1))
-       flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
-      
-      /* We have more than 8 bits, then assume that it is RGB color mode.  */
-      if (depth > 8)
-       flags |= GRUB_VIDEO_MODE_TYPE_RGB;
-      
-      /* If user requested specific depth, forward that information to driver.  */
-      if (depth != -1)
-       flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
-         & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
-      
-      /* Try to initialize requested mode.  */
-      if (grub_video_setup (linux_vesafb_res[linux_mode->res_index].width,
-                           linux_vesafb_res[linux_mode->res_index].height,
-                           flags) != GRUB_ERR_NONE)
-       {
-         grub_printf ("Unable to initialize requested video mode (vga=0x%x)\n", vid_mode);
-         return grub_errno;
-       }
+      tmp = grub_malloc (grub_strlen (modevar) 
+                        + sizeof (DEFAULT_VIDEO_MODE) + 1);
+      if (! tmp)
+       return grub_errno;
+      grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+      err = grub_video_set_mode (tmp, 0);
+      grub_free (tmp);
     }
-#if ! GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
+#ifndef GRUB_ASSUME_LINUX_HAS_FB_SUPPORT
   else
-    /* If user didn't request a video mode, and we can't assume Linux supports FB,
-       then we go back to text mode.  */
-    grub_video_restore ();
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
 #endif
 
+  if (err)
+    {
+      grub_print_error ();
+      grub_printf ("Booting however\n");
+      grub_errno = GRUB_ERR_NONE;
+    }
+
   if (! grub_linux_setup_video (params))
     params->have_vga = GRUB_VIDEO_TYPE_VLFB;
   else
@@ -708,7 +698,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
               (unsigned) real_size, (unsigned) prot_size);
 
   /* Look for memory size and video mode specified on the command line.  */
-  vid_mode = 0;
   linux_mem_size = 0;
   for (i = 1; i < argc; i++)
 #ifdef GRUB_MACHINE_PCBIOS
@@ -716,6 +705,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       {
        /* Video mode selection support.  */
        char *val = argv[i] + 4;
+       unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+       struct linux_vesafb_mode *linux_mode;
+       grub_err_t err;
+       char *buf;
 
        if (grub_strcmp (val, "normal") == 0)
          vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
@@ -737,21 +730,57 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
        switch (vid_mode)
          {
          case 0:
-           vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+         case GRUB_LINUX_VID_MODE_NORMAL:
+           grub_env_set ("gfxpayload", "text");
+           grub_printf ("%s is deprecated. "
+                        "Use set gfxpayload=text before "
+                        "linux command instead.\n", 
+                        argv[i]);      
            break;
+
          case 1:
-           vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
+         case GRUB_LINUX_VID_MODE_EXTENDED:
+           /* FIXME: support 80x50 text. */
+           grub_env_set ("gfxpayload", "text");
+           grub_printf ("%s is deprecated. "
+                        "Use set gfxpayload=text before "
+                        "linux command instead.\n", 
+                        argv[i]);      
            break;
          default:
            /* Ignore invalid values.  */
            if (vid_mode < GRUB_LINUX_VID_MODE_VESA_START ||
                vid_mode >= GRUB_LINUX_VID_MODE_VESA_START +
                ARRAY_SIZE (linux_vesafb_modes))
-             vid_mode = 0;
-         }
+             {
+               grub_env_set ("gfxpayload", "text");
+               grub_printf ("%s is deprecated. Mode %d isn't recognized. "
+                            "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] before "
+                            "linux command instead.\n", 
+                            argv[i], vid_mode);        
+               break;
+             }
 
-       if (grub_errno)
-         goto fail;
+           buf = grub_malloc (20);
+           if (! buf)
+             goto fail;
+           
+           linux_mode 
+             = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START];
+           
+           grub_sprintf (buf, "%dx%dx%d", 
+                         linux_vesafb_res[linux_mode->res_index].width,
+                         linux_vesafb_res[linux_mode->res_index].height,
+                         linux_mode->depth);
+           grub_printf ("%s is deprecated. "
+                        "Use set gfxpayload=%s before "
+                        "linux command instead.\n", 
+                        argv[i], buf); 
+           err = grub_env_set ("gfxpayload", buf);
+           grub_free (buf);
+           if (err)
+             goto fail;
+         }
       }
     else
 #endif /* GRUB_MACHINE_PCBIOS */
index 1cca1387e5ca6c91efa8c43827d7da69b08d7bb5..d32f6793b82817580d13cbbeb53475d4cd35732b 100644 (file)
@@ -19,6 +19,7 @@
 #include <grub/env.h>
 #include <grub/misc.h>
 #include <grub/xnu.h>
+#include <grub/mm.h>
 #include <grub/cpu/xnu.h>
 #include <grub/machine/vbe.h>
 #include <grub/machine/vga.h>
 #define min(a,b) (((a) < (b)) ? (a) : (b))
 #define max(a,b) (((a) > (b)) ? (a) : (b))
 
+#define DEFAULT_VIDEO_MODE "1024x768x32,800x600x32,640x480x32"
+
+static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)),
+                                       struct grub_video_mode_info *info)
+{
+  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
+    return 0;
+
+  return 1;
+}
+
 /* Setup video for xnu. */
 grub_err_t
 grub_xnu_set_video (struct grub_xnu_boot_params *params)
@@ -34,8 +46,27 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params)
   struct grub_video_render_target *render_target;
   int ret;
   int x,y;
+  char *tmp, *modevar;
   grub_err_t err;
 
+  modevar = grub_env_get ("gfxpayload");
+  if (! modevar || *modevar == 0)
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook);
+  else
+    {
+      tmp = grub_malloc (grub_strlen (modevar) 
+                        + sizeof (DEFAULT_VIDEO_MODE) + 1);
+      if (! tmp)
+       return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                          "couldn't allocate temporary storag");
+      grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+      err = grub_video_set_mode (tmp, video_hook);
+      grub_free (tmp);
+    }
+
+  if (err)
+    return err;
+
   ret = grub_video_get_info (&mode_info);
   if (ret)
     return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters");
index e6baa159f965ca64ce3177eb69b233319639c96a..5da678846c942f3e3f7fe1fa19c14dd9f3a17830 100644 (file)
 #include <grub/bitmap.h>
 #include <grub/command.h>
 
-#define DEFAULT_VIDEO_WIDTH    640
-#define DEFAULT_VIDEO_HEIGHT   480
-#define DEFAULT_VIDEO_FLAGS    0
-
+#define DEFAULT_VIDEO_MODE "1024x768,800x600,640x480"
 #define DEFAULT_BORDER_WIDTH   10
 
 #define DEFAULT_STANDARD_COLOR  0x07
@@ -231,16 +228,22 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
   return grub_errno;
 }
 
+static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)),
+                                       struct grub_video_mode_info *info)
+{
+  return ! (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT);
+}
+
 static grub_err_t
 grub_gfxterm_init (void)
 {
   char *font_name;
   char *modevar;
-  int width = DEFAULT_VIDEO_WIDTH;
-  int height = DEFAULT_VIDEO_HEIGHT;
-  int depth = -1;
-  int flags = DEFAULT_VIDEO_FLAGS;
+  char *tmp;
   grub_video_color_t color;
+  int width;
+  int height;
+  grub_err_t err;
 
   /* Select the font to use. */
   font_name = grub_env_get ("gfxterm_font");
@@ -249,231 +252,24 @@ grub_gfxterm_init (void)
 
   /* Parse gfxmode environment variable if set.  */
   modevar = grub_env_get ("gfxmode");
-  if (modevar)
-    {
-      char *tmp;
-      char *next_mode;
-      char *current_mode;
-      char *param;
-      char *value;
-      int mode_found = 0;
-
-      /* Take copy of env.var. as we don't want to modify that.  */
-      tmp = grub_strdup (modevar);
-      modevar = tmp;
-
-      if (grub_errno != GRUB_ERR_NONE)
-        return grub_errno;
-        
-      /* Initialize next mode.  */
-      next_mode = modevar;
-      
-      /* Loop until all modes has been tested out.  */
-      while (next_mode != NULL)
-        {
-          /* Use last next_mode as current mode.  */
-          tmp = next_mode;
-          
-          /* Reset video mode settings.  */
-          width = DEFAULT_VIDEO_WIDTH;
-          height = DEFAULT_VIDEO_HEIGHT;
-          depth = -1;
-          flags = DEFAULT_VIDEO_FLAGS;
-        
-          /* Save position of next mode and separate modes.  */
-          next_mode = grub_strchr(next_mode, ';');
-          if (next_mode)
-            {
-              *next_mode = 0;
-              next_mode++;
-            }
-
-          /* Skip whitespace.  */
-          while (grub_isspace (*tmp))
-            tmp++;
-
-          /* Initialize token holders.  */
-          current_mode = tmp;
-          param = tmp;
-          value = NULL;
-
-          /* Parse <width>x<height>[x<depth>]*/
-
-          /* Find width value.  */
-          value = param;
-          param = grub_strchr(param, 'x');
-          if (param == NULL)
-            {
-              grub_err_t rc;
-              
-              /* First setup error message.  */
-             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                               "Invalid mode: %s\n",
-                               current_mode);
-              
-              /* Free memory before returning.  */
-              grub_free (modevar);
-              
-              return rc;
-            }
-
-          *param = 0;
-          param++;
-
-          width = grub_strtoul (value, 0, 0);
-          if (grub_errno != GRUB_ERR_NONE)
-            {
-              grub_err_t rc;
-              
-              /* First setup error message.  */
-             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                               "Invalid mode: %s\n",
-                               current_mode);
-              
-              /* Free memory before returning.  */
-              grub_free (modevar);
-              
-              return rc;
-            }
-
-          /* Find height value.  */
-          value = param;
-          param = grub_strchr(param, 'x');
-          if (param == NULL)
-            {
-              height = grub_strtoul (value, 0, 0);
-              if (grub_errno != GRUB_ERR_NONE)
-                {
-                  grub_err_t rc;
-
-                  /* First setup error message.  */
-                 rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                                   "Invalid mode: %s\n",
-                                   current_mode);
-
-                  /* Free memory before returning.  */
-                  grub_free (modevar);
-
-                 return rc;
-               }
-            }
-         else
-            {
-             /* We have optional color depth value.  */
-             *param = 0;
-             param++;
-
-             height = grub_strtoul (value, 0, 0);
-             if (grub_errno != GRUB_ERR_NONE)
-               {
-                 grub_err_t rc;
-
-                 /* First setup error message.  */
-                 rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                                  "Invalid mode: %s\n",
-                                  current_mode);
-
-                 /* Free memory before returning.  */
-                 grub_free (modevar);
-
-                 return rc;
-               }
-
-             /* Convert color depth value.  */
-             value = param;
-             depth = grub_strtoul (value, 0, 0);
-             if (grub_errno != GRUB_ERR_NONE)
-               {
-                 grub_err_t rc;
-
-                 /* First setup error message.  */
-                 rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
-                                  "Invalid mode: %s\n",
-                                  current_mode);
-
-                 /* Free memory before returning.  */
-                 grub_free (modevar);
-
-                 return rc;
-               }
-            }
-
-         /* Try out video mode.  */
-
-         /* If we have 8 or less bits, then assume that it is indexed color mode.  */
-         if ((depth <= 8) && (depth != -1))
-           flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
-
-         /* We have more than 8 bits, then assume that it is RGB color mode.  */
-         if (depth > 8)
-           flags |= GRUB_VIDEO_MODE_TYPE_RGB;
-
-         /* If user requested specific depth, forward that information to driver.  */
-         if (depth != -1)
-           flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
-                    & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
-
-         /* Try to initialize requested mode.  Ignore any errors.  */
-         grub_error_push ();
-         if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
-           {
-             grub_error_pop ();
-             continue;
-           }
-
-         /* Figure out what mode we ended up.  */
-         if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
-           {
-             /* Couldn't get video mode info, restore old mode and continue to next one.  */
-             grub_error_pop ();
-
-             grub_video_restore ();
-             continue;
-           }
-          
-          /* Restore state of error stack.  */
-          grub_error_pop ();
-          
-          /* Mode found!  Exit loop.  */
-          mode_found = 1;
-          break;
-        }
-
-      /* Free memory.  */
-      grub_free (modevar);
-      
-      if (!mode_found)
-        return grub_error (GRUB_ERR_BAD_ARGUMENT,
-                           "No suitable mode found.");
-    }
+  if (! modevar || *modevar == 0)
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook);
   else
     {
-      /* No gfxmode variable set, use defaults.  */
-      
-      /* If we have 8 or less bits, then assume that it is indexed color mode.  */
-      if ((depth <= 8) && (depth != -1))
-        flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
-
-      /* We have more than 8 bits, then assume that it is RGB color mode.  */
-      if (depth > 8)
-        flags |= GRUB_VIDEO_MODE_TYPE_RGB;
-
-      /* If user requested specific depth, forward that information to driver.  */
-      if (depth != -1)
-        flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
-                 & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+      tmp = grub_malloc (grub_strlen (modevar) 
+                        + sizeof (DEFAULT_VIDEO_MODE) + 1);
+      grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar);
+      err = grub_video_set_mode (tmp, video_hook);
+      grub_free (tmp);
+    }
 
-      /* Initialize user requested mode.  */
-      if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
-        return grub_errno;
+  if (err)
+    return err;
 
-      /* Figure out what mode we ended up.  */
-      if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
-        {
-          grub_video_restore ();
-          return grub_errno;
-        }
-    }
+  err = grub_video_get_info (&mode_info);
+  /* Figure out what mode we ended up.  */
+  if (err)
+    return err;
 
   /* Make sure screen is black.  */
   color = grub_video_map_rgb (0, 0, 0);
index a145277fc868cf679836050885125a199c686727..7d4d17e9593240e5a65e7e671d7b2303a6e6b63a 100644 (file)
@@ -90,9 +90,6 @@ EOF
 menuentry "${LONGNAME} (on ${DEVICE})" {
        set root=${OSXROOT}
         insmod vbe
-        insmod gfxterm
-        gfxmode="1024x768x32;800x600x32"
-        terminal_output gfxterm
         do_resume=0
         if [ /var/vm/sleepimage -nt10 / ]; then
            if xnu_resume /var/vm/sleepimage; then
index 49e6cb95e13221aebe24f503c03b9a3906e6a2ee..2c7f12b9efddc49b504ab86ee8f4bd3d88ac9294 100644 (file)
@@ -19,6 +19,8 @@
 #include <grub/video.h>
 #include <grub/types.h>
 #include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
 
 /* The list of video adapters registered to system.  */
 static grub_video_adapter_t grub_video_adapter_list;
@@ -59,59 +61,6 @@ grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
       break;
 }
 
-/* Setup specified video mode.  */
-grub_err_t
-grub_video_setup (unsigned int width, unsigned int height,
-                  unsigned int mode_type)
-{
-  grub_video_adapter_t p;
-
-  /* De-activate last set video adapter.  */
-  if (grub_video_adapter_active)
-    {
-      /* Finalize adapter.  */
-      grub_video_adapter_active->fini ();
-      if (grub_errno != GRUB_ERR_NONE)
-        return grub_errno;
-
-      /* Mark active adapter as not set.  */
-      grub_video_adapter_active = 0;
-    }
-
-  /* Loop thru all possible video adapter trying to find requested mode.  */
-  for (p = grub_video_adapter_list; p; p = p->next)
-    {
-      /* Try to initialize adapter, if it fails, skip to next adapter.  */
-      p->init ();
-      if (grub_errno != GRUB_ERR_NONE)
-        {
-          grub_errno = GRUB_ERR_NONE;
-          continue;
-        }
-
-      /* Try to initialize video mode.  */
-      p->setup (width, height, mode_type);
-      if (grub_errno == GRUB_ERR_NONE)
-        {
-          /* Valid mode found from adapter, and it has been activated.
-             Specify it as active adapter.  */
-          grub_video_adapter_active = p;
-          return GRUB_ERR_NONE;
-        }
-      else
-        grub_errno = GRUB_ERR_NONE;
-
-      /* No valid mode found in this adapter, finalize adapter.  */
-      p->fini ();
-      if (grub_errno != GRUB_ERR_NONE)
-        return grub_errno;
-    }
-
-  /* We couldn't find suitable adapter for specified mode.  */
-  return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
-                     "Can't locate valid adapter for mode");
-}
-
 /* Restore back to initial mode (where applicable).  */
 grub_err_t
 grub_video_restore (void)
@@ -430,6 +379,319 @@ grub_video_get_active_render_target (struct grub_video_render_target **target)
   return grub_video_adapter_active->get_active_render_target (target);
 }
 
+grub_err_t
+grub_video_set_mode (char *modestring,
+                    int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
+                                                  struct grub_video_mode_info *mode_info))
+{
+  char *tmp;
+  char *next_mode;
+  char *current_mode;
+  char *param;
+  char *value;
+  char *modevar;
+  int width = -1;
+  int height = -1;
+  int depth = -1;
+  int flags = 0;
+
+  /* Take copy of env.var. as we don't want to modify that.  */
+  modevar = grub_strdup (modestring);
+
+  /* Initialize next mode.  */
+  next_mode = modevar;
+
+  if (! modevar)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "couldn't allocate space for local modevar copy");
+
+  if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0
+      || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
+      || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
+    {
+      struct grub_video_mode_info mode_info;
+      int suitable = 1;
+      grub_err_t err;
+      
+      grub_memset (&mode_info, 0, sizeof (mode_info));
+
+      if (grub_video_adapter_active)
+       {
+         err = grub_video_get_info (&mode_info);
+         if (err)
+           {
+             suitable = 0;
+             grub_errno = GRUB_ERR_NONE;
+           }
+       }
+      else
+       mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
+
+      if (suitable && hook)
+       suitable = hook (grub_video_adapter_active, &mode_info);
+      if (suitable)
+       {
+         grub_free (modevar);
+         return GRUB_ERR_NONE;
+       }
+      next_mode += sizeof ("keep") - 1;
+      if (! *next_mode)
+       {
+         grub_free (modevar);
+  
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            "No suitable mode found.");
+       }
+      
+      /* Skip separator. */
+      next_mode++;
+    }
+
+  /* De-activate last set video adapter.  */
+  if (grub_video_adapter_active)
+    {
+      /* Finalize adapter.  */
+      grub_video_adapter_active->fini ();
+      if (grub_errno != GRUB_ERR_NONE)
+       grub_errno = GRUB_ERR_NONE;
+      
+      /* Mark active adapter as not set.  */
+      grub_video_adapter_active = 0;
+    }
+    
+  /* Loop until all modes has been tested out.  */
+  while (next_mode != NULL)
+    {
+      /* Use last next_mode as current mode.  */
+      tmp = next_mode;
+      
+      /* Reset video mode settings.  */
+      width = -1;
+      height = -1;
+      depth = -1;
+      flags = 0;
+      
+      /* Save position of next mode and separate modes.  */
+      for (; *next_mode; next_mode++)
+       if (*next_mode == ',' || *next_mode == ';')
+         break;
+      if (*next_mode)
+       {
+         *next_mode = 0;
+         next_mode++;
+       }
+      else
+       next_mode = 0;
+      
+      /* Skip whitespace.  */
+      while (grub_isspace (*tmp))
+       tmp++;
+      
+      /* Initialize token holders.  */
+      current_mode = tmp;
+      param = tmp;
+      value = NULL;
+
+      /* XXX: we assume that we're in pure text mode if 
+        no video mode is initialized. Is it always true? */
+      if (grub_strcmp (param, "text") == 0)
+       {
+         struct grub_video_mode_info mode_info;
+         
+         grub_memset (&mode_info, 0, sizeof (mode_info));
+         mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
+
+         if (! hook || hook (0, &mode_info))
+           {
+             /* Valid mode found from adapter, and it has been activated.
+                Specify it as active adapter.  */
+             grub_video_adapter_active = NULL;
+
+             /* Free memory.  */
+             grub_free (modevar);
+
+             return GRUB_ERR_NONE;
+           }
+       }
+
+      /* Parse <width>x<height>[x<depth>]*/
+      
+      /* Find width value.  */
+      value = param;
+      param = grub_strchr(param, 'x');
+      if (param == NULL)
+       {
+         grub_err_t rc;
+          
+         /* First setup error message.  */
+         rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                          "Invalid mode: %s\n",
+                          current_mode);
+          
+         /* Free memory before returning.  */
+         grub_free (modevar);
+         
+         return rc;
+       }
+      
+      *param = 0;
+      param++;
+      
+      width = grub_strtoul (value, 0, 0);
+      if (grub_errno != GRUB_ERR_NONE)
+       {
+         grub_err_t rc;
+          
+         /* First setup error message.  */
+         rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                          "Invalid mode: %s\n",
+                          current_mode);
+         
+         /* Free memory before returning.  */
+         grub_free (modevar);
+          
+         return rc;
+       }
+      
+      /* Find height value.  */
+      value = param;
+      param = grub_strchr(param, 'x');
+      if (param == NULL)
+       {
+         height = grub_strtoul (value, 0, 0);
+         if (grub_errno != GRUB_ERR_NONE)
+           {
+             grub_err_t rc;
+             
+             /* First setup error message.  */
+             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                              "Invalid mode: %s\n",
+                              current_mode);
+             
+             /* Free memory before returning.  */
+             grub_free (modevar);
+             
+             return rc;
+           }
+       }
+      else
+       {
+         /* We have optional color depth value.  */
+         *param = 0;
+         param++;
+         
+         height = grub_strtoul (value, 0, 0);
+         if (grub_errno != GRUB_ERR_NONE)
+           {
+             grub_err_t rc;
+             
+             /* First setup error message.  */
+             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                              "Invalid mode: %s\n",
+                              current_mode);
+             
+             /* Free memory before returning.  */
+             grub_free (modevar);
+             
+             return rc;
+           }
+         
+         /* Convert color depth value.  */
+         value = param;
+         depth = grub_strtoul (value, 0, 0);
+         if (grub_errno != GRUB_ERR_NONE)
+           {
+             grub_err_t rc;
+             
+             /* First setup error message.  */
+             rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                              "Invalid mode: %s\n",
+                              current_mode);
+             
+             /* Free memory before returning.  */
+             grub_free (modevar);
+
+             return rc;
+           }
+       }
+
+      /* Try out video mode.  */
+      
+      /* If we have 8 or less bits, then assume that it is indexed color mode.  */
+      if ((depth <= 8) && (depth != -1))
+       flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
+
+      /* We have more than 8 bits, then assume that it is RGB color mode.  */
+      if (depth > 8)
+       flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+      
+      /* If user requested specific depth, forward that information to driver.  */
+      if (depth != -1)
+       flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+         & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
+      
+      /* Try to initialize requested mode.  Ignore any errors.  */
+      grub_video_adapter_t p;
+
+      /* Loop thru all possible video adapter trying to find requested mode.  */
+      for (p = grub_video_adapter_list; p; p = p->next)
+       {
+         grub_err_t err;
+         struct grub_video_mode_info mode_info;
+         
+         grub_memset (&mode_info, 0, sizeof (mode_info));
+
+         /* Try to initialize adapter, if it fails, skip to next adapter.  */
+         err = p->init ();
+         if (err != GRUB_ERR_NONE)
+           {
+             grub_errno = GRUB_ERR_NONE;
+             continue;
+           }
+
+         /* Try to initialize video mode.  */
+         err = p->setup (width, height, flags);
+         if (err != GRUB_ERR_NONE)
+           {
+             p->fini ();
+             grub_errno = GRUB_ERR_NONE;
+             continue;
+           }
+
+         err = p->get_info (&mode_info);
+         if (err != GRUB_ERR_NONE)
+           {
+             p->fini ();
+             grub_errno = GRUB_ERR_NONE;
+             continue;
+           }
+
+         if (hook && ! hook (p, &mode_info))
+           {
+             p->fini ();
+             grub_errno = GRUB_ERR_NONE;
+             continue;
+           }
+           
+         /* Valid mode found from adapter, and it has been activated.
+            Specify it as active adapter.  */
+         grub_video_adapter_active = p;
+         
+         /* Free memory.  */
+         grub_free (modevar);
+         
+         return GRUB_ERR_NONE;
+       }
+
+    }
+
+  /* Free memory.  */
+  grub_free (modevar);
+  
+  return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                    "No suitable mode found.");
+}
+
 /* Initialize Video API module.  */
 GRUB_MOD_INIT(video_video)
 {