> Just tried it in VMware.
> With set gfxmode=1024x768x24 and set gfxpayload=1024x768x24 and no vga=
> option I just get the normal text mode
> with set gfxpayload=keep it works
> and also vga=0x317 works too.
As we figured out on IRC the problem was that vmware has no 16-bit.
New patch with fixed vga=0 and warning for users when using vga=
> --
> Felix Zielcke
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>



-- 
Regards
Vladimir 'phcoder' Serbinenko
diff --git a/commands/videotest.c b/commands/videotest.c
index db7f704..6fe4b9b 100644
--- a/commands/videotest.c
+++ b/commands/videotest.c
@@ -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;
diff --git a/include/grub/video.h b/include/grub/video.h
index cb73dae..3b27655 100644
--- a/include/grub/video.h
+++ b/include/grub/video.h
@@ -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 */
diff --git a/loader/i386/linux.c b/loader/i386/linux.c
index ca44fb4..72d826c 100644
--- a/loader/i386/linux.c
+++ b/loader/i386/linux.c
@@ -44,7 +44,9 @@
    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
+#define DEFAULT_VIDEO_MODE "text"
+#else
+#define DEFAULT_VIDEO_MODE "keep"
 #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,48 +444,32 @@ 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");
+  if (! modevar || *modevar == 0)
+    err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0);
+  else
     {
-      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_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, 0);
+      grub_free (tmp);
+    }
+
+  if (err)
+    {
+      grub_print_error ();
+      grub_printf ("Booting however\n");
+      grub_errno = GRUB_ERR_NONE;
     }
-#if ! 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 ();
-#endif
 
   if (! grub_linux_setup_video (params))
     params->have_vga = GRUB_VIDEO_TYPE_VLFB;
@@ -708,7 +694,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,11 +701,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       {
 	/* Video mode selection support.  */
 	char *val = argv[i] + 4;
+	unsigned vid_mode = 0;
+	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;
+	  vid_mode = 0;
 	else if (grub_strcmp (val, "ext") == 0)
-	  vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
+	  vid_mode = 1;
 	else if (grub_strcmp (val, "ask") == 0)
 	  {
 	    grub_printf ("Legacy `ask' parameter no longer supported.\n");
@@ -737,21 +726,58 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 	switch (vid_mode)
 	  {
 	  case 0:
-	    vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
+	    grub_env_set ("gfxpayload", "text");
+	    grub_printf ("%s is depreceated. "
+			 "Use set gfxpayload=text before "
+			 "linux command instead.\n", 
+			 argv[i]);	
 	    break;
 	  case 1:
-	    vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
+	    /* FIXME: support 80x50 text. */
+	    grub_env_set ("gfxpayload", "text");
+	    grub_printf ("%s is depreceated. "
+			 "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 depreceated. 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)
+	      {
+		grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+			    "couldn't allocate temporary storage");
+		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 depreceated. "
+			 "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 */
diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c
index 1cca138..d32f679 100644
--- a/loader/i386/pc/xnu.c
+++ b/loader/i386/pc/xnu.c
@@ -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>
@@ -26,6 +27,17 @@
 #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");
diff --git a/term/gfxterm.c b/term/gfxterm.c
index e6baa15..5da6788 100644
--- a/term/gfxterm.c
+++ b/term/gfxterm.c
@@ -27,10 +27,7 @@
 #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);
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index a145277..7d4d17e 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -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
diff --git a/video/video.c b/video/video.c
index 49e6cb9..2c7f12b 100644
--- a/video/video.c
+++ b/video/video.c
@@ -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)
 {
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to