~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to video/video.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 2006,2007,2008,2009  Free Software Foundation, Inc.
4
 
 *
5
 
 *  GRUB is free software: you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation, either version 3 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  GRUB is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
#include <grub/video.h>
20
 
#include <grub/types.h>
21
 
#include <grub/dl.h>
22
 
#include <grub/misc.h>
23
 
#include <grub/mm.h>
24
 
 
25
 
/* The list of video adapters registered to system.  */
26
 
grub_video_adapter_t grub_video_adapter_list = NULL;
27
 
 
28
 
/* Active video adapter.  */
29
 
static grub_video_adapter_t grub_video_adapter_active;
30
 
 
31
 
/* Restore back to initial mode (where applicable).  */
32
 
grub_err_t
33
 
grub_video_restore (void)
34
 
{
35
 
  if (grub_video_adapter_active)
36
 
    {
37
 
      grub_video_adapter_active->fini ();
38
 
      if (grub_errno != GRUB_ERR_NONE)
39
 
        return grub_errno;
40
 
 
41
 
      grub_video_adapter_active = 0;
42
 
    }
43
 
  return GRUB_ERR_NONE;
44
 
}
45
 
 
46
 
/* Get information about active video mode.  */
47
 
grub_err_t
48
 
grub_video_get_info (struct grub_video_mode_info *mode_info)
49
 
{
50
 
  if (! grub_video_adapter_active)
51
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
52
 
 
53
 
  /* If mode_info is NULL just report that video adapter is active.  */
54
 
  if (! mode_info)
55
 
    {
56
 
      grub_errno = GRUB_ERR_NONE;
57
 
      return grub_errno;
58
 
    }
59
 
 
60
 
  return grub_video_adapter_active->get_info (mode_info);
61
 
}
62
 
 
63
 
grub_video_driver_id_t
64
 
grub_video_get_driver_id (void)
65
 
{
66
 
  if (! grub_video_adapter_active)
67
 
    return GRUB_VIDEO_DRIVER_NONE;
68
 
  return grub_video_adapter_active->id;
69
 
}
70
 
 
71
 
/* Get information about active video mode.  */
72
 
grub_err_t
73
 
grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
74
 
                              void **framebuffer)
75
 
{
76
 
  grub_err_t err;
77
 
 
78
 
  if (! grub_video_adapter_active)
79
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
80
 
 
81
 
  err = grub_video_adapter_active->get_info_and_fini (mode_info, framebuffer);
82
 
  if (err)
83
 
    return err;
84
 
 
85
 
  grub_video_adapter_active = 0;
86
 
  return GRUB_ERR_NONE;
87
 
}
88
 
 
89
 
/* Determine optimized blitting formation for specified video mode info.  */
90
 
enum grub_video_blit_format
91
 
grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
92
 
{
93
 
  /* Check if we have any known 32 bit modes.  */
94
 
  if (mode_info->bpp == 32)
95
 
    {
96
 
      if ((mode_info->red_mask_size == 8)
97
 
          && (mode_info->red_field_pos == 16)
98
 
          && (mode_info->green_mask_size == 8)
99
 
          && (mode_info->green_field_pos == 8)
100
 
          && (mode_info->blue_mask_size == 8)
101
 
          && (mode_info->blue_field_pos == 0))
102
 
        {
103
 
          return GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
104
 
        }
105
 
      else if ((mode_info->red_mask_size == 8)
106
 
               && (mode_info->red_field_pos == 0)
107
 
               && (mode_info->green_mask_size == 8)
108
 
               && (mode_info->green_field_pos == 8)
109
 
               && (mode_info->blue_mask_size == 8)
110
 
               && (mode_info->blue_field_pos == 16))
111
 
        {
112
 
          return GRUB_VIDEO_BLIT_FORMAT_RGBA_8888;
113
 
        }
114
 
    }
115
 
  /* Check if we have any known 24 bit modes.  */
116
 
  else if (mode_info->bpp == 24)
117
 
    {
118
 
      if ((mode_info->red_mask_size == 8)
119
 
          && (mode_info->red_field_pos == 16)
120
 
          && (mode_info->green_mask_size == 8)
121
 
          && (mode_info->green_field_pos == 8)
122
 
          && (mode_info->blue_mask_size == 8)
123
 
          && (mode_info->blue_field_pos == 0))
124
 
        {
125
 
          return GRUB_VIDEO_BLIT_FORMAT_BGR_888;
126
 
        }
127
 
      else if ((mode_info->red_mask_size == 8)
128
 
               && (mode_info->red_field_pos == 0)
129
 
               && (mode_info->green_mask_size == 8)
130
 
               && (mode_info->green_field_pos == 8)
131
 
               && (mode_info->blue_mask_size == 8)
132
 
               && (mode_info->blue_field_pos == 16))
133
 
        {
134
 
          return GRUB_VIDEO_BLIT_FORMAT_RGB_888;
135
 
        }
136
 
    }
137
 
  /* Check if we have any known 16 bit modes.  */
138
 
  else if (mode_info->bpp == 16)
139
 
    {
140
 
      if ((mode_info->red_mask_size == 5)
141
 
          && (mode_info->red_field_pos == 11)
142
 
          && (mode_info->green_mask_size == 6)
143
 
          && (mode_info->green_field_pos == 5)
144
 
          && (mode_info->blue_mask_size == 5)
145
 
          && (mode_info->blue_field_pos == 0))
146
 
        {
147
 
          return GRUB_VIDEO_BLIT_FORMAT_BGR_565;
148
 
        }
149
 
      else if ((mode_info->red_mask_size == 5)
150
 
               && (mode_info->red_field_pos == 0)
151
 
               && (mode_info->green_mask_size == 6)
152
 
               && (mode_info->green_field_pos == 5)
153
 
               && (mode_info->blue_mask_size == 5)
154
 
               && (mode_info->blue_field_pos == 11))
155
 
        {
156
 
          return GRUB_VIDEO_BLIT_FORMAT_RGB_565;
157
 
        }
158
 
    }
159
 
  else if (mode_info->bpp == 1)
160
 
    return GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
161
 
 
162
 
  /* Backup route.  Unknown format.  */
163
 
 
164
 
  /* If there are more than 8 bits per color, assume RGB(A) mode.  */
165
 
  if (mode_info->bpp > 8)
166
 
    {
167
 
      if (mode_info->reserved_mask_size > 0)
168
 
        {
169
 
          return GRUB_VIDEO_BLIT_FORMAT_RGBA;
170
 
        }
171
 
      else
172
 
        {
173
 
          return GRUB_VIDEO_BLIT_FORMAT_RGB;
174
 
        }
175
 
    }
176
 
 
177
 
  /* Assume as indexcolor mode.  */
178
 
  return GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR;
179
 
}
180
 
 
181
 
/* Set new indexed color palette entries.  */
182
 
grub_err_t
183
 
grub_video_set_palette (unsigned int start, unsigned int count,
184
 
                        struct grub_video_palette_data *palette_data)
185
 
{
186
 
  if (! grub_video_adapter_active)
187
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
188
 
 
189
 
  return grub_video_adapter_active->set_palette (start, count, palette_data);
190
 
}
191
 
 
192
 
/* Get indexed color palette entries.  */
193
 
grub_err_t
194
 
grub_video_get_palette (unsigned int start, unsigned int count,
195
 
                        struct grub_video_palette_data *palette_data)
196
 
{
197
 
  if (! grub_video_adapter_active)
198
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
199
 
 
200
 
  return grub_video_adapter_active->get_palette (start, count, palette_data);
201
 
}
202
 
 
203
 
/* Set viewport dimensions.  */
204
 
grub_err_t
205
 
grub_video_set_viewport (unsigned int x, unsigned int y,
206
 
                         unsigned int width, unsigned int height)
207
 
{
208
 
  if (! grub_video_adapter_active)
209
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
210
 
 
211
 
  return grub_video_adapter_active->set_viewport (x, y, width, height);
212
 
}
213
 
 
214
 
/* Get viewport dimensions.  */
215
 
grub_err_t
216
 
grub_video_get_viewport (unsigned int *x, unsigned int *y,
217
 
                         unsigned int *width, unsigned int *height)
218
 
{
219
 
  if (! grub_video_adapter_active)
220
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
221
 
 
222
 
  return grub_video_adapter_active->get_viewport (x, y, width, height);
223
 
}
224
 
 
225
 
/* Map color name to adapter specific color.  */
226
 
grub_video_color_t
227
 
grub_video_map_color (grub_uint32_t color_name)
228
 
{
229
 
  if (! grub_video_adapter_active)
230
 
    return 0;
231
 
 
232
 
  return grub_video_adapter_active->map_color (color_name);
233
 
}
234
 
 
235
 
/* Map RGB value to adapter specific color.  */
236
 
grub_video_color_t
237
 
grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue)
238
 
{
239
 
  if (! grub_video_adapter_active)
240
 
    return 0;
241
 
 
242
 
  return grub_video_adapter_active->map_rgb (red, green, blue);
243
 
}
244
 
 
245
 
/* Map RGBA value to adapter specific color.  */
246
 
grub_video_color_t
247
 
grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue,
248
 
                     grub_uint8_t alpha)
249
 
{
250
 
  if (! grub_video_adapter_active)
251
 
    return 0;
252
 
 
253
 
  return grub_video_adapter_active->map_rgba (red, green, blue, alpha);
254
 
}
255
 
 
256
 
/* Unmap video color back to RGBA components.  */
257
 
grub_err_t
258
 
grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red,
259
 
                        grub_uint8_t *green, grub_uint8_t *blue,
260
 
                        grub_uint8_t *alpha)
261
 
{
262
 
  if (! grub_video_adapter_active)
263
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
264
 
 
265
 
  return grub_video_adapter_active->unmap_color (color,
266
 
                                                 red,
267
 
                                                 green,
268
 
                                                 blue,
269
 
                                                 alpha);
270
 
}
271
 
 
272
 
/* Fill rectangle using specified color.  */
273
 
grub_err_t
274
 
grub_video_fill_rect (grub_video_color_t color, int x, int y,
275
 
                      unsigned int width, unsigned int height)
276
 
{
277
 
  if (! grub_video_adapter_active)
278
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
279
 
 
280
 
  return grub_video_adapter_active->fill_rect (color, x, y, width, height);
281
 
}
282
 
 
283
 
/* Blit bitmap to screen.  */
284
 
grub_err_t
285
 
grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
286
 
                        enum grub_video_blit_operators oper,
287
 
                        int x, int y, int offset_x, int offset_y,
288
 
                        unsigned int width, unsigned int height)
289
 
{
290
 
  if (! grub_video_adapter_active)
291
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
292
 
 
293
 
  return grub_video_adapter_active->blit_bitmap (bitmap, oper, x, y,
294
 
                                                 offset_x, offset_y,
295
 
                                                 width, height);
296
 
}
297
 
 
298
 
/* Blit render target to active render target.  */
299
 
grub_err_t
300
 
grub_video_blit_render_target (struct grub_video_render_target *target,
301
 
                               enum grub_video_blit_operators oper,
302
 
                               int x, int y, int offset_x, int offset_y,
303
 
                               unsigned int width, unsigned int height)
304
 
{
305
 
  if (! grub_video_adapter_active)
306
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
307
 
 
308
 
  return grub_video_adapter_active->blit_render_target (target, oper, x, y,
309
 
                                                        offset_x, offset_y,
310
 
                                                        width, height);
311
 
}
312
 
 
313
 
/* Scroll viewport and fill new areas with specified color.  */
314
 
grub_err_t
315
 
grub_video_scroll (grub_video_color_t color, int dx, int dy)
316
 
{
317
 
  if (! grub_video_adapter_active)
318
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
319
 
 
320
 
  return grub_video_adapter_active->scroll (color, dx, dy);
321
 
}
322
 
 
323
 
/* Swap buffers (swap active render target).  */
324
 
grub_err_t
325
 
grub_video_swap_buffers (void)
326
 
{
327
 
  if (! grub_video_adapter_active)
328
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
329
 
 
330
 
  return grub_video_adapter_active->swap_buffers ();
331
 
}
332
 
 
333
 
/* Create new render target.  */
334
 
grub_err_t
335
 
grub_video_create_render_target (struct grub_video_render_target **result,
336
 
                                 unsigned int width, unsigned int height,
337
 
                                 unsigned int mode_type)
338
 
{
339
 
  if (! grub_video_adapter_active)
340
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
341
 
 
342
 
  return grub_video_adapter_active->create_render_target (result,
343
 
                                                          width, height,
344
 
                                                          mode_type);
345
 
}
346
 
 
347
 
/* Delete render target.  */
348
 
grub_err_t
349
 
grub_video_delete_render_target (struct grub_video_render_target *target)
350
 
{
351
 
  if (! grub_video_adapter_active)
352
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
353
 
 
354
 
  return grub_video_adapter_active->delete_render_target (target);
355
 
}
356
 
 
357
 
/* Set active render target.  */
358
 
grub_err_t
359
 
grub_video_set_active_render_target (struct grub_video_render_target *target)
360
 
{
361
 
  if (! grub_video_adapter_active)
362
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
363
 
 
364
 
  return grub_video_adapter_active->set_active_render_target (target);
365
 
}
366
 
 
367
 
/* Get active render target.  */
368
 
grub_err_t
369
 
grub_video_get_active_render_target (struct grub_video_render_target **target)
370
 
{
371
 
  if (! grub_video_adapter_active)
372
 
    return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
373
 
 
374
 
  return grub_video_adapter_active->get_active_render_target (target);
375
 
}
376
 
 
377
 
/* Parse <width>x<height>[x<depth>]*/
378
 
static grub_err_t
379
 
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
380
 
{
381
 
  const char *value;
382
 
  const char *param = current_mode;
383
 
 
384
 
  *width = *height = *depth = -1;
385
 
 
386
 
  if (grub_strcmp (param, "auto") == 0)
387
 
    {
388
 
      *width = *height = 0;
389
 
      return GRUB_ERR_NONE;
390
 
    }
391
 
 
392
 
  /* Find width value.  */
393
 
  value = param;
394
 
  param = grub_strchr(param, 'x');
395
 
  if (param == NULL)
396
 
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
397
 
                       "Invalid mode: %s\n",
398
 
                       current_mode);
399
 
 
400
 
  param++;
401
 
  
402
 
  *width = grub_strtoul (value, 0, 0);
403
 
  if (grub_errno != GRUB_ERR_NONE)
404
 
      return grub_error (GRUB_ERR_BAD_ARGUMENT,
405
 
                         "Invalid mode: %s\n",
406
 
                         current_mode);
407
 
  
408
 
  /* Find height value.  */
409
 
  value = param;
410
 
  param = grub_strchr(param, 'x');
411
 
  if (param == NULL)
412
 
    {
413
 
      *height = grub_strtoul (value, 0, 0);
414
 
      if (grub_errno != GRUB_ERR_NONE)
415
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT,
416
 
                           "Invalid mode: %s\n",
417
 
                           current_mode);
418
 
    }
419
 
  else
420
 
    {
421
 
      /* We have optional color depth value.  */
422
 
      param++;
423
 
      
424
 
      *height = grub_strtoul (value, 0, 0);
425
 
      if (grub_errno != GRUB_ERR_NONE)
426
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT,
427
 
                           "Invalid mode: %s\n",
428
 
                           current_mode);
429
 
      
430
 
      /* Convert color depth value.  */
431
 
      value = param;
432
 
      *depth = grub_strtoul (value, 0, 0);
433
 
      if (grub_errno != GRUB_ERR_NONE)
434
 
        return grub_error (GRUB_ERR_BAD_ARGUMENT,
435
 
                           "Invalid mode: %s\n",
436
 
                           current_mode);
437
 
    }
438
 
  return GRUB_ERR_NONE;
439
 
}
440
 
 
441
 
grub_err_t
442
 
grub_video_set_mode (const char *modestring,
443
 
                     unsigned int modemask,
444
 
                     unsigned int modevalue)
445
 
{
446
 
  char *tmp;
447
 
  char *next_mode;
448
 
  char *current_mode;
449
 
  char *modevar;
450
 
 
451
 
  modevalue &= modemask;
452
 
 
453
 
  /* Take copy of env.var. as we don't want to modify that.  */
454
 
  modevar = grub_strdup (modestring);
455
 
 
456
 
  /* Initialize next mode.  */
457
 
  next_mode = modevar;
458
 
 
459
 
  if (! modevar)
460
 
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
461
 
                       "couldn't allocate space for local modevar copy");
462
 
 
463
 
  if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0
464
 
      || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
465
 
      || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
466
 
    {
467
 
      int suitable = 1;
468
 
      grub_err_t err;
469
 
 
470
 
      if (grub_video_adapter_active)
471
 
        {
472
 
          struct grub_video_mode_info mode_info;
473
 
          grub_memset (&mode_info, 0, sizeof (mode_info));
474
 
          err = grub_video_get_info (&mode_info);
475
 
          if (err)
476
 
            {
477
 
              suitable = 0;
478
 
              grub_errno = GRUB_ERR_NONE;
479
 
            }
480
 
          if ((mode_info.mode_type & modemask) != modevalue)
481
 
            suitable = 0;
482
 
        }
483
 
      else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
484
 
               && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
485
 
        suitable = 0;
486
 
 
487
 
      if (suitable)
488
 
        {
489
 
          grub_free (modevar);
490
 
          return GRUB_ERR_NONE;
491
 
        }
492
 
      next_mode += sizeof ("keep") - 1;
493
 
      if (! *next_mode)
494
 
        {
495
 
          grub_free (modevar);
496
 
 
497
 
          return grub_error (GRUB_ERR_BAD_ARGUMENT,
498
 
                             "no suitable mode found");
499
 
        }
500
 
 
501
 
      /* Skip separator. */
502
 
      next_mode++;
503
 
    }
504
 
 
505
 
  /* De-activate last set video adapter.  */
506
 
  if (grub_video_adapter_active)
507
 
    {
508
 
      /* Finalize adapter.  */
509
 
      grub_video_adapter_active->fini ();
510
 
      if (grub_errno != GRUB_ERR_NONE)
511
 
        grub_errno = GRUB_ERR_NONE;
512
 
 
513
 
      /* Mark active adapter as not set.  */
514
 
      grub_video_adapter_active = 0;
515
 
    }
516
 
 
517
 
  /* Loop until all modes has been tested out.  */
518
 
  while (next_mode != NULL)
519
 
    {
520
 
      int width = -1;
521
 
      int height = -1;
522
 
      int depth = -1;
523
 
      grub_err_t err;
524
 
      unsigned int flags = modevalue;
525
 
      unsigned int flagmask = modemask;
526
 
 
527
 
      /* Use last next_mode as current mode.  */
528
 
      tmp = next_mode;
529
 
 
530
 
      /* Save position of next mode and separate modes.  */
531
 
      for (; *next_mode; next_mode++)
532
 
        if (*next_mode == ',' || *next_mode == ';')
533
 
          break;
534
 
      if (*next_mode)
535
 
        {
536
 
          *next_mode = 0;
537
 
          next_mode++;
538
 
        }
539
 
      else
540
 
        next_mode = 0;
541
 
 
542
 
      /* Skip whitespace.  */
543
 
      while (grub_isspace (*tmp))
544
 
        tmp++;
545
 
 
546
 
      /* Initialize token holders.  */
547
 
      current_mode = tmp;
548
 
 
549
 
      /* XXX: we assume that we're in pure text mode if
550
 
         no video mode is initialized. Is it always true? */
551
 
      if (grub_strcmp (current_mode, "text") == 0)
552
 
        {
553
 
          struct grub_video_mode_info mode_info;
554
 
 
555
 
          grub_memset (&mode_info, 0, sizeof (mode_info));
556
 
          if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0)
557
 
              || ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0))
558
 
            {
559
 
              /* Valid mode found from adapter, and it has been activated.
560
 
                 Specify it as active adapter.  */
561
 
              grub_video_adapter_active = NULL;
562
 
 
563
 
              /* Free memory.  */
564
 
              grub_free (modevar);
565
 
 
566
 
              return GRUB_ERR_NONE;
567
 
            }
568
 
        }
569
 
 
570
 
      err = parse_modespec (current_mode, &width, &height, &depth);
571
 
      if (err)
572
 
        {
573
 
          /* Free memory before returning.  */
574
 
          grub_free (modevar);
575
 
 
576
 
          return err;
577
 
        }
578
 
 
579
 
      /* Try out video mode.  */
580
 
 
581
 
      /* If user requested specific depth check if this depth is supported.  */
582
 
      if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
583
 
          &&
584
 
          (((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
585
 
            != ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
586
 
                & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK))))
587
 
        continue;
588
 
 
589
 
      if (depth != -1)
590
 
        {
591
 
          flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
592
 
            & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
593
 
          flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
594
 
        }
595
 
 
596
 
      /* Try to initialize requested mode.  Ignore any errors.  */
597
 
      grub_video_adapter_t p;
598
 
 
599
 
      /* Loop thru all possible video adapter trying to find requested mode.  */
600
 
      for (p = grub_video_adapter_list; p; p = p->next)
601
 
        {
602
 
          struct grub_video_mode_info mode_info;
603
 
 
604
 
          grub_memset (&mode_info, 0, sizeof (mode_info));
605
 
 
606
 
          /* Try to initialize adapter, if it fails, skip to next adapter.  */
607
 
          err = p->init ();
608
 
          if (err != GRUB_ERR_NONE)
609
 
            {
610
 
              grub_errno = GRUB_ERR_NONE;
611
 
              continue;
612
 
            }
613
 
 
614
 
          /* Try to initialize video mode.  */
615
 
          err = p->setup (width, height, flags, flagmask);
616
 
          if (err != GRUB_ERR_NONE)
617
 
            {
618
 
              p->fini ();
619
 
              grub_errno = GRUB_ERR_NONE;
620
 
              continue;
621
 
            }
622
 
 
623
 
          err = p->get_info (&mode_info);
624
 
          if (err != GRUB_ERR_NONE)
625
 
            {
626
 
              p->fini ();
627
 
              grub_errno = GRUB_ERR_NONE;
628
 
              continue;
629
 
            }
630
 
 
631
 
          flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
632
 
          flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
633
 
            & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
634
 
 
635
 
          /* Check that mode is suitable for upper layer.  */
636
 
          if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
637
 
              ? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
638
 
                 && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
639
 
              : ((flags & modemask) != modevalue))
640
 
            {
641
 
              p->fini ();
642
 
              grub_errno = GRUB_ERR_NONE;
643
 
              continue;
644
 
            }
645
 
 
646
 
          /* Valid mode found from adapter, and it has been activated.
647
 
             Specify it as active adapter.  */
648
 
          grub_video_adapter_active = p;
649
 
 
650
 
          /* Free memory.  */
651
 
          grub_free (modevar);
652
 
 
653
 
          return GRUB_ERR_NONE;
654
 
        }
655
 
 
656
 
    }
657
 
 
658
 
  /* Free memory.  */
659
 
  grub_free (modevar);
660
 
 
661
 
  return grub_error (GRUB_ERR_BAD_ARGUMENT,
662
 
                     "no suitable mode found");
663
 
}
664
 
 
665
 
/* Initialize Video API module.  */
666
 
GRUB_MOD_INIT(video)
667
 
{
668
 
}
669
 
 
670
 
/* Finalize Video API module.  */
671
 
GRUB_MOD_FINI(video)
672
 
{
673
 
}