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
This commit is contained in:
phcoder 2009-06-04 18:22:45 +00:00
parent fd8c967c29
commit 3eb5ed4ec0
8 changed files with 480 additions and 338 deletions

View file

@ -19,6 +19,8 @@
#include <grub/video.h>
#include <grub/types.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/mm.h>
/* The list of video adapters registered to system. */
static grub_video_adapter_t grub_video_adapter_list;
@ -59,59 +61,6 @@ grub_video_iterate (int (*hook) (grub_video_adapter_t adapter))
break;
}
/* Setup specified video mode. */
grub_err_t
grub_video_setup (unsigned int width, unsigned int height,
unsigned int mode_type)
{
grub_video_adapter_t p;
/* De-activate last set video adapter. */
if (grub_video_adapter_active)
{
/* Finalize adapter. */
grub_video_adapter_active->fini ();
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
/* Mark active adapter as not set. */
grub_video_adapter_active = 0;
}
/* Loop thru all possible video adapter trying to find requested mode. */
for (p = grub_video_adapter_list; p; p = p->next)
{
/* Try to initialize adapter, if it fails, skip to next adapter. */
p->init ();
if (grub_errno != GRUB_ERR_NONE)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
/* Try to initialize video mode. */
p->setup (width, height, mode_type);
if (grub_errno == GRUB_ERR_NONE)
{
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
grub_video_adapter_active = p;
return GRUB_ERR_NONE;
}
else
grub_errno = GRUB_ERR_NONE;
/* No valid mode found in this adapter, finalize adapter. */
p->fini ();
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
}
/* We couldn't find suitable adapter for specified mode. */
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"Can't locate valid adapter for mode");
}
/* Restore back to initial mode (where applicable). */
grub_err_t
grub_video_restore (void)
@ -430,6 +379,319 @@ grub_video_get_active_render_target (struct grub_video_render_target **target)
return grub_video_adapter_active->get_active_render_target (target);
}
grub_err_t
grub_video_set_mode (char *modestring,
int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
struct grub_video_mode_info *mode_info))
{
char *tmp;
char *next_mode;
char *current_mode;
char *param;
char *value;
char *modevar;
int width = -1;
int height = -1;
int depth = -1;
int flags = 0;
/* Take copy of env.var. as we don't want to modify that. */
modevar = grub_strdup (modestring);
/* Initialize next mode. */
next_mode = modevar;
if (! modevar)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't allocate space for local modevar copy");
if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0
|| grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
|| grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
{
struct grub_video_mode_info mode_info;
int suitable = 1;
grub_err_t err;
grub_memset (&mode_info, 0, sizeof (mode_info));
if (grub_video_adapter_active)
{
err = grub_video_get_info (&mode_info);
if (err)
{
suitable = 0;
grub_errno = GRUB_ERR_NONE;
}
}
else
mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
if (suitable && hook)
suitable = hook (grub_video_adapter_active, &mode_info);
if (suitable)
{
grub_free (modevar);
return GRUB_ERR_NONE;
}
next_mode += sizeof ("keep") - 1;
if (! *next_mode)
{
grub_free (modevar);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"No suitable mode found.");
}
/* Skip separator. */
next_mode++;
}
/* De-activate last set video adapter. */
if (grub_video_adapter_active)
{
/* Finalize adapter. */
grub_video_adapter_active->fini ();
if (grub_errno != GRUB_ERR_NONE)
grub_errno = GRUB_ERR_NONE;
/* Mark active adapter as not set. */
grub_video_adapter_active = 0;
}
/* Loop until all modes has been tested out. */
while (next_mode != NULL)
{
/* Use last next_mode as current mode. */
tmp = next_mode;
/* Reset video mode settings. */
width = -1;
height = -1;
depth = -1;
flags = 0;
/* Save position of next mode and separate modes. */
for (; *next_mode; next_mode++)
if (*next_mode == ',' || *next_mode == ';')
break;
if (*next_mode)
{
*next_mode = 0;
next_mode++;
}
else
next_mode = 0;
/* Skip whitespace. */
while (grub_isspace (*tmp))
tmp++;
/* Initialize token holders. */
current_mode = tmp;
param = tmp;
value = NULL;
/* XXX: we assume that we're in pure text mode if
no video mode is initialized. Is it always true? */
if (grub_strcmp (param, "text") == 0)
{
struct grub_video_mode_info mode_info;
grub_memset (&mode_info, 0, sizeof (mode_info));
mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
if (! hook || hook (0, &mode_info))
{
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
grub_video_adapter_active = NULL;
/* Free memory. */
grub_free (modevar);
return GRUB_ERR_NONE;
}
}
/* Parse <width>x<height>[x<depth>]*/
/* Find width value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
*param = 0;
param++;
width = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
/* Find height value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
{
height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
}
else
{
/* We have optional color depth value. */
*param = 0;
param++;
height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
/* Convert color depth value. */
value = param;
depth = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
}
/* Try out video mode. */
/* If we have 8 or less bits, then assume that it is indexed color mode. */
if ((depth <= 8) && (depth != -1))
flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
/* We have more than 8 bits, then assume that it is RGB color mode. */
if (depth > 8)
flags |= GRUB_VIDEO_MODE_TYPE_RGB;
/* If user requested specific depth, forward that information to driver. */
if (depth != -1)
flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
/* Try to initialize requested mode. Ignore any errors. */
grub_video_adapter_t p;
/* Loop thru all possible video adapter trying to find requested mode. */
for (p = grub_video_adapter_list; p; p = p->next)
{
grub_err_t err;
struct grub_video_mode_info mode_info;
grub_memset (&mode_info, 0, sizeof (mode_info));
/* Try to initialize adapter, if it fails, skip to next adapter. */
err = p->init ();
if (err != GRUB_ERR_NONE)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
/* Try to initialize video mode. */
err = p->setup (width, height, flags);
if (err != GRUB_ERR_NONE)
{
p->fini ();
grub_errno = GRUB_ERR_NONE;
continue;
}
err = p->get_info (&mode_info);
if (err != GRUB_ERR_NONE)
{
p->fini ();
grub_errno = GRUB_ERR_NONE;
continue;
}
if (hook && ! hook (p, &mode_info))
{
p->fini ();
grub_errno = GRUB_ERR_NONE;
continue;
}
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
grub_video_adapter_active = p;
/* Free memory. */
grub_free (modevar);
return GRUB_ERR_NONE;
}
}
/* Free memory. */
grub_free (modevar);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"No suitable mode found.");
}
/* Initialize Video API module. */
GRUB_MOD_INIT(video_video)
{