[2247] 2009-06-04 Vladimir Serbinenko <[email protected]>

Vladimir Serbinenko <[email protected]>
Newsgroups gmane.comp.boot-loaders.grub.cvs
Message-ID <[email protected]>
Revision: 2247
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=2247
Author:   phcoder
Date:     2009-06-04 18:22:45 +0000 (Thu, 04 Jun 2009)
Log Message:
-----------
2009-06-04  Vladimir Serbinenko  <[email protected]>

	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

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

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/ChangeLog	2009-06-04 18:22:45 UTC (rev 2247)
@@ -1,5 +1,31 @@
 2009-06-04  Vladimir Serbinenko  <[email protected]>
 
+	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  <[email protected]>
+
 	Avoid calling biosdisk in drivemap
 
 	* commands/i386/pc/drivemap.c (parse_biosdisk): remove

Modified: trunk/grub2/commands/videotest.c
===================================================================
--- trunk/grub2/commands/videotest.c	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/commands/videotest.c	2009-06-04 18:22:45 UTC (rev 2247)
@@ -30,8 +30,7 @@
                     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;

Modified: trunk/grub2/include/grub/video.h
===================================================================
--- trunk/grub2/include/grub/video.h	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/include/grub/video.h	2009-06-04 18:22:45 UTC (rev 2247)
@@ -34,6 +34,7 @@
 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_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_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 */

Modified: trunk/grub2/loader/i386/linux.c
===================================================================
--- trunk/grub2/loader/i386/linux.c	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/loader/i386/linux.c	2009-06-04 18:22:45 UTC (rev 2247)
@@ -43,8 +43,10 @@
    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 @@
     0
   };
 
-static grub_uint16_t vid_mode;
-
+#ifdef GRUB_MACHINE_PCBIOS
 struct linux_vesafb_res
 {
   grub_uint16_t width;
@@ -262,6 +263,7 @@
     { 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 @@
 {
   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 @@
 	       (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 @@
       {
 	/* 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 @@
 	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;
+	      }
+
+	    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;
 	  }
-
-	if (grub_errno)
-	  goto fail;
       }
     else
 #endif /* GRUB_MACHINE_PCBIOS */

Modified: trunk/grub2/loader/i386/pc/xnu.c
===================================================================
--- trunk/grub2/loader/i386/pc/xnu.c	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/loader/i386/pc/xnu.c	2009-06-04 18:22:45 UTC (rev 2247)
@@ -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 @@
   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");

Modified: trunk/grub2/term/gfxterm.c
===================================================================
--- trunk/grub2/term/gfxterm.c	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/term/gfxterm.c	2009-06-04 18:22:45 UTC (rev 2247)
@@ -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 @@
   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,232 +252,25 @@
 
   /* 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;
+      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);
+    }
 
-      /* We have more than 8 bits, then assume that it is RGB color mode.  */
-      if (depth > 8)
-        flags |= GRUB_VIDEO_MODE_TYPE_RGB;
+  if (err)
+    return err;
 
-      /* 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;
+  err = grub_video_get_info (&mode_info);
+  /* Figure out what mode we ended up.  */
+  if (err)
+    return err;
 
-      /* Initialize user requested mode.  */
-      if (grub_video_setup (width, height, flags) != GRUB_ERR_NONE)
-        return grub_errno;
-
-      /* Figure out what mode we ended up.  */
-      if (grub_video_get_info (&mode_info) != GRUB_ERR_NONE)
-        {
-          grub_video_restore ();
-          return grub_errno;
-        }
-    }
-
   /* Make sure screen is black.  */
   color = grub_video_map_rgb (0, 0, 0);
   grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);

Modified: trunk/grub2/util/grub.d/30_os-prober.in
===================================================================
--- trunk/grub2/util/grub.d/30_os-prober.in	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/util/grub.d/30_os-prober.in	2009-06-04 18:22:45 UTC (rev 2247)
@@ -90,9 +90,6 @@
 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

Modified: trunk/grub2/video/video.c
===================================================================
--- trunk/grub2/video/video.c	2009-06-04 17:58:25 UTC (rev 2246)
+++ trunk/grub2/video/video.c	2009-06-04 18:22:45 UTC (rev 2247)
@@ -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 @@
       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 @@
   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)
 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.