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 #include #include +#include #include #include #include @@ -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 #include -#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 x[x]*/ - - /* 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 #include #include +#include +#include /* 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 x[x]*/ + + /* 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) {