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

« back to all changes in this revision

Viewing changes to video/bochs.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) 2005,2006,2007,2008,2009,2010  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
 
#define grub_video_render_target grub_video_fbrender_target
20
 
 
21
 
#include <grub/err.h>
22
 
#include <grub/types.h>
23
 
#include <grub/dl.h>
24
 
#include <grub/misc.h>
25
 
#include <grub/mm.h>
26
 
#include <grub/video.h>
27
 
#include <grub/video_fb.h>
28
 
#include <grub/pci.h>
29
 
#include <grub/vga.h>
30
 
 
31
 
static struct
32
 
{
33
 
  struct grub_video_mode_info mode_info;
34
 
 
35
 
  grub_uint8_t *ptr;
36
 
  int mapped;
37
 
  grub_uint32_t base;
38
 
  grub_pci_device_t dev;
39
 
} framebuffer;
40
 
 
41
 
#define BOCHS_APERTURE_SIZE 0x800000
42
 
#define BOCHS_MAX_WIDTH 1600
43
 
#define BOCHS_MAX_HEIGHT 1200
44
 
#define BOCHS_WIDTH_ALIGN 8
45
 
 
46
 
enum
47
 
  {
48
 
    BOCHS_VBE_INDEX = 0x1ce,
49
 
    BOCHS_VBE_DATA = 0x1cf,
50
 
  };
51
 
 
52
 
enum
53
 
  {
54
 
    BOCHS_VBE_WIDTH = 1,
55
 
    BOCHS_VBE_HEIGHT = 2,
56
 
    BOCHS_VBE_BPP = 3,
57
 
    BOCHS_VBE_ENABLE = 4,
58
 
    BOCHS_VBE_Y_OFFSET = 9,
59
 
    BOCHS_VBE_MAX
60
 
  };
61
 
 
62
 
static void
63
 
vbe_write (grub_uint16_t val, grub_uint16_t addr)
64
 
{
65
 
  grub_outw (addr, BOCHS_VBE_INDEX);
66
 
  grub_outw (val, BOCHS_VBE_DATA);
67
 
}
68
 
 
69
 
static grub_uint16_t
70
 
vbe_read (grub_uint16_t addr)
71
 
{
72
 
  grub_outw (addr, BOCHS_VBE_INDEX);
73
 
  return grub_inw (BOCHS_VBE_DATA);
74
 
}
75
 
 
76
 
struct saved_state
77
 
{
78
 
  grub_uint8_t cr[256];
79
 
  grub_uint8_t gr[256];
80
 
  grub_uint8_t sr[256];
81
 
  grub_uint8_t r[256];
82
 
  grub_uint8_t g[256];
83
 
  grub_uint8_t b[256];
84
 
  grub_uint8_t vbe[BOCHS_VBE_MAX];
85
 
  int vbe_enable;
86
 
  /* We need to preserve VGA font and VGA text. */
87
 
  grub_uint8_t vram[32 * 4 * 256];
88
 
};
89
 
 
90
 
static struct saved_state initial_state;
91
 
static int state_saved = 0;
92
 
 
93
 
static void
94
 
save_state (struct saved_state *st)
95
 
{
96
 
  unsigned i;
97
 
 
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);
104
 
 
105
 
  for (i = 0; i < 256; i++)
106
 
    grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i);
107
 
 
108
 
  st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1;
109
 
  if (st->vbe_enable)
110
 
    for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
111
 
      st->vbe[i] = vbe_read (i);
112
 
 
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);
116
 
}
117
 
 
118
 
static void
119
 
restore_state (struct saved_state *st)
120
 
{
121
 
  unsigned i;
122
 
 
123
 
  if (st->vbe_enable)
124
 
    for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
125
 
      vbe_write (st->vbe[i], i);
126
 
  else
127
 
    vbe_write (0, BOCHS_VBE_ENABLE);
128
 
 
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);
136
 
 
137
 
  for (i = 0; i < 256; i++)
138
 
    grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]);
139
 
 
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);
143
 
}
144
 
 
145
 
static grub_err_t
146
 
grub_video_bochs_video_init (void)
147
 
{
148
 
  /* Reset frame buffer.  */
149
 
  grub_memset (&framebuffer, 0, sizeof(framebuffer));
150
 
 
151
 
  return grub_video_fb_init ();
152
 
}
153
 
 
154
 
static grub_err_t
155
 
grub_video_bochs_video_fini (void)
156
 
{
157
 
  if (framebuffer.mapped)
158
 
    grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
159
 
                                 BOCHS_APERTURE_SIZE);
160
 
 
161
 
  if (state_saved)
162
 
    {
163
 
      restore_state (&initial_state);
164
 
      state_saved = 0;
165
 
    }
166
 
 
167
 
  return grub_video_fb_fini ();
168
 
}
169
 
 
170
 
static grub_err_t
171
 
doublebuf_pageflipping_set_page (int page)
172
 
{
173
 
  int start = framebuffer.mode_info.height * page;
174
 
 
175
 
  vbe_write (start, BOCHS_VBE_Y_OFFSET);
176
 
  return GRUB_ERR_NONE;
177
 
}
178
 
 
179
 
static grub_err_t
180
 
grub_video_bochs_set_palette (unsigned int start, unsigned int count,
181
 
                               struct grub_video_palette_data *palette_data)
182
 
{
183
 
  if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
184
 
    {
185
 
      unsigned i;
186
 
      if (start >= 0x100)
187
 
        return GRUB_ERR_NONE;
188
 
      if (start + count >= 0x100)
189
 
        count = 0x100 - start;
190
 
 
191
 
      for (i = 0; i < count; i++)
192
 
        grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g,
193
 
                                palette_data[i].b);
194
 
    }
195
 
 
196
 
  /* Then set color to emulated palette.  */
197
 
  return grub_video_fb_set_palette (start, count, palette_data);
198
 
}
199
 
 
200
 
static grub_err_t
201
 
grub_video_bochs_setup (unsigned int width, unsigned int height,
202
 
                        unsigned int mode_type, unsigned int mode_mask)
203
 
{
204
 
  int depth;
205
 
  grub_err_t err;
206
 
  int found = 0;
207
 
  int pitch, bytes_per_pixel;
208
 
  grub_size_t page_size;        /* The size of a page in bytes.  */
209
 
 
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)
212
 
    {
213
 
      grub_pci_address_t addr;
214
 
      grub_uint32_t class;
215
 
 
216
 
      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
217
 
      class = grub_pci_read (addr);
218
 
 
219
 
      if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234)
220
 
        return 0;
221
 
      
222
 
      found = 1;
223
 
 
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;
227
 
 
228
 
      return 1;
229
 
    }
230
 
 
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;
234
 
 
235
 
  if (width == 0 || height == 0)
236
 
    {
237
 
      width = 800;
238
 
      height = 600;
239
 
    }
240
 
 
241
 
  if (width > BOCHS_MAX_WIDTH)
242
 
    return grub_error (GRUB_ERR_IO, "width must be at most",
243
 
                       BOCHS_MAX_WIDTH);
244
 
 
245
 
  if (height > BOCHS_MAX_HEIGHT)
246
 
    return grub_error (GRUB_ERR_IO, "height must be at most",
247
 
                       BOCHS_MAX_HEIGHT);
248
 
 
249
 
  if (width & (BOCHS_WIDTH_ALIGN - 1))
250
 
    return grub_error (GRUB_ERR_IO, "width must be a multiple of %d",
251
 
                       BOCHS_WIDTH_ALIGN);
252
 
 
253
 
  if (depth == 0
254
 
      && !grub_video_check_mode_flag (mode_type, mode_mask,
255
 
                                      GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0))
256
 
    depth = 24;
257
 
 
258
 
  if (depth == 0)
259
 
    depth = 8;
260
 
 
261
 
  if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8
262
 
      && depth != 4)
263
 
    return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bpp are"
264
 
                       " supported by bochs video");
265
 
 
266
 
  if (depth == 4)
267
 
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "4-bpp isn't cupported");
268
 
 
269
 
  bytes_per_pixel = (depth + 7) / 8;
270
 
  if (depth == 4)
271
 
    pitch = width / 2;
272
 
  else
273
 
    pitch = width * bytes_per_pixel;
274
 
 
275
 
  page_size = pitch * height;
276
 
 
277
 
  if (page_size > BOCHS_APERTURE_SIZE)
278
 
    return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode");
279
 
 
280
 
  grub_pci_iterate (find_card);
281
 
  if (!found)
282
 
    return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
283
 
 
284
 
  if (found && framebuffer.base == 0)
285
 
    {
286
 
      /* FIXME: change framebuffer base */
287
 
      return grub_error (GRUB_ERR_IO, "PCI BAR not set");
288
 
    }
289
 
 
290
 
  /* We can safely discard volatile attribute.  */
291
 
  framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev,
292
 
                                                        framebuffer.base,
293
 
                                                        BOCHS_APERTURE_SIZE);
294
 
  framebuffer.mapped = 1;
295
 
 
296
 
  if (!state_saved)
297
 
    {
298
 
      save_state (&initial_state);
299
 
      state_saved = 1;
300
 
    }
301
 
 
302
 
  {
303
 
    vbe_write (0, BOCHS_VBE_ENABLE);
304
 
 
305
 
    vbe_write (width, BOCHS_VBE_WIDTH);
306
 
    vbe_write (height, BOCHS_VBE_HEIGHT);
307
 
    vbe_write (depth, BOCHS_VBE_BPP);
308
 
 
309
 
    vbe_write (1, BOCHS_VBE_ENABLE);
310
 
    doublebuf_pageflipping_set_page (0);
311
 
  }
312
 
 
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;
323
 
 
324
 
  switch (depth)
325
 
    {
326
 
    case 4:
327
 
    case 8:
328
 
      framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
329
 
      break;
330
 
    case 16:
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;
337
 
      break;
338
 
 
339
 
    case 15:
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;
346
 
      break;
347
 
 
348
 
    case 32:
349
 
      framebuffer.mode_info.reserved_mask_size = 8;
350
 
      framebuffer.mode_info.reserved_field_pos = 24;
351
 
 
352
 
    case 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;
359
 
      break;
360
 
    }
361
 
 
362
 
  framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
363
 
 
364
 
  if (BOCHS_APERTURE_SIZE >= 2 * page_size)
365
 
    err = grub_video_fb_setup (mode_type, mode_mask,
366
 
                               &framebuffer.mode_info,
367
 
                               framebuffer.ptr,
368
 
                               doublebuf_pageflipping_set_page,
369
 
                               framebuffer.ptr + page_size);
370
 
  else
371
 
    err = grub_video_fb_setup (mode_type, mode_mask,
372
 
                               &framebuffer.mode_info,
373
 
                               framebuffer.ptr, 0, 0);
374
 
 
375
 
 
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);
379
 
  return err;
380
 
}
381
 
 
382
 
static struct grub_video_adapter grub_video_bochs_adapter =
383
 
  {
384
 
    .name = "Bochs PCI Video Driver",
385
 
    .id = GRUB_VIDEO_DRIVER_BOCHS,
386
 
 
387
 
    .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
388
 
 
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,
411
 
 
412
 
    .next = 0
413
 
  };
414
 
 
415
 
GRUB_MOD_INIT(video_bochs)
416
 
{
417
 
  grub_video_register (&grub_video_bochs_adapter);
418
 
}
419
 
 
420
 
GRUB_MOD_FINI(video_bochs)
421
 
{
422
 
  grub_video_unregister (&grub_video_bochs_adapter);
423
 
}