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/types.h>
24 #include <grub/misc.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>
33 GRUB_MOD_LICENSE ("GPLv3+");
35 static grub_efi_guid_t uga_draw_guid
= GRUB_EFI_UGA_DRAW_GUID
;
36 static struct grub_efi_uga_draw_protocol
*uga
;
37 static grub_uint32_t uga_fb
;
38 static grub_uint32_t uga_pitch
;
42 struct grub_video_mode_info mode_info
;
43 struct grub_video_render_target
*render_target
;
47 #define RGB_MASK 0xffffff
48 #define RGB_MAGIC 0x121314
51 #define FBTEST_STEP (0x10000 >> 2)
52 #define FBTEST_COUNT 8
55 find_line_len (grub_uint32_t
*fb_base
, grub_uint32_t
*line_len
)
57 grub_uint32_t
*base
= (grub_uint32_t
*) (grub_addr_t
) *fb_base
;
60 for (i
= 0; i
< FBTEST_COUNT
; i
++, base
+= FBTEST_STEP
)
62 if ((*base
& RGB_MASK
) == RGB_MAGIC
)
66 for (j
= LINE_MIN
; j
<= LINE_MAX
; j
++)
68 if ((base
[j
] & RGB_MASK
) == RGB_MAGIC
)
70 *fb_base
= (grub_uint32_t
) (grub_addr_t
) base
;
85 find_framebuf (grub_uint32_t
*fb_base
, grub_uint32_t
*line_len
)
89 auto int NESTED_FUNC_ATTR
find_card (grub_pci_device_t dev
,
92 int NESTED_FUNC_ATTR
find_card (grub_pci_device_t dev
,
95 grub_pci_address_t addr
;
97 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CLASS
);
98 if (grub_pci_read (addr
) >> 24 == 0x3)
102 grub_dprintf ("fb", "Display controller: %d:%d.%d\nDevice id: %x\n",
103 grub_pci_get_bus (dev
), grub_pci_get_device (dev
),
104 grub_pci_get_function (dev
), pciid
);
106 for (i
= 0; i
< 6; i
++, addr
+= 4)
108 grub_uint32_t old_bar1
, old_bar2
, type
;
109 grub_uint64_t base64
;
111 old_bar1
= grub_pci_read (addr
);
112 if ((! old_bar1
) || (old_bar1
& GRUB_PCI_ADDR_SPACE_IO
))
115 type
= old_bar1
& GRUB_PCI_ADDR_MEM_TYPE_MASK
;
116 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
121 old_bar2
= grub_pci_read (addr
+ 4);
128 base64
|= (old_bar1
& GRUB_PCI_ADDR_MEM_MASK
);
130 grub_dprintf ("fb", "%s(%d): 0x%llx\n",
131 ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) ?
133 (unsigned long long) base64
);
135 if ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) && (! found
))
138 if (find_line_len (fb_base
, line_len
))
142 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
153 grub_pci_iterate (find_card
);
158 check_protocol (void)
160 grub_efi_uga_draw_protocol_t
*c
;
162 c
= grub_efi_locate_protocol (&uga_draw_guid
, 0);
165 grub_uint32_t width
, height
, depth
, rate
, pixel
;
168 if (efi_call_5 (c
->get_mode
, c
, &width
, &height
, &depth
, &rate
))
171 grub_efi_set_text_mode (0);
173 efi_call_10 (c
->blt
, c
, (struct grub_efi_uga_pixel
*) &pixel
,
174 GRUB_EFI_UGA_VIDEO_FILL
, 0, 0, 0, 0, 1, height
, 0);
175 ret
= find_framebuf (&uga_fb
, &uga_pitch
);
176 grub_efi_set_text_mode (1);
189 grub_video_uga_init (void)
191 grub_memset (&framebuffer
, 0, sizeof(framebuffer
));
192 return grub_video_fb_init ();
196 grub_video_uga_fini (void)
198 return grub_video_fb_fini ();
202 grub_video_uga_setup (unsigned int width
, unsigned int height
,
203 unsigned int mode_type
,
204 unsigned int mode_mask
__attribute__ ((unused
)))
209 depth
= (mode_type
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
)
210 >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS
;
218 if ((! efi_call_5 (uga
->get_mode
, uga
, &w
, &h
, &d
, &r
)) &&
219 ((! width
) || (width
== w
)) &&
220 ((! height
) || (height
== h
)) &&
221 ((! depth
) || (depth
== d
)))
223 framebuffer
.mode_info
.width
= w
;
224 framebuffer
.mode_info
.height
= h
;
225 framebuffer
.mode_info
.pitch
= uga_pitch
;
226 framebuffer
.ptr
= (grub_uint8_t
*) (grub_addr_t
) uga_fb
;
236 framebuffer
.mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_RGB
;
237 framebuffer
.mode_info
.bpp
= 32;
238 framebuffer
.mode_info
.bytes_per_pixel
= 4;
239 framebuffer
.mode_info
.number_of_colors
= 256; /* TODO: fix me. */
240 framebuffer
.mode_info
.red_mask_size
= 8;
241 framebuffer
.mode_info
.red_field_pos
= 16;
242 framebuffer
.mode_info
.green_mask_size
= 8;
243 framebuffer
.mode_info
.green_field_pos
= 8;
244 framebuffer
.mode_info
.blue_mask_size
= 8;
245 framebuffer
.mode_info
.blue_field_pos
= 0;
246 framebuffer
.mode_info
.reserved_mask_size
= 8;
247 framebuffer
.mode_info
.reserved_field_pos
= 24;
249 framebuffer
.mode_info
.blit_format
=
250 grub_video_get_blit_format (&framebuffer
.mode_info
);
252 err
= grub_video_fb_create_render_target_from_pointer
253 (&framebuffer
.render_target
,
254 &framebuffer
.mode_info
,
260 err
= grub_video_fb_set_active_render_target
261 (framebuffer
.render_target
);
266 err
= grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS
,
267 grub_video_fbstd_colors
);
272 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no matching mode found");
276 grub_video_uga_swap_buffers (void)
278 /* TODO: Implement buffer swapping. */
279 return GRUB_ERR_NONE
;
283 grub_video_uga_set_active_render_target (struct grub_video_render_target
*target
)
285 if (target
== GRUB_VIDEO_RENDER_TARGET_DISPLAY
)
286 target
= framebuffer
.render_target
;
288 return grub_video_fb_set_active_render_target (target
);
292 grub_video_uga_get_info_and_fini (struct grub_video_mode_info
*mode_info
,
295 grub_memcpy (mode_info
, &(framebuffer
.mode_info
), sizeof (*mode_info
));
296 *framebuf
= (char *) framebuffer
.ptr
;
298 grub_video_fb_fini ();
300 return GRUB_ERR_NONE
;
303 static struct grub_video_adapter grub_video_uga_adapter
=
305 .name
= "EFI UGA driver",
306 .id
= GRUB_VIDEO_DRIVER_EFI_UGA
,
308 .prio
= GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY
,
310 .init
= grub_video_uga_init
,
311 .fini
= grub_video_uga_fini
,
312 .setup
= grub_video_uga_setup
,
313 .get_info
= grub_video_fb_get_info
,
314 .get_info_and_fini
= grub_video_uga_get_info_and_fini
,
315 .set_palette
= grub_video_fb_set_palette
,
316 .get_palette
= grub_video_fb_get_palette
,
317 .set_viewport
= grub_video_fb_set_viewport
,
318 .get_viewport
= grub_video_fb_get_viewport
,
319 .map_color
= grub_video_fb_map_color
,
320 .map_rgb
= grub_video_fb_map_rgb
,
321 .map_rgba
= grub_video_fb_map_rgba
,
322 .unmap_color
= grub_video_fb_unmap_color
,
323 .fill_rect
= grub_video_fb_fill_rect
,
324 .blit_bitmap
= grub_video_fb_blit_bitmap
,
325 .blit_render_target
= grub_video_fb_blit_render_target
,
326 .scroll
= grub_video_fb_scroll
,
327 .swap_buffers
= grub_video_uga_swap_buffers
,
328 .create_render_target
= grub_video_fb_create_render_target
,
329 .delete_render_target
= grub_video_fb_delete_render_target
,
330 .set_active_render_target
= grub_video_uga_set_active_render_target
,
331 .get_active_render_target
= grub_video_fb_get_active_render_target
,
334 GRUB_MOD_INIT(efi_uga
)
336 if (check_protocol ())
337 grub_video_register (&grub_video_uga_adapter
);
340 GRUB_MOD_FINI(efi_uga
)
343 grub_video_unregister (&grub_video_uga_adapter
);