videoinfo.c 7.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* videoinfo.c - command to list video modes.  */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2005,2007,2008,2009,2010  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/video.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <grub/i18n.h>

28 29
GRUB_MOD_LICENSE ("GPLv3+");

30 31 32 33 34
struct hook_ctx
{
  unsigned height, width, depth; 
  struct grub_video_mode_info *current_mode;
};
35

36
static int
37
hook (const struct grub_video_mode_info *info, void *hook_arg)
38
{
39 40 41
  struct hook_ctx *ctx = hook_arg;

  if (ctx->height && ctx->width && (info->width != ctx->width || info->height != ctx->height))
42 43
    return 0;

44
  if (ctx->depth && info->bpp != ctx->depth)
45 46
    return 0;

47 48 49
  if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID)
    grub_printf ("        ");
  else
50
    {
51
      if (ctx->current_mode && info->mode_number == ctx->current_mode->mode_number)
52 53 54 55 56
	grub_printf ("*");
      else
	grub_printf (" ");
      grub_printf (" 0x%03x ", info->mode_number);
    }
57 58
  grub_printf ("%4d x %4d x %2d (%4d)  ", info->width, info->height, info->bpp,
	       info->pitch);
59

60
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
61
    grub_xputs (_("Text-only "));
62 63
  /* Show mask and position details for direct color modes.  */
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
64 65
    /* TRANSLATORS: "Direct color" is a mode when the color components
       are written dirrectly into memory.  */
66
    grub_printf_ (N_("Direct color, mask: %d/%d/%d/%d  pos: %d/%d/%d/%d"),
67 68 69 70 71 72 73 74
		  info->red_mask_size,
		  info->green_mask_size,
		  info->blue_mask_size,
		  info->reserved_mask_size,
		  info->red_field_pos,
		  info->green_field_pos,
		  info->blue_field_pos,
		  info->reserved_field_pos);
75
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
76 77 78
    /* TRANSLATORS: In "paletted color" mode you write the index of the color
       in the palette. Synonyms include "packed pixel".  */
    grub_xputs (_("Paletted "));
79
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
80
    grub_xputs (_("YUV "));
81
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
82 83 84
    /* TRANSLATORS: "Planar" is the video memory where you have to write
       in several different banks "plans" to control the different color
       components of the same pixel.  */
85
    grub_xputs (_("Planar "));
86
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
87
    grub_xputs (_("Hercules "));
88
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
89
    grub_xputs (_("CGA "));
90
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
91 92
    /* TRANSLATORS: Non-chain 4 is a 256-color planar
       (unchained) video memory mode.  */
93
    grub_xputs (_("Non-chain 4 "));
94
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
95
    grub_xputs (_("Monochrome "));
96
  if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
97
    grub_xputs (_("Unknown video mode "));
98

99
  grub_xputs ("\n");
100 101 102 103

  return 0;
}

104 105 106 107 108 109 110
static void
print_edid (struct grub_video_edid_info *edid_info)
{
  unsigned int edid_width, edid_height;

  if (grub_video_edid_checksum (edid_info))
    {
111
      grub_puts_ (N_("  EDID checksum invalid"));
112 113 114 115
      grub_errno = GRUB_ERR_NONE;
      return;
    }

116 117
  grub_printf_ (N_("  EDID version: %u.%u\n"),
		edid_info->version, edid_info->revision);
118 119
  if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
	== GRUB_ERR_NONE)
120
    grub_printf_ (N_("    Preferred mode: %ux%u\n"), edid_width, edid_height);
121 122
  else
    {
123
      grub_printf_ (N_("    No preferred mode available\n"));
124 125 126 127
      grub_errno = GRUB_ERR_NONE;
    }
}

128 129
static grub_err_t
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
130
		    int argc, char **args)
131 132
{
  grub_video_adapter_t adapter;
133
  grub_video_driver_id_t id;
134
  struct hook_ctx ctx;
135

136
  ctx.height = ctx.width = ctx.depth = 0;
137 138 139 140
  if (argc)
    {
      char *ptr;
      ptr = args[0];
141
      ctx.width = grub_strtoul (ptr, &ptr, 0);
142 143 144
      if (grub_errno)
	return grub_errno;
      if (*ptr != 'x')
145 146 147
	return grub_error (GRUB_ERR_BAD_ARGUMENT,
			   N_("invalid video mode specification `%s'"),
			   args[0]);
148
      ptr++;
149
      ctx.height = grub_strtoul (ptr, &ptr, 0);
150 151 152 153 154
      if (grub_errno)
	return grub_errno;
      if (*ptr == 'x')
	{
	  ptr++;
155
	  ctx.depth = grub_strtoul (ptr, &ptr, 0);
156 157 158 159 160
	  if (grub_errno)
	    return grub_errno;
	}
    }

161 162 163 164 165 166
#ifdef GRUB_MACHINE_PCBIOS
  if (grub_strcmp (cmd->name, "vbeinfo") == 0)
    grub_dl_load ("vbe");
#endif

  id = grub_video_get_driver_id ();
167

168
  grub_puts_ (N_("List of supported video modes:"));
169
  grub_puts_ (N_("Legend: mask/position=red/green/blue/reserved"));
170 171 172

  FOR_VIDEO_ADAPTERS (adapter)
  {
173
    struct grub_video_mode_info info;
174
    struct grub_video_edid_info edid_info;
175

176
    grub_printf_ (N_("Adapter `%s':\n"), adapter->name);
177 178 179

    if (!adapter->iterate)
      {
180
	grub_puts_ (N_("  No info available"));
181 182 183
	continue;
      }

184
    ctx.current_mode = NULL;
185 186 187 188

    if (adapter->id == id)
      {
	if (grub_video_get_info (&info) == GRUB_ERR_NONE)
189
	  ctx.current_mode = &info;
190 191 192 193 194
	else
	  /* Don't worry about errors.  */
	  grub_errno = GRUB_ERR_NONE;
      }
    else
195 196 197
      {
	if (adapter->init ())
	  {
198
	    grub_puts_ (N_("  Failed to initialize video adapter"));
199 200 201 202 203
	    grub_errno = GRUB_ERR_NONE;
	    continue;
	  }
      }

204 205 206
    if (adapter->print_adapter_specific_info)
      adapter->print_adapter_specific_info ();

207
    adapter->iterate (hook, &ctx);
208

209
    if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE)
210 211 212 213
      print_edid (&edid_info);
    else
      grub_errno = GRUB_ERR_NONE;

214
    ctx.current_mode = NULL;
215

216 217 218 219 220 221 222 223 224 225 226 227 228
    if (adapter->id != id)
      {
	if (adapter->fini ())
	  {
	    grub_errno = GRUB_ERR_NONE;
	    continue;
	  }
      }
  }
  return GRUB_ERR_NONE;
}

static grub_command_t cmd;
229 230 231
#ifdef GRUB_MACHINE_PCBIOS
static grub_command_t cmd_vbe;
#endif
232 233 234

GRUB_MOD_INIT(videoinfo)
{
235 236 237 238 239
  cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo,
			       /* TRANSLATORS: "x" has to be entered in,
				  like an identifier, so please don't
				  use better Unicode codepoints.  */
			       N_("[WxH[xD]]"),
240 241 242
			       N_("List available video modes. If "
				     "resolution is given show only modes"
				     " matching it."));
243
#ifdef GRUB_MACHINE_PCBIOS
244
  cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo,
245 246 247
				   /* TRANSLATORS: "x" has to be entered in,
				      like an identifier, so please don't
				      use better Unicode codepoints.  */
248
				   N_("[WxH[xD]]"),
249 250 251
				   N_("List available video modes. If "
				      "resolution is given show only modes"
				      " matching it."));
252
#endif
253 254 255 256 257
}

GRUB_MOD_FINI(videoinfo)
{
  grub_unregister_command (cmd);
258 259 260
#ifdef GRUB_MACHINE_PCBIOS
  grub_unregister_command (cmd_vbe);
#endif
261 262
}