~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/video/efi_uga.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

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  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/efi/api.h>
 
29
#include <grub/efi/efi.h>
 
30
#include <grub/efi/uga_draw.h>
 
31
#include <grub/pci.h>
 
32
 
 
33
static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
 
34
static struct grub_efi_uga_draw_protocol *uga;
 
35
static grub_uint32_t uga_fb;
 
36
static grub_uint32_t uga_pitch;
 
37
 
 
38
static struct
 
39
{
 
40
  struct grub_video_mode_info mode_info;
 
41
  struct grub_video_render_target *render_target;
 
42
  grub_uint8_t *ptr;
 
43
} framebuffer;
 
44
 
 
45
#define RGB_MASK        0xffffff
 
46
#define RGB_MAGIC       0x121314
 
47
#define LINE_MIN        800
 
48
#define LINE_MAX        4096
 
49
#define FBTEST_STEP     (0x10000 >> 2)
 
50
#define FBTEST_COUNT    8
 
51
 
 
52
static int
 
53
find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
 
54
{
 
55
  grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base;
 
56
  int i;
 
57
 
 
58
  for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP)
 
59
    {
 
60
      if ((*base & RGB_MASK) == RGB_MAGIC)
 
61
        {
 
62
          int j;
 
63
 
 
64
          for (j = LINE_MIN; j <= LINE_MAX; j++)
 
65
            {
 
66
              if ((base[j] & RGB_MASK) == RGB_MAGIC)
 
67
                {
 
68
                  *fb_base = (grub_uint32_t) (grub_target_addr_t) base;
 
69
                  *line_len = j << 2;
 
70
 
 
71
                  return 1;
 
72
                }
 
73
            }
 
74
 
 
75
          break;
 
76
        }
 
77
    }
 
78
 
 
79
  return 0;
 
80
}
 
81
 
 
82
static int
 
83
find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
 
84
{
 
85
  int found = 0;
 
86
 
 
87
  auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev,
 
88
                                       grub_pci_id_t pciid);
 
89
 
 
90
  int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev,
 
91
                                  grub_pci_id_t pciid)
 
92
    {
 
93
      grub_pci_address_t addr;
 
94
 
 
95
      addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
 
96
      if (grub_pci_read (addr) >> 24 == 0x3)
 
97
        {
 
98
          int i;
 
99
 
 
100
          grub_dprintf ("fb", "Display controller: %d:%d.%d\nDevice id: %x\n",
 
101
                        grub_pci_get_bus (dev), grub_pci_get_device (dev),
 
102
                        grub_pci_get_function (dev), pciid);
 
103
          addr += 8;
 
104
          for (i = 0; i < 6; i++, addr += 4)
 
105
            {
 
106
              grub_uint32_t old_bar1, old_bar2, type;
 
107
              grub_uint64_t base64;
 
108
 
 
109
              old_bar1 = grub_pci_read (addr);
 
110
              if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO))
 
111
                continue;
 
112
 
 
113
              type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK;
 
114
              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
 
115
                {
 
116
                  if (i == 5)
 
117
                    break;
 
118
 
 
119
                  old_bar2 = grub_pci_read (addr + 4);
 
120
                }
 
121
              else
 
122
                old_bar2 = 0;
 
123
 
 
124
              base64 = old_bar2;
 
125
              base64 <<= 32;
 
126
              base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
 
127
 
 
128
              grub_dprintf ("fb", "%s(%d): 0x%llx\n",
 
129
                            ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
 
130
                            "VMEM" : "MMIO"), i,
 
131
                           (unsigned long long) base64);
 
132
 
 
133
              if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found))
 
134
                {
 
135
                  *fb_base = base64;
 
136
                  if (find_line_len (fb_base, line_len))
 
137
                    found++;
 
138
                }
 
139
 
 
140
              if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
 
141
                {
 
142
                  i++;
 
143
                  addr += 4;
 
144
                }
 
145
            }
 
146
        }
 
147
 
 
148
      return found;
 
149
    }
 
150
 
 
151
  grub_pci_iterate (find_card);
 
152
  return found;
 
153
}
 
154
 
 
155
static int
 
156
check_protocol (void)
 
157
{
 
158
  grub_efi_uga_draw_protocol_t *c;
 
159
 
 
160
  c = grub_efi_locate_protocol (&uga_draw_guid, 0);
 
161
  if (c)
 
162
    {
 
163
      grub_uint32_t width, height, depth, rate, pixel;
 
164
      int ret;
 
165
 
 
166
      if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
 
167
        return 0;
 
168
 
 
169
      grub_efi_set_text_mode (0);
 
170
      pixel = RGB_MAGIC;
 
171
      efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
 
172
                   GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
 
173
      ret = find_framebuf (&uga_fb, &uga_pitch);
 
174
      grub_efi_set_text_mode (1);
 
175
 
 
176
      if (ret)
 
177
        {
 
178
          uga = c;
 
179
          return 1;
 
180
        }
 
181
    }
 
182
 
 
183
  return 0;
 
184
}
 
185
 
 
186
static grub_err_t
 
187
grub_video_uga_init (void)
 
188
{
 
189
  grub_memset (&framebuffer, 0, sizeof(framebuffer));
 
190
  return grub_video_fb_init ();
 
191
}
 
192
 
 
193
static grub_err_t
 
194
grub_video_uga_fini (void)
 
195
{
 
196
  return grub_video_fb_fini ();
 
197
}
 
198
 
 
199
static grub_err_t
 
200
grub_video_uga_setup (unsigned int width, unsigned int height,
 
201
                      unsigned int mode_type,
 
202
                      unsigned int mode_mask __attribute__ ((unused)))
 
203
{
 
204
  unsigned int depth;
 
205
  int found = 0;
 
206
 
 
207
  depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
 
208
    >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
 
209
 
 
210
  {
 
211
    grub_uint32_t w;
 
212
    grub_uint32_t h;
 
213
    grub_uint32_t d;
 
214
    grub_uint32_t r;
 
215
 
 
216
    if ((! efi_call_5 (uga->get_mode, uga, &w, &h, &d, &r)) &&
 
217
        ((! width) || (width == w)) &&
 
218
        ((! height) || (height == h)) &&
 
219
        ((! depth) || (depth == d)))
 
220
      {
 
221
        framebuffer.mode_info.width = w;
 
222
        framebuffer.mode_info.height = h;
 
223
        framebuffer.mode_info.pitch = uga_pitch;
 
224
        framebuffer.ptr = (grub_uint8_t *) (grub_target_addr_t) uga_fb;
 
225
 
 
226
        found = 1;
 
227
      }
 
228
  }
 
229
 
 
230
  if (found)
 
231
    {
 
232
      grub_err_t err;
 
233
 
 
234
      framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
 
235
      framebuffer.mode_info.bpp = 32;
 
236
      framebuffer.mode_info.bytes_per_pixel = 4;
 
237
      framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me.  */
 
238
      framebuffer.mode_info.red_mask_size = 8;
 
239
      framebuffer.mode_info.red_field_pos = 16;
 
240
      framebuffer.mode_info.green_mask_size = 8;
 
241
      framebuffer.mode_info.green_field_pos = 8;
 
242
      framebuffer.mode_info.blue_mask_size = 8;
 
243
      framebuffer.mode_info.blue_field_pos = 0;
 
244
      framebuffer.mode_info.reserved_mask_size = 8;
 
245
      framebuffer.mode_info.reserved_field_pos = 24;
 
246
 
 
247
      framebuffer.mode_info.blit_format =
 
248
        grub_video_get_blit_format (&framebuffer.mode_info);
 
249
 
 
250
      err = grub_video_fb_create_render_target_from_pointer
 
251
        (&framebuffer.render_target,
 
252
         &framebuffer.mode_info,
 
253
         framebuffer.ptr);
 
254
 
 
255
      if (err)
 
256
        return err;
 
257
 
 
258
      err = grub_video_fb_set_active_render_target
 
259
        (framebuffer.render_target);
 
260
 
 
261
      if (err)
 
262
        return err;
 
263
 
 
264
      err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
 
265
                                       grub_video_fbstd_colors);
 
266
 
 
267
      return err;
 
268
    }
 
269
 
 
270
  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
 
271
}
 
272
 
 
273
static grub_err_t
 
274
grub_video_uga_swap_buffers (void)
 
275
{
 
276
  /* TODO: Implement buffer swapping.  */
 
277
  return GRUB_ERR_NONE;
 
278
}
 
279
 
 
280
static grub_err_t
 
281
grub_video_uga_set_active_render_target (struct grub_video_render_target *target)
 
282
{
 
283
  if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
 
284
    target = framebuffer.render_target;
 
285
 
 
286
  return grub_video_fb_set_active_render_target (target);
 
287
}
 
288
 
 
289
static grub_err_t
 
290
grub_video_uga_get_info_and_fini (struct grub_video_mode_info *mode_info,
 
291
                                  void **framebuf)
 
292
{
 
293
  grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
 
294
  *framebuf = (char *) framebuffer.ptr;
 
295
 
 
296
  grub_video_fb_fini ();
 
297
 
 
298
  return GRUB_ERR_NONE;
 
299
}
 
300
 
 
301
static struct grub_video_adapter grub_video_uga_adapter =
 
302
  {
 
303
    .name = "EFI UGA driver",
 
304
    .id = GRUB_VIDEO_DRIVER_EFI_UGA,
 
305
 
 
306
    .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY,
 
307
 
 
308
    .init = grub_video_uga_init,
 
309
    .fini = grub_video_uga_fini,
 
310
    .setup = grub_video_uga_setup,
 
311
    .get_info = grub_video_fb_get_info,
 
312
    .get_info_and_fini = grub_video_uga_get_info_and_fini,
 
313
    .set_palette = grub_video_fb_set_palette,
 
314
    .get_palette = grub_video_fb_get_palette,
 
315
    .set_viewport = grub_video_fb_set_viewport,
 
316
    .get_viewport = grub_video_fb_get_viewport,
 
317
    .map_color = grub_video_fb_map_color,
 
318
    .map_rgb = grub_video_fb_map_rgb,
 
319
    .map_rgba = grub_video_fb_map_rgba,
 
320
    .unmap_color = grub_video_fb_unmap_color,
 
321
    .fill_rect = grub_video_fb_fill_rect,
 
322
    .blit_bitmap = grub_video_fb_blit_bitmap,
 
323
    .blit_render_target = grub_video_fb_blit_render_target,
 
324
    .scroll = grub_video_fb_scroll,
 
325
    .swap_buffers = grub_video_uga_swap_buffers,
 
326
    .create_render_target = grub_video_fb_create_render_target,
 
327
    .delete_render_target = grub_video_fb_delete_render_target,
 
328
    .set_active_render_target = grub_video_uga_set_active_render_target,
 
329
    .get_active_render_target = grub_video_fb_get_active_render_target,
 
330
  };
 
331
 
 
332
GRUB_MOD_INIT(efi_uga)
 
333
{
 
334
  if (check_protocol ())
 
335
    grub_video_register (&grub_video_uga_adapter);
 
336
}
 
337
 
 
338
GRUB_MOD_FINI(efi_uga)
 
339
{
 
340
  if (uga)
 
341
    grub_video_unregister (&grub_video_uga_adapter);
 
342
}