2
* GRUB -- GRand Unified Bootloader
3
* Copyright (C) 2005,2006,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
22
#include <grub/types.h>
24
#include <grub/misc.h>
26
#include <grub/video.h>
27
#include <grub/video_fb.h>
33
struct grub_video_mode_info mode_info;
38
grub_pci_device_t dev;
41
#define BOCHS_APERTURE_SIZE 0x800000
42
#define BOCHS_MAX_WIDTH 1600
43
#define BOCHS_MAX_HEIGHT 1200
44
#define BOCHS_WIDTH_ALIGN 8
48
BOCHS_VBE_INDEX = 0x1ce,
49
BOCHS_VBE_DATA = 0x1cf,
58
BOCHS_VBE_Y_OFFSET = 9,
63
vbe_write (grub_uint16_t val, grub_uint16_t addr)
65
grub_outw (addr, BOCHS_VBE_INDEX);
66
grub_outw (val, BOCHS_VBE_DATA);
70
vbe_read (grub_uint16_t addr)
72
grub_outw (addr, BOCHS_VBE_INDEX);
73
return grub_inw (BOCHS_VBE_DATA);
84
grub_uint8_t vbe[BOCHS_VBE_MAX];
86
/* We need to preserve VGA font and VGA text. */
87
grub_uint8_t vram[32 * 4 * 256];
90
static struct saved_state initial_state;
91
static int state_saved = 0;
94
save_state (struct saved_state *st)
98
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
99
st->cr[i] = grub_vga_cr_read (i);
100
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
101
st->gr[i] = grub_vga_gr_read (i);
102
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
103
st->sr[i] = grub_vga_sr_read (i);
105
for (i = 0; i < 256; i++)
106
grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i);
108
st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1;
110
for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
111
st->vbe[i] = vbe_read (i);
113
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
114
grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram));
115
grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE);
119
restore_state (struct saved_state *st)
124
for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
125
vbe_write (st->vbe[i], i);
127
vbe_write (0, BOCHS_VBE_ENABLE);
129
grub_vga_cr_write (0, 0x11);
130
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
131
grub_vga_cr_write (st->cr[i], i);
132
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
133
grub_vga_sr_write (st->sr[i], i);
134
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
135
grub_vga_gr_write (st->gr[i], i);
137
for (i = 0; i < 256; i++)
138
grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]);
140
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
141
grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram));
142
grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE);
146
grub_video_bochs_video_init (void)
148
/* Reset frame buffer. */
149
grub_memset (&framebuffer, 0, sizeof(framebuffer));
151
return grub_video_fb_init ();
155
grub_video_bochs_video_fini (void)
157
if (framebuffer.mapped)
158
grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
159
BOCHS_APERTURE_SIZE);
163
restore_state (&initial_state);
167
return grub_video_fb_fini ();
171
doublebuf_pageflipping_set_page (int page)
173
int start = framebuffer.mode_info.height * page;
175
vbe_write (start, BOCHS_VBE_Y_OFFSET);
176
return GRUB_ERR_NONE;
180
grub_video_bochs_set_palette (unsigned int start, unsigned int count,
181
struct grub_video_palette_data *palette_data)
183
if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
187
return GRUB_ERR_NONE;
188
if (start + count >= 0x100)
189
count = 0x100 - start;
191
for (i = 0; i < count; i++)
192
grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g,
196
/* Then set color to emulated palette. */
197
return grub_video_fb_set_palette (start, count, palette_data);
201
grub_video_bochs_setup (unsigned int width, unsigned int height,
202
unsigned int mode_type, unsigned int mode_mask)
207
int pitch, bytes_per_pixel;
208
grub_size_t page_size; /* The size of a page in bytes. */
210
auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)));
211
int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid)
213
grub_pci_address_t addr;
216
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
217
class = grub_pci_read (addr);
219
if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234)
224
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
225
framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
226
framebuffer.dev = dev;
231
/* Decode depth from mode_type. If it is zero, then autodetect. */
232
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
233
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
235
if (width == 0 || height == 0)
241
if (width > BOCHS_MAX_WIDTH)
242
return grub_error (GRUB_ERR_IO, "width must be at most",
245
if (height > BOCHS_MAX_HEIGHT)
246
return grub_error (GRUB_ERR_IO, "height must be at most",
249
if (width & (BOCHS_WIDTH_ALIGN - 1))
250
return grub_error (GRUB_ERR_IO, "width must be a multiple of %d",
254
&& !grub_video_check_mode_flag (mode_type, mode_mask,
255
GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0))
261
if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8
263
return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bpp are"
264
" supported by bochs video");
267
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "4-bpp isn't cupported");
269
bytes_per_pixel = (depth + 7) / 8;
273
pitch = width * bytes_per_pixel;
275
page_size = pitch * height;
277
if (page_size > BOCHS_APERTURE_SIZE)
278
return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode");
280
grub_pci_iterate (find_card);
282
return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
284
if (found && framebuffer.base == 0)
286
/* FIXME: change framebuffer base */
287
return grub_error (GRUB_ERR_IO, "PCI BAR not set");
290
/* We can safely discard volatile attribute. */
291
framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev,
293
BOCHS_APERTURE_SIZE);
294
framebuffer.mapped = 1;
298
save_state (&initial_state);
303
vbe_write (0, BOCHS_VBE_ENABLE);
305
vbe_write (width, BOCHS_VBE_WIDTH);
306
vbe_write (height, BOCHS_VBE_HEIGHT);
307
vbe_write (depth, BOCHS_VBE_BPP);
309
vbe_write (1, BOCHS_VBE_ENABLE);
310
doublebuf_pageflipping_set_page (0);
313
/* Fill mode info details. */
314
framebuffer.mode_info.width = width;
315
framebuffer.mode_info.height = height;
316
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
317
framebuffer.mode_info.bpp = depth;
318
framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel;
319
framebuffer.mode_info.pitch = pitch;
320
framebuffer.mode_info.number_of_colors = 256;
321
framebuffer.mode_info.reserved_mask_size = 0;
322
framebuffer.mode_info.reserved_field_pos = 0;
328
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
331
framebuffer.mode_info.red_mask_size = 5;
332
framebuffer.mode_info.red_field_pos = 11;
333
framebuffer.mode_info.green_mask_size = 6;
334
framebuffer.mode_info.green_field_pos = 5;
335
framebuffer.mode_info.blue_mask_size = 5;
336
framebuffer.mode_info.blue_field_pos = 0;
340
framebuffer.mode_info.red_mask_size = 5;
341
framebuffer.mode_info.red_field_pos = 10;
342
framebuffer.mode_info.green_mask_size = 5;
343
framebuffer.mode_info.green_field_pos = 5;
344
framebuffer.mode_info.blue_mask_size = 5;
345
framebuffer.mode_info.blue_field_pos = 0;
349
framebuffer.mode_info.reserved_mask_size = 8;
350
framebuffer.mode_info.reserved_field_pos = 24;
353
framebuffer.mode_info.red_mask_size = 8;
354
framebuffer.mode_info.red_field_pos = 16;
355
framebuffer.mode_info.green_mask_size = 8;
356
framebuffer.mode_info.green_field_pos = 8;
357
framebuffer.mode_info.blue_mask_size = 8;
358
framebuffer.mode_info.blue_field_pos = 0;
362
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
364
if (BOCHS_APERTURE_SIZE >= 2 * page_size)
365
err = grub_video_fb_setup (mode_type, mode_mask,
366
&framebuffer.mode_info,
368
doublebuf_pageflipping_set_page,
369
framebuffer.ptr + page_size);
371
err = grub_video_fb_setup (mode_type, mode_mask,
372
&framebuffer.mode_info,
373
framebuffer.ptr, 0, 0);
376
/* Copy default palette to initialize emulated palette. */
377
err = grub_video_bochs_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
378
grub_video_fbstd_colors);
382
static struct grub_video_adapter grub_video_bochs_adapter =
384
.name = "Bochs PCI Video Driver",
385
.id = GRUB_VIDEO_DRIVER_BOCHS,
387
.prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
389
.init = grub_video_bochs_video_init,
390
.fini = grub_video_bochs_video_fini,
391
.setup = grub_video_bochs_setup,
392
.get_info = grub_video_fb_get_info,
393
.get_info_and_fini = grub_video_fb_get_info_and_fini,
394
.set_palette = grub_video_bochs_set_palette,
395
.get_palette = grub_video_fb_get_palette,
396
.set_viewport = grub_video_fb_set_viewport,
397
.get_viewport = grub_video_fb_get_viewport,
398
.map_color = grub_video_fb_map_color,
399
.map_rgb = grub_video_fb_map_rgb,
400
.map_rgba = grub_video_fb_map_rgba,
401
.unmap_color = grub_video_fb_unmap_color,
402
.fill_rect = grub_video_fb_fill_rect,
403
.blit_bitmap = grub_video_fb_blit_bitmap,
404
.blit_render_target = grub_video_fb_blit_render_target,
405
.scroll = grub_video_fb_scroll,
406
.swap_buffers = grub_video_fb_swap_buffers,
407
.create_render_target = grub_video_fb_create_render_target,
408
.delete_render_target = grub_video_fb_delete_render_target,
409
.set_active_render_target = grub_video_fb_set_active_render_target,
410
.get_active_render_target = grub_video_fb_get_active_render_target,
415
GRUB_MOD_INIT(video_bochs)
417
grub_video_register (&grub_video_bochs_adapter);
420
GRUB_MOD_FINI(video_bochs)
422
grub_video_unregister (&grub_video_bochs_adapter);