2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
19
#define grub_video_render_target grub_video_fbrender_target
22
#include <grub/machine/memory.h>
23
#include <grub/machine/vga.h>
24
#include <grub/machine/vbe.h>
25
#include <grub/video_fb.h>
26
#include <grub/types.h>
28
#include <grub/misc.h>
30
#include <grub/video.h>
31
#include <grub/machine/int.h>
33
static int vbe_detected = -1;
35
static struct grub_vbe_info_block controller_info;
37
/* Track last mode to support cards which fail on get_mode. */
38
static grub_uint32_t last_set_mode = 3;
42
struct grub_video_mode_info mode_info;
47
static grub_uint32_t initial_vbe_mode;
48
static grub_uint16_t *vbe_mode_list;
51
real2pm (grub_vbe_farptr_t ptr)
53
return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
54
+ ((unsigned long) ptr & 0x0000FFFF));
57
/* Call VESA BIOS 0x4f09 to set palette data, return status. */
58
static grub_vbe_status_t
59
grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
60
grub_uint32_t start_index,
61
struct grub_vbe_palette_data *palette_data)
63
struct grub_bios_int_registers regs;
66
regs.ecx = color_count;
67
regs.edx = start_index;
68
regs.es = (((grub_addr_t) palette_data) & 0xffff0000) >> 4;
69
regs.edi = ((grub_addr_t) palette_data) & 0xffff;
70
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
71
grub_bios_interrupt (0x10, ®s);
72
return regs.eax & 0xffff;
75
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
77
grub_vbe_bios_get_controller_info (struct grub_vbe_info_block *ci)
79
struct grub_bios_int_registers regs;
80
/* Store *controller_info to %es:%di. */
81
regs.es = (((grub_addr_t) ci) & 0xffff0000) >> 4;
82
regs.edi = ((grub_addr_t) ci) & 0xffff;
84
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
85
grub_bios_interrupt (0x10, ®s);
86
return regs.eax & 0xffff;
89
/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */
91
grub_vbe_bios_get_mode_info (grub_uint32_t mode,
92
struct grub_vbe_mode_info_block *mode_info)
94
struct grub_bios_int_registers regs;
97
/* Store *mode_info to %es:%di. */
98
regs.es = ((grub_addr_t) mode_info & 0xffff0000) >> 4;
99
regs.edi = (grub_addr_t) mode_info & 0x0000ffff;
100
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
101
grub_bios_interrupt (0x10, ®s);
102
return regs.eax & 0xffff;
105
/* Call VESA BIOS 0x4f02 to set video mode, return status. */
106
static grub_vbe_status_t
107
grub_vbe_bios_set_mode (grub_uint32_t mode,
108
struct grub_vbe_crtc_info_block *crtc_info)
110
struct grub_bios_int_registers regs;
114
/* Store *crtc_info to %es:%di. */
115
regs.es = (((grub_addr_t) crtc_info) & 0xffff0000) >> 4;
116
regs.edi = ((grub_addr_t) crtc_info) & 0xffff;
117
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
118
grub_bios_interrupt (0x10, ®s);
120
return regs.eax & 0xffff;
123
/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */
125
grub_vbe_bios_get_mode (grub_uint32_t *mode)
127
struct grub_bios_int_registers regs;
130
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
131
grub_bios_interrupt (0x10, ®s);
132
*mode = regs.ebx & 0xffff;
134
return regs.eax & 0xffff;
138
grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size)
140
struct grub_bios_int_registers regs;
143
regs.ebx = (*dac_mask_size & 0xff) >> 8;
144
regs.ebx = set ? 1 : 0;
145
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
146
grub_bios_interrupt (0x10, ®s);
147
*dac_mask_size = (regs.ebx >> 8) & 0xff;
149
return regs.eax & 0xffff;
152
/* Call VESA BIOS 0x4f05 to set memory window, return status. */
154
grub_vbe_bios_set_memory_window (grub_uint32_t window,
155
grub_uint32_t position)
157
struct grub_bios_int_registers regs;
159
/* BL = window, BH = 0, Set memory window. */
160
regs.ebx = window & 0x00ff;
163
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
164
grub_bios_interrupt (0x10, ®s);
165
return regs.eax & 0xffff;
168
/* Call VESA BIOS 0x4f05 to return memory window, return status. */
170
grub_vbe_bios_get_memory_window (grub_uint32_t window,
171
grub_uint32_t *position)
173
struct grub_bios_int_registers regs;
176
/* BH = 1, Get memory window. BL = window. */
177
regs.ebx = (window & 0x00ff) | 0x100;
178
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
179
grub_bios_interrupt (0x10, ®s);
181
*position = regs.edx & 0xffff;
182
return regs.eax & 0xffff;
185
/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */
187
grub_vbe_bios_set_scanline_length (grub_uint32_t length)
189
struct grub_bios_int_registers regs;
193
/* BL = 2, Set Scan Line in Bytes. */
195
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
196
grub_bios_interrupt (0x10, ®s);
197
return regs.eax & 0xffff;
200
/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */
202
grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
204
struct grub_bios_int_registers regs;
208
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
209
/* BL = 1, Get Scan Line Length (in bytes). */
210
grub_bios_interrupt (0x10, ®s);
212
*length = regs.ebx & 0xffff;
213
return regs.eax & 0xffff;
216
/* Call VESA BIOS 0x4f07 to set display start, return status. */
217
static grub_vbe_status_t
218
grub_vbe_bios_set_display_start (grub_uint32_t x, grub_uint32_t y)
220
struct grub_bios_int_registers regs;
222
/* Store x in %ecx. */
226
/* BL = 80h, Set Display Start during Vertical Retrace. */
228
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
229
grub_bios_interrupt (0x10, ®s);
230
return regs.eax & 0xffff;
233
/* Call VESA BIOS 0x4f07 to get display start, return status. */
235
grub_vbe_bios_get_display_start (grub_uint32_t *x,
238
struct grub_bios_int_registers regs;
241
/* BL = 1, Get Display Start. */
243
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
244
grub_bios_interrupt (0x10, ®s);
246
*x = regs.ecx & 0xffff;
247
*y = regs.edx & 0xffff;
248
return regs.eax & 0xffff;
251
/* Call VESA BIOS 0x4f0a. */
253
grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset,
254
grub_uint16_t *length)
256
struct grub_bios_int_registers regs;
260
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
261
grub_bios_interrupt (0x10, ®s);
263
if ((regs.eax & 0xffff) != GRUB_VBE_STATUS_OK)
270
*segment = regs.es & 0xffff;
271
*offset = regs.edi & 0xffff;
272
*length = regs.ecx & 0xffff;
273
return regs.eax & 0xffff;
278
grub_vbe_probe (struct grub_vbe_info_block *info_block)
280
struct grub_vbe_info_block *vbe_ib;
281
grub_vbe_status_t status;
283
/* Clear caller's controller info block. */
285
grub_memset (info_block, 0, sizeof (*info_block));
287
/* Do not probe more than one time, if not necessary. */
288
if (vbe_detected == -1 || info_block)
290
/* Clear old copy of controller info block. */
291
grub_memset (&controller_info, 0, sizeof (controller_info));
293
/* Mark VESA BIOS extension as undetected. */
296
/* Use low memory scratch area as temporary storage
297
for VESA BIOS call. */
298
vbe_ib = (struct grub_vbe_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
300
/* Prepare info block. */
301
grub_memset (vbe_ib, 0, sizeof (*vbe_ib));
303
vbe_ib->signature[0] = 'V';
304
vbe_ib->signature[1] = 'B';
305
vbe_ib->signature[2] = 'E';
306
vbe_ib->signature[3] = '2';
308
/* Try to get controller info block. */
309
status = grub_vbe_bios_get_controller_info (vbe_ib);
310
if (status == GRUB_VBE_STATUS_OK)
312
/* Copy it for later usage. */
313
grub_memcpy (&controller_info, vbe_ib, sizeof (controller_info));
315
/* Mark VESA BIOS extension as detected. */
321
return grub_error (GRUB_ERR_BAD_DEVICE, "VESA BIOS Extension not found");
323
/* Make copy of controller info block to caller. */
325
grub_memcpy (info_block, &controller_info, sizeof (*info_block));
327
return GRUB_ERR_NONE;
331
grub_vbe_set_video_mode (grub_uint32_t vbe_mode,
332
struct grub_vbe_mode_info_block *vbe_mode_info)
334
grub_vbe_status_t status;
335
grub_uint32_t old_vbe_mode;
336
struct grub_vbe_mode_info_block new_vbe_mode_info;
339
/* Make sure that VBE is supported. */
341
if (grub_errno != GRUB_ERR_NONE)
344
/* Try to get mode info. */
345
grub_vbe_get_video_mode_info (vbe_mode, &new_vbe_mode_info);
346
if (grub_errno != GRUB_ERR_NONE)
349
/* For all VESA BIOS modes, force linear frame buffer. */
350
if (vbe_mode >= 0x100)
352
/* We only want linear frame buffer modes. */
355
/* Determine frame buffer pixel format. */
356
if (new_vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL
357
&& new_vbe_mode_info.memory_model
358
!= GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
359
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
360
"unsupported pixel format 0x%x",
361
new_vbe_mode_info.memory_model);
364
/* Get current mode. */
365
grub_vbe_get_video_mode (&old_vbe_mode);
366
if (grub_errno != GRUB_ERR_NONE)
369
/* Try to set video mode. */
370
status = grub_vbe_bios_set_mode (vbe_mode, 0);
371
if (status != GRUB_VBE_STATUS_OK)
372
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", vbe_mode);
373
last_set_mode = vbe_mode;
375
if (vbe_mode < 0x100)
377
/* If this is not a VESA mode, guess address. */
378
framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR;
382
framebuffer.ptr = (grub_uint8_t *) new_vbe_mode_info.phys_base_addr;
385
/* Check whether mode is text mode or graphics mode. */
386
if (new_vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
390
/* No special action needed for text mode as it is not supported for
391
graphical support. */
397
/* If video mode is in indexed color, setup default VGA palette. */
398
if (vbe_mode < 0x100 || new_vbe_mode_info.memory_model
399
== GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
401
struct grub_vbe_palette_data *palette
402
= (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
405
/* Make sure that the BIOS can reach the palette. */
406
for (i = 0; i < GRUB_VIDEO_FBSTD_NUMCOLORS; i++)
408
palette[i].red = grub_video_fbstd_colors[i].r;
409
palette[i].green = grub_video_fbstd_colors[i].g;
410
palette[i].blue = grub_video_fbstd_colors[i].b;
411
palette[i].alignment = 0;
414
status = grub_vbe_bios_set_palette_data (GRUB_VIDEO_FBSTD_NUMCOLORS,
417
/* Just ignore the status. */
418
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
419
grub_video_fbstd_colors);
426
/* Copy mode info for caller. */
428
grub_memcpy (vbe_mode_info, &new_vbe_mode_info, sizeof (*vbe_mode_info));
430
return GRUB_ERR_NONE;
434
grub_vbe_get_video_mode (grub_uint32_t *mode)
436
grub_vbe_status_t status;
438
/* Make sure that VBE is supported. */
440
if (grub_errno != GRUB_ERR_NONE)
443
/* Try to query current mode from VESA BIOS. */
444
status = grub_vbe_bios_get_mode (mode);
445
/* XXX: ATI cards don't support get_mode. */
446
if (status != GRUB_VBE_STATUS_OK)
447
*mode = last_set_mode;
449
return GRUB_ERR_NONE;
453
grub_vbe_get_video_mode_info (grub_uint32_t mode,
454
struct grub_vbe_mode_info_block *mode_info)
456
struct grub_vbe_mode_info_block *mi_tmp
457
= (struct grub_vbe_mode_info_block *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
458
grub_vbe_status_t status;
460
/* Make sure that VBE is supported. */
462
if (grub_errno != GRUB_ERR_NONE)
465
/* If mode is not VESA mode, skip mode info query. */
468
/* Try to get mode info from VESA BIOS. */
469
status = grub_vbe_bios_get_mode_info (mode, mi_tmp);
470
if (status != GRUB_VBE_STATUS_OK)
471
return grub_error (GRUB_ERR_BAD_DEVICE,
472
"cannot get information on the mode %x", mode);
474
/* Make copy of mode info block. */
475
grub_memcpy (mode_info, mi_tmp, sizeof (*mode_info));
478
/* Just clear mode info block if it isn't a VESA mode. */
479
grub_memset (mode_info, 0, sizeof (*mode_info));
481
return GRUB_ERR_NONE;
485
grub_video_vbe_init (void)
487
grub_uint16_t *rm_vbe_mode_list;
489
grub_size_t vbe_mode_list_size;
490
struct grub_vbe_info_block info_block;
492
/* Check if there is adapter present.
494
Firmware note: There has been a report that some cards store video mode
495
list in temporary memory. So we must first use vbe probe to get
496
refreshed information to receive valid pointers and data, and then
497
copy this information to somewhere safe. */
498
grub_vbe_probe (&info_block);
499
if (grub_errno != GRUB_ERR_NONE)
502
/* Copy modelist to local memory. */
503
p = rm_vbe_mode_list = real2pm (info_block.video_mode_ptr);
504
while(*p++ != 0xFFFF)
507
vbe_mode_list_size = (grub_addr_t) p - (grub_addr_t) rm_vbe_mode_list;
508
vbe_mode_list = grub_malloc (vbe_mode_list_size);
511
grub_memcpy (vbe_mode_list, rm_vbe_mode_list, vbe_mode_list_size);
513
/* Adapter could be found, figure out initial video mode. */
514
grub_vbe_get_video_mode (&initial_vbe_mode);
515
if (grub_errno != GRUB_ERR_NONE)
517
/* Free allocated resources. */
518
grub_free (vbe_mode_list);
519
vbe_mode_list = NULL;
524
/* Reset frame buffer. */
525
grub_memset (&framebuffer, 0, sizeof(framebuffer));
527
return grub_video_fb_init ();
531
grub_video_vbe_fini (void)
533
grub_vbe_status_t status;
536
/* Restore old video mode. */
537
if (last_set_mode != initial_vbe_mode)
539
status = grub_vbe_bios_set_mode (initial_vbe_mode, 0);
540
if (status != GRUB_VBE_STATUS_OK)
541
/* TODO: Decide, is this something we want to do. */
544
last_set_mode = initial_vbe_mode;
546
/* TODO: Free any resources allocated by driver. */
547
grub_free (vbe_mode_list);
548
vbe_mode_list = NULL;
550
err = grub_video_fb_fini ();
555
Set framebuffer render target page and display the proper page, based on
556
`doublebuf_state.render_page' and `doublebuf_state.displayed_page',
560
doublebuf_pageflipping_set_page (int page)
562
/* Tell the video adapter to display the new front page. */
563
int display_start_line
564
= framebuffer.mode_info.height * page;
566
grub_vbe_status_t vbe_err =
567
grub_vbe_bios_set_display_start (0, display_start_line);
569
if (vbe_err != GRUB_VBE_STATUS_OK)
570
return grub_error (GRUB_ERR_IO, "couldn't commit pageflip");
576
vbe2videoinfo (grub_uint32_t mode,
577
const struct grub_vbe_mode_info_block *vbeinfo,
578
struct grub_video_mode_info *mode_info)
580
mode_info->mode_number = mode;
582
mode_info->width = vbeinfo->x_resolution;
583
mode_info->height = vbeinfo->y_resolution;
584
mode_info->mode_type = 0;
585
switch (vbeinfo->memory_model)
587
case GRUB_VBE_MEMORY_MODEL_TEXT:
588
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
591
/* CGA is basically 4-bit packed pixel. */
592
case GRUB_VBE_MEMORY_MODEL_CGA:
593
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_CGA;
594
case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
595
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
598
case GRUB_VBE_MEMORY_MODEL_HERCULES:
599
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_HERCULES
600
| GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
603
/* Non chain 4 is a special case of planar. */
604
case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256:
605
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_NONCHAIN4;
606
case GRUB_VBE_MEMORY_MODEL_PLANAR:
607
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR
608
| GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
611
case GRUB_VBE_MEMORY_MODEL_YUV:
612
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_YUV;
615
case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
616
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
619
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UNKNOWN;
623
mode_info->bpp = vbeinfo->bits_per_pixel;
624
/* Calculate bytes_per_pixel value. */
625
switch(vbeinfo->bits_per_pixel)
628
mode_info->bytes_per_pixel = 4;
631
mode_info->bytes_per_pixel = 3;
634
mode_info->bytes_per_pixel = 2;
637
mode_info->bytes_per_pixel = 2;
640
mode_info->bytes_per_pixel = 1;
643
mode_info->bytes_per_pixel = 0;
647
if (controller_info.version >= 0x300)
648
mode_info->pitch = vbeinfo->lin_bytes_per_scan_line;
650
mode_info->pitch = vbeinfo->bytes_per_scan_line;
652
mode_info->number_of_colors = 256; /* TODO: fix me. */
653
mode_info->red_mask_size = vbeinfo->red_mask_size;
654
mode_info->red_field_pos = vbeinfo->red_field_position;
655
mode_info->green_mask_size = vbeinfo->green_mask_size;
656
mode_info->green_field_pos = vbeinfo->green_field_position;
657
mode_info->blue_mask_size = vbeinfo->blue_mask_size;
658
mode_info->blue_field_pos = vbeinfo->blue_field_position;
659
mode_info->reserved_mask_size = vbeinfo->rsvd_mask_size;
660
mode_info->reserved_field_pos = vbeinfo->rsvd_field_position;
662
mode_info->blit_format = grub_video_get_blit_format (mode_info);
666
grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info))
669
struct grub_vbe_mode_info_block vbe_mode_info;
670
struct grub_video_mode_info mode_info;
672
for (p = vbe_mode_list; *p != 0xFFFF; p++)
674
grub_vbe_get_video_mode_info (*p, &vbe_mode_info);
675
if (grub_errno != GRUB_ERR_NONE)
677
/* Could not retrieve mode info, retreat. */
678
grub_errno = GRUB_ERR_NONE;
682
vbe2videoinfo (*p, &vbe_mode_info, &mode_info);
683
if (hook (&mode_info))
690
grub_video_vbe_setup (unsigned int width, unsigned int height,
691
unsigned int mode_type, unsigned int mode_mask)
694
struct grub_vbe_mode_info_block vbe_mode_info;
695
struct grub_vbe_mode_info_block best_vbe_mode_info;
696
grub_uint32_t best_vbe_mode = 0;
699
/* Decode depth from mode_type. If it is zero, then autodetect. */
700
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
701
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
703
/* Walk thru mode list and try to find matching mode. */
704
for (p = vbe_mode_list; *p != 0xFFFF; p++)
706
grub_uint32_t vbe_mode = *p;
708
grub_vbe_get_video_mode_info (vbe_mode, &vbe_mode_info);
709
if (grub_errno != GRUB_ERR_NONE)
711
/* Could not retrieve mode info, retreat. */
712
grub_errno = GRUB_ERR_NONE;
716
if ((vbe_mode_info.mode_attributes & 0x001) == 0)
717
/* If not available, skip it. */
720
if ((vbe_mode_info.mode_attributes & 0x008) == 0)
721
/* Monochrome is unusable. */
724
if ((vbe_mode_info.mode_attributes & 0x080) == 0)
725
/* We support only linear frame buffer modes. */
728
if ((vbe_mode_info.mode_attributes & 0x010) == 0)
729
/* We allow only graphical modes. */
732
if ((vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
733
&& (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
734
/* Not compatible memory model. */
737
if (vbe_mode_info.bits_per_pixel != 8
738
&& vbe_mode_info.bits_per_pixel != 15
739
&& vbe_mode_info.bits_per_pixel != 16
740
&& vbe_mode_info.bits_per_pixel != 24
741
&& vbe_mode_info.bits_per_pixel != 32)
742
/* Unsupported bitdepth . */
745
if (((vbe_mode_info.x_resolution != width)
746
|| (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0)
747
/* Non matching resolution. */
750
/* Check if user requested RGB or index color mode. */
751
if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
753
unsigned my_mode_type = 0;
755
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
756
my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
758
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
759
my_mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
761
if ((my_mode_type & mode_mask
762
& (GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR))
763
!= (mode_type & mode_mask
764
& (GRUB_VIDEO_MODE_TYPE_RGB
765
| GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)))
769
/* If there is a request for specific depth, ignore others. */
770
if ((depth != 0) && (vbe_mode_info.bits_per_pixel != depth))
773
/* Select mode with most of "volume" (size of framebuffer in bits). */
774
if (best_vbe_mode != 0)
775
if ((grub_uint64_t) vbe_mode_info.bits_per_pixel
776
* vbe_mode_info.x_resolution * vbe_mode_info.y_resolution
777
< (grub_uint64_t) best_vbe_mode_info.bits_per_pixel
778
* best_vbe_mode_info.x_resolution * best_vbe_mode_info.y_resolution)
781
/* Save so far best mode information for later use. */
782
best_vbe_mode = vbe_mode;
783
grub_memcpy (&best_vbe_mode_info, &vbe_mode_info, sizeof (vbe_mode_info));
786
/* Try to initialize best mode found. */
787
if (best_vbe_mode != 0)
790
static struct grub_vbe_mode_info_block active_vbe_mode_info;
791
/* If this fails, then we have mode selection heuristics problem,
792
or adapter failure. */
793
grub_vbe_set_video_mode (best_vbe_mode, &active_vbe_mode_info);
794
if (grub_errno != GRUB_ERR_NONE)
797
/* Fill mode info details. */
798
vbe2videoinfo (best_vbe_mode, &active_vbe_mode_info,
799
&framebuffer.mode_info);
802
/* Get video RAM size in bytes. */
803
grub_size_t vram_size = controller_info.total_memory << 16;
804
grub_size_t page_size; /* The size of a page in bytes. */
806
page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height;
808
if (vram_size >= 2 * page_size)
809
err = grub_video_fb_setup (mode_type, mode_mask,
810
&framebuffer.mode_info,
812
doublebuf_pageflipping_set_page,
813
framebuffer.ptr + page_size);
815
err = grub_video_fb_setup (mode_type, mode_mask,
816
&framebuffer.mode_info,
817
framebuffer.ptr, 0, 0);
820
/* Copy default palette to initialize emulated palette. */
821
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
822
grub_video_fbstd_colors);
826
/* Couldn't found matching mode. */
827
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
831
grub_video_vbe_set_palette (unsigned int start, unsigned int count,
832
struct grub_video_palette_data *palette_data)
834
if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
836
/* TODO: Implement setting indexed color mode palette to hardware. */
837
//status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
838
// / sizeof (struct grub_vbe_palette_data),
844
/* Then set color to emulated palette. */
846
return grub_video_fb_set_palette (start, count, palette_data);
850
grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
853
grub_free (vbe_mode_list);
854
vbe_mode_list = NULL;
855
return grub_video_fb_get_info_and_fini (mode_info, framebuf);
859
grub_video_vbe_print_adapter_specific_info (void)
861
grub_printf (" VBE info: version: %d.%d OEM software rev: %d.%d\n",
862
controller_info.version >> 8,
863
controller_info.version & 0xFF,
864
controller_info.oem_software_rev >> 8,
865
controller_info.oem_software_rev & 0xFF);
867
/* The total_memory field is in 64 KiB units. */
868
grub_printf (" total memory: %d KiB\n",
869
(controller_info.total_memory << 16) / 1024);
872
static struct grub_video_adapter grub_video_vbe_adapter =
874
.name = "VESA BIOS Extension Video Driver",
875
.id = GRUB_VIDEO_DRIVER_VBE,
877
.prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE,
879
.init = grub_video_vbe_init,
880
.fini = grub_video_vbe_fini,
881
.setup = grub_video_vbe_setup,
882
.get_info = grub_video_fb_get_info,
883
.get_info_and_fini = grub_video_vbe_get_info_and_fini,
884
.set_palette = grub_video_vbe_set_palette,
885
.get_palette = grub_video_fb_get_palette,
886
.set_viewport = grub_video_fb_set_viewport,
887
.get_viewport = grub_video_fb_get_viewport,
888
.map_color = grub_video_fb_map_color,
889
.map_rgb = grub_video_fb_map_rgb,
890
.map_rgba = grub_video_fb_map_rgba,
891
.unmap_color = grub_video_fb_unmap_color,
892
.fill_rect = grub_video_fb_fill_rect,
893
.blit_bitmap = grub_video_fb_blit_bitmap,
894
.blit_render_target = grub_video_fb_blit_render_target,
895
.scroll = grub_video_fb_scroll,
896
.swap_buffers = grub_video_fb_swap_buffers,
897
.create_render_target = grub_video_fb_create_render_target,
898
.delete_render_target = grub_video_fb_delete_render_target,
899
.set_active_render_target = grub_video_fb_set_active_render_target,
900
.get_active_render_target = grub_video_fb_get_active_render_target,
901
.iterate = grub_video_vbe_iterate,
902
.print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info,
907
GRUB_MOD_INIT(video_i386_pc_vbe)
909
grub_video_register (&grub_video_vbe_adapter);
912
GRUB_MOD_FINI(video_i386_pc_vbe)
914
grub_video_unregister (&grub_video_vbe_adapter);