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
;
84 /* Context for find_framebuf. */
85 struct find_framebuf_ctx
87 grub_uint32_t
*fb_base
;
88 grub_uint32_t
*line_len
;
92 /* Helper for find_framebuf. */
94 find_card (grub_pci_device_t dev
, grub_pci_id_t pciid
, void *data
)
96 struct find_framebuf_ctx
*ctx
= data
;
97 grub_pci_address_t addr
;
99 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CLASS
);
100 if (grub_pci_read (addr
) >> 24 == 0x3)
104 grub_dprintf ("fb", "Display controller: %d:%d.%d\nDevice id: %x\n",
105 grub_pci_get_bus (dev
), grub_pci_get_device (dev
),
106 grub_pci_get_function (dev
), pciid
);
108 for (i
= 0; i
< 6; i
++, addr
+= 4)
110 grub_uint32_t old_bar1
, old_bar2
, type
;
111 grub_uint64_t base64
;
113 old_bar1
= grub_pci_read (addr
);
114 if ((! old_bar1
) || (old_bar1
& GRUB_PCI_ADDR_SPACE_IO
))
117 type
= old_bar1
& GRUB_PCI_ADDR_MEM_TYPE_MASK
;
118 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
123 old_bar2
= grub_pci_read (addr
+ 4);
130 base64
|= (old_bar1
& GRUB_PCI_ADDR_MEM_MASK
);
132 grub_dprintf ("fb", "%s(%d): 0x%llx\n",
133 ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) ?
135 (unsigned long long) base64
);
137 if ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) && (! ctx
->found
))
139 *ctx
->fb_base
= base64
;
140 if (find_line_len (ctx
->fb_base
, ctx
->line_len
))
144 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
156 find_framebuf (grub_uint32_t
*fb_base
, grub_uint32_t
*line_len
)
158 struct find_framebuf_ctx ctx
= {
160 .line_len
= line_len
,
164 grub_pci_iterate (find_card
, &ctx
);
169 check_protocol (void)
171 grub_efi_uga_draw_protocol_t
*c
;
173 c
= grub_efi_locate_protocol (&uga_draw_guid
, 0);
176 grub_uint32_t width
, height
, depth
, rate
, pixel
;
179 if (efi_call_5 (c
->get_mode
, c
, &width
, &height
, &depth
, &rate
))
182 grub_efi_set_text_mode (0);
184 efi_call_10 (c
->blt
, c
, (struct grub_efi_uga_pixel
*) &pixel
,
185 GRUB_EFI_UGA_VIDEO_FILL
, 0, 0, 0, 0, 1, height
, 0);
186 ret
= find_framebuf (&uga_fb
, &uga_pitch
);
187 grub_efi_set_text_mode (1);
200 grub_video_uga_init (void)
202 grub_memset (&framebuffer
, 0, sizeof(framebuffer
));
203 return grub_video_fb_init ();
207 grub_video_uga_fini (void)
209 return grub_video_fb_fini ();
213 grub_video_uga_setup (unsigned int width
, unsigned int height
,
214 unsigned int mode_type
,
215 unsigned int mode_mask
__attribute__ ((unused
)))
220 depth
= (mode_type
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
)
221 >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS
;
229 if ((! efi_call_5 (uga
->get_mode
, uga
, &w
, &h
, &d
, &r
)) &&
230 ((! width
) || (width
== w
)) &&
231 ((! height
) || (height
== h
)) &&
232 ((! depth
) || (depth
== d
)))
234 framebuffer
.mode_info
.width
= w
;
235 framebuffer
.mode_info
.height
= h
;
236 framebuffer
.mode_info
.pitch
= uga_pitch
;
237 framebuffer
.ptr
= (grub_uint8_t
*) (grub_addr_t
) uga_fb
;
247 framebuffer
.mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_RGB
;
248 framebuffer
.mode_info
.bpp
= 32;
249 framebuffer
.mode_info
.bytes_per_pixel
= 4;
250 framebuffer
.mode_info
.number_of_colors
= 256;
251 framebuffer
.mode_info
.red_mask_size
= 8;
252 framebuffer
.mode_info
.red_field_pos
= 16;
253 framebuffer
.mode_info
.green_mask_size
= 8;
254 framebuffer
.mode_info
.green_field_pos
= 8;
255 framebuffer
.mode_info
.blue_mask_size
= 8;
256 framebuffer
.mode_info
.blue_field_pos
= 0;
257 framebuffer
.mode_info
.reserved_mask_size
= 8;
258 framebuffer
.mode_info
.reserved_field_pos
= 24;
260 framebuffer
.mode_info
.blit_format
=
261 grub_video_get_blit_format (&framebuffer
.mode_info
);
263 err
= grub_video_fb_create_render_target_from_pointer
264 (&framebuffer
.render_target
,
265 &framebuffer
.mode_info
,
271 err
= grub_video_fb_set_active_render_target
272 (framebuffer
.render_target
);
277 err
= grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS
,
278 grub_video_fbstd_colors
);
283 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no matching mode found");
287 grub_video_uga_swap_buffers (void)
289 /* TODO: Implement buffer swapping. */
290 return GRUB_ERR_NONE
;
294 grub_video_uga_set_active_render_target (struct grub_video_render_target
*target
)
296 if (target
== GRUB_VIDEO_RENDER_TARGET_DISPLAY
)
297 target
= framebuffer
.render_target
;
299 return grub_video_fb_set_active_render_target (target
);
303 grub_video_uga_get_info_and_fini (struct grub_video_mode_info
*mode_info
,
306 grub_memcpy (mode_info
, &(framebuffer
.mode_info
), sizeof (*mode_info
));
307 *framebuf
= (char *) framebuffer
.ptr
;
309 grub_video_fb_fini ();
311 return GRUB_ERR_NONE
;
314 static struct grub_video_adapter grub_video_uga_adapter
=
316 .name
= "EFI UGA driver",
317 .id
= GRUB_VIDEO_DRIVER_EFI_UGA
,
319 .prio
= GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY
,
321 .init
= grub_video_uga_init
,
322 .fini
= grub_video_uga_fini
,
323 .setup
= grub_video_uga_setup
,
324 .get_info
= grub_video_fb_get_info
,
325 .get_info_and_fini
= grub_video_uga_get_info_and_fini
,
326 .set_palette
= grub_video_fb_set_palette
,
327 .get_palette
= grub_video_fb_get_palette
,
328 .set_viewport
= grub_video_fb_set_viewport
,
329 .get_viewport
= grub_video_fb_get_viewport
,
330 .set_region
= grub_video_fb_set_region
,
331 .get_region
= grub_video_fb_get_region
,
332 .set_area_status
= grub_video_fb_set_area_status
,
333 .get_area_status
= grub_video_fb_get_area_status
,
334 .map_color
= grub_video_fb_map_color
,
335 .map_rgb
= grub_video_fb_map_rgb
,
336 .map_rgba
= grub_video_fb_map_rgba
,
337 .unmap_color
= grub_video_fb_unmap_color
,
338 .fill_rect
= grub_video_fb_fill_rect
,
339 .blit_bitmap
= grub_video_fb_blit_bitmap
,
340 .blit_render_target
= grub_video_fb_blit_render_target
,
341 .scroll
= grub_video_fb_scroll
,
342 .swap_buffers
= grub_video_uga_swap_buffers
,
343 .create_render_target
= grub_video_fb_create_render_target
,
344 .delete_render_target
= grub_video_fb_delete_render_target
,
345 .set_active_render_target
= grub_video_uga_set_active_render_target
,
346 .get_active_render_target
= grub_video_fb_get_active_render_target
,
349 GRUB_MOD_INIT(efi_uga
)
351 if (check_protocol ())
352 grub_video_register (&grub_video_uga_adapter
);
355 GRUB_MOD_FINI(efi_uga
)
358 grub_video_unregister (&grub_video_uga_adapter
);