2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 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
21 #include <grub/i386/pc/int.h>
22 #include <grub/machine/console.h>
23 #include <grub/cpu/io.h>
25 #include <grub/video.h>
26 #include <grub/video_fb.h>
27 #include <grub/types.h>
29 #include <grub/misc.h>
32 GRUB_MOD_LICENSE ("GPLv3+");
35 #define VGA_HEIGHT 350
36 #define VGA_MEM ((grub_uint8_t *) 0xa0000)
37 #define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8))
39 static unsigned char text_mode
;
40 static unsigned char saved_map_mask
;
44 struct grub_video_mode_info mode_info
;
45 struct grub_video_render_target
*render_target
;
46 grub_uint8_t
*temporary_buffer
;
52 grub_vga_set_mode (unsigned char mode
)
54 struct grub_bios_int_registers regs
;
56 /* get current mode */
59 regs
.flags
= GRUB_CPU_INT_FLAGS_DEFAULT
;
60 grub_bios_interrupt (0x10, ®s
);
62 ret
= regs
.eax
& 0xff;
64 regs
.flags
= GRUB_CPU_INT_FLAGS_DEFAULT
;
65 grub_bios_interrupt (0x10, ®s
);
73 /* Wait until there is a vertical retrace. */
74 while (! (grub_inb (GRUB_VGA_IO_INPUT_STATUS1_REGISTER
)
75 & GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT
));
78 /* Get Map Mask Register. */
82 return grub_vga_sr_read (GRUB_VGA_SR_MAP_MASK_REGISTER
);
85 /* Set Map Mask Register. */
87 set_map_mask (unsigned char mask
)
89 grub_vga_sr_write (mask
, GRUB_VGA_SR_MAP_MASK_REGISTER
);
93 /* Set Read Map Register. */
95 set_read_map (unsigned char map
)
97 grub_vga_gr_write (map
, GRUB_VGA_GR_READ_MAP_REGISTER
);
101 /* Set start address. */
103 set_start_address (unsigned int start
)
105 grub_vga_cr_write (start
& 0xFF, GRUB_VGA_CR_START_ADDR_LOW_REGISTER
);
106 grub_vga_cr_write (start
>> 8, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER
);
109 static int setup
= 0;
110 static int is_target
= 0;
113 grub_video_vga_init (void)
115 return GRUB_ERR_NONE
;
119 grub_video_vga_setup (unsigned int width
, unsigned int height
,
120 grub_video_mode_type_t mode_type
,
121 grub_video_mode_type_t mode_mask
)
125 if ((width
&& width
!= VGA_WIDTH
) || (height
&& height
!= VGA_HEIGHT
))
126 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no matching mode found");
128 framebuffer
.temporary_buffer
= grub_malloc (VGA_HEIGHT
* VGA_WIDTH
);
129 framebuffer
.front_page
= 0;
130 framebuffer
.back_page
= 0;
131 if (!framebuffer
.temporary_buffer
)
134 saved_map_mask
= get_map_mask ();
136 text_mode
= grub_vga_set_mode (0x10);
139 set_start_address (PAGE_OFFSET (framebuffer
.front_page
));
141 framebuffer
.mode_info
.width
= VGA_WIDTH
;
142 framebuffer
.mode_info
.height
= VGA_HEIGHT
;
144 framebuffer
.mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
;
146 if (grub_video_check_mode_flag (mode_type
, mode_mask
,
147 GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
, 1))
149 framebuffer
.back_page
= 1;
150 framebuffer
.mode_info
.mode_type
|= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
;
153 framebuffer
.mode_info
.bpp
= 8;
154 framebuffer
.mode_info
.bytes_per_pixel
= 1;
155 framebuffer
.mode_info
.pitch
= VGA_WIDTH
;
156 framebuffer
.mode_info
.number_of_colors
= 16;
157 framebuffer
.mode_info
.red_mask_size
= 0;
158 framebuffer
.mode_info
.red_field_pos
= 0;
159 framebuffer
.mode_info
.green_mask_size
= 0;
160 framebuffer
.mode_info
.green_field_pos
= 0;
161 framebuffer
.mode_info
.blue_mask_size
= 0;
162 framebuffer
.mode_info
.blue_field_pos
= 0;
163 framebuffer
.mode_info
.reserved_mask_size
= 0;
164 framebuffer
.mode_info
.reserved_field_pos
= 0;
166 framebuffer
.mode_info
.blit_format
167 = grub_video_get_blit_format (&framebuffer
.mode_info
);
169 err
= grub_video_fb_create_render_target_from_pointer (&framebuffer
.render_target
,
170 &framebuffer
.mode_info
,
171 framebuffer
.temporary_buffer
);
175 grub_dprintf ("video", "Couldn't create FB target\n");
180 err
= grub_video_fb_set_active_render_target (framebuffer
.render_target
);
185 err
= grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS
,
186 grub_video_fbstd_colors
);
188 return GRUB_ERR_NONE
;
192 grub_video_vga_fini (void)
196 set_map_mask (saved_map_mask
);
197 grub_vga_set_mode (text_mode
);
200 grub_free (framebuffer
.temporary_buffer
);
201 framebuffer
.temporary_buffer
= 0;
202 return GRUB_ERR_NONE
;
213 for (plane
= 0x01; plane
<= 0x08; plane
<<= 1)
216 volatile grub_uint8_t
*ptr2
;
219 set_map_mask (plane
);
220 for (ptr
= framebuffer
.temporary_buffer
,
221 ptr2
= VGA_MEM
+ PAGE_OFFSET (framebuffer
.back_page
);
222 ptr
< framebuffer
.temporary_buffer
+ VGA_WIDTH
* VGA_HEIGHT
; ptr
++)
224 cbyte
|= (!!(plane
& *ptr
)) << shift
;
237 grub_video_vga_blit_bitmap (struct grub_video_bitmap
*bitmap
,
238 enum grub_video_blit_operators oper
, int x
, int y
,
239 int offset_x
, int offset_y
,
240 unsigned int width
, unsigned int height
)
243 ret
= grub_video_fb_blit_bitmap (bitmap
, oper
, x
, y
, offset_x
, offset_y
,
250 grub_video_vga_blit_render_target (struct grub_video_fbrender_target
*source
,
251 enum grub_video_blit_operators oper
,
252 int x
, int y
, int offset_x
, int offset_y
,
253 unsigned int width
, unsigned int height
)
257 ret
= grub_video_fb_blit_render_target (source
, oper
, x
, y
,
258 offset_x
, offset_y
, width
, height
);
265 grub_video_vga_set_active_render_target (struct grub_video_render_target
*target
)
267 if (target
== GRUB_VIDEO_RENDER_TARGET_DISPLAY
)
270 target
= framebuffer
.render_target
;
275 return grub_video_fb_set_active_render_target (target
);
279 grub_video_vga_get_active_render_target (struct grub_video_render_target
**target
)
282 err
= grub_video_fb_get_active_render_target (target
);
286 if (*target
== framebuffer
.render_target
)
287 *target
= GRUB_VIDEO_RENDER_TARGET_DISPLAY
;
289 return GRUB_ERR_NONE
;
293 grub_video_vga_swap_buffers (void)
295 if (!(framebuffer
.mode_info
.mode_type
& GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
))
296 return GRUB_ERR_NONE
;
298 /* Activate the other page. */
299 framebuffer
.front_page
= !framebuffer
.front_page
;
300 framebuffer
.back_page
= !framebuffer
.back_page
;
302 set_start_address (PAGE_OFFSET (framebuffer
.front_page
));
304 return GRUB_ERR_NONE
;
308 grub_video_vga_set_palette (unsigned int start
__attribute__ ((unused
)),
309 unsigned int count
__attribute__ ((unused
)),
310 struct grub_video_palette_data
*palette_data
__attribute__ ((unused
)))
312 return grub_error (GRUB_ERR_IO
, "can't change palette");
316 grub_video_vga_get_info_and_fini (struct grub_video_mode_info
*mode_info
,
321 grub_memcpy (mode_info
, &(framebuffer
.mode_info
), sizeof (*mode_info
));
323 mode_info
->bytes_per_pixel
= 0;
324 mode_info
->pitch
= VGA_WIDTH
/ 8;
325 mode_info
->number_of_colors
= 1;
327 mode_info
->bg_red
= 0;
328 mode_info
->bg_green
= 0;
329 mode_info
->bg_blue
= 0;
330 mode_info
->bg_alpha
= 255;
332 mode_info
->fg_red
= 255;
333 mode_info
->fg_green
= 255;
334 mode_info
->fg_blue
= 255;
335 mode_info
->fg_alpha
= 255;
337 *framebuf
= VGA_MEM
+ PAGE_OFFSET (framebuffer
.front_page
);
339 grub_video_fb_fini ();
340 grub_free (framebuffer
.temporary_buffer
);
341 framebuffer
.temporary_buffer
= 0;
344 return GRUB_ERR_NONE
;
348 static struct grub_video_adapter grub_video_vga_adapter
=
350 .name
= "VGA Video Driver",
351 .id
= GRUB_VIDEO_DRIVER_VGA
,
353 .prio
= GRUB_VIDEO_ADAPTER_PRIO_FALLBACK
,
355 .init
= grub_video_vga_init
,
356 .fini
= grub_video_vga_fini
,
357 .setup
= grub_video_vga_setup
,
358 .get_info
= grub_video_fb_get_info
,
359 .get_info_and_fini
= grub_video_vga_get_info_and_fini
,
360 .set_palette
= grub_video_vga_set_palette
,
361 .get_palette
= grub_video_fb_get_palette
,
362 .set_viewport
= grub_video_fb_set_viewport
,
363 .get_viewport
= grub_video_fb_get_viewport
,
364 .map_color
= grub_video_fb_map_color
,
365 .map_rgb
= grub_video_fb_map_rgb
,
366 .map_rgba
= grub_video_fb_map_rgba
,
367 .unmap_color
= grub_video_fb_unmap_color
,
368 .fill_rect
= grub_video_fb_fill_rect
,
369 .blit_bitmap
= grub_video_vga_blit_bitmap
,
370 .blit_render_target
= grub_video_vga_blit_render_target
,
371 .scroll
= grub_video_fb_scroll
,
372 .swap_buffers
= grub_video_vga_swap_buffers
,
373 .create_render_target
= grub_video_fb_create_render_target
,
374 .delete_render_target
= grub_video_fb_delete_render_target
,
375 .set_active_render_target
= grub_video_vga_set_active_render_target
,
376 .get_active_render_target
= grub_video_vga_get_active_render_target
,
383 grub_video_register (&grub_video_vga_adapter
);
388 grub_video_unregister (&grub_video_vga_adapter
);