+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
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;
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
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);
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 */
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;
0
};
-static grub_uint16_t vid_mode;
-
+#ifdef GRUB_MACHINE_PCBIOS
struct linux_vesafb_res
{
grub_uint16_t width;
{ VGA_800_500, 24 }, /* 0x372 */
{ VGA_800_500, 32 }, /* 0x373 */
};
+#endif
static inline grub_size_t
page_align (grub_size_t size)
{
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
(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
{
/* 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;
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 */
#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)
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");
#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
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");
/* 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);
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
#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;
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)
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)
{