1 /* -----------------------------------------------------------------------
3 * Copyright 2011 Intel Corporation; author Matt Fleming
5 * This file is part of the Linux kernel, and is made available under
6 * the terms of the GNU General Public License version 2.
8 * ----------------------------------------------------------------------- */
10 #include <linux/efi.h>
11 #include <linux/screen_info.h>
13 #include <asm/setup.h>
15 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
23 while (!(mask & 0x1)) {
39 setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
40 struct efi_pixel_bitmask pixel_info, int pixel_format)
42 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
44 si->lfb_linelength = pixels_per_scan_line * 4;
53 } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
55 si->lfb_linelength = pixels_per_scan_line * 4;
64 } else if (pixel_format == PIXEL_BIT_MASK) {
65 find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
66 find_bits(pixel_info.green_mask, &si->green_pos,
68 find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
69 find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
71 si->lfb_depth = si->red_size + si->green_size +
72 si->blue_size + si->rsvd_size;
73 si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
76 si->lfb_linelength = si->lfb_width / 2;
89 __gop_query32(efi_system_table_t *sys_table_arg,
90 struct efi_graphics_output_protocol_32 *gop32,
91 struct efi_graphics_output_mode_info **info,
92 unsigned long *size, u64 *fb_base)
94 struct efi_graphics_output_protocol_mode_32 *mode;
95 efi_graphics_output_protocol_query_mode query_mode;
100 mode = (struct efi_graphics_output_protocol_mode_32 *)m;
101 query_mode = (void *)(unsigned long)gop32->query_mode;
103 status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
105 if (status != EFI_SUCCESS)
108 *fb_base = mode->frame_buffer_base;
113 setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
114 efi_guid_t *proto, unsigned long size, void **gop_handle)
116 struct efi_graphics_output_protocol_32 *gop32, *first_gop;
117 unsigned long nr_gops;
119 u32 pixels_per_scan_line;
122 struct efi_pixel_bitmask pixel_info;
124 efi_status_t status = EFI_NOT_FOUND;
125 u32 *handles = (u32 *)(unsigned long)gop_handle;
131 nr_gops = size / sizeof(u32);
132 for (i = 0; i < nr_gops; i++) {
133 struct efi_graphics_output_mode_info *info = NULL;
134 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
135 bool conout_found = false;
137 efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
140 status = efi_call_early(handle_protocol, h,
141 proto, (void **)&gop32);
142 if (status != EFI_SUCCESS)
145 status = efi_call_early(handle_protocol, h,
146 &conout_proto, &dummy);
147 if (status == EFI_SUCCESS)
150 status = __gop_query32(sys_table_arg, gop32, &info, &size,
152 if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
153 info->pixel_format != PIXEL_BLT_ONLY) {
155 * Systems that use the UEFI Console Splitter may
156 * provide multiple GOP devices, not all of which are
157 * backed by real hardware. The workaround is to search
158 * for a GOP implementing the ConOut protocol, and if
159 * one isn't found, to just fall back to the first GOP.
161 width = info->horizontal_resolution;
162 height = info->vertical_resolution;
163 pixel_format = info->pixel_format;
164 pixel_info = info->pixel_information;
165 pixels_per_scan_line = info->pixels_per_scan_line;
166 fb_base = current_fb_base;
169 * Once we've found a GOP supporting ConOut,
170 * don't bother looking any further.
178 /* Did we find any GOPs? */
182 /* EFI framebuffer */
183 si->orig_video_isVGA = VIDEO_TYPE_EFI;
185 si->lfb_width = width;
186 si->lfb_height = height;
187 si->lfb_base = fb_base;
189 ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
191 si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
192 si->ext_lfb_base = ext_lfb_base;
197 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
199 si->lfb_size = si->lfb_linelength * si->lfb_height;
201 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
207 __gop_query64(efi_system_table_t *sys_table_arg,
208 struct efi_graphics_output_protocol_64 *gop64,
209 struct efi_graphics_output_mode_info **info,
210 unsigned long *size, u64 *fb_base)
212 struct efi_graphics_output_protocol_mode_64 *mode;
213 efi_graphics_output_protocol_query_mode query_mode;
218 mode = (struct efi_graphics_output_protocol_mode_64 *)m;
219 query_mode = (void *)(unsigned long)gop64->query_mode;
221 status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
223 if (status != EFI_SUCCESS)
226 *fb_base = mode->frame_buffer_base;
231 setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
232 efi_guid_t *proto, unsigned long size, void **gop_handle)
234 struct efi_graphics_output_protocol_64 *gop64, *first_gop;
235 unsigned long nr_gops;
237 u32 pixels_per_scan_line;
240 struct efi_pixel_bitmask pixel_info;
242 efi_status_t status = EFI_NOT_FOUND;
243 u64 *handles = (u64 *)(unsigned long)gop_handle;
249 nr_gops = size / sizeof(u64);
250 for (i = 0; i < nr_gops; i++) {
251 struct efi_graphics_output_mode_info *info = NULL;
252 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
253 bool conout_found = false;
255 efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
258 status = efi_call_early(handle_protocol, h,
259 proto, (void **)&gop64);
260 if (status != EFI_SUCCESS)
263 status = efi_call_early(handle_protocol, h,
264 &conout_proto, &dummy);
265 if (status == EFI_SUCCESS)
268 status = __gop_query64(sys_table_arg, gop64, &info, &size,
270 if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
271 info->pixel_format != PIXEL_BLT_ONLY) {
273 * Systems that use the UEFI Console Splitter may
274 * provide multiple GOP devices, not all of which are
275 * backed by real hardware. The workaround is to search
276 * for a GOP implementing the ConOut protocol, and if
277 * one isn't found, to just fall back to the first GOP.
279 width = info->horizontal_resolution;
280 height = info->vertical_resolution;
281 pixel_format = info->pixel_format;
282 pixel_info = info->pixel_information;
283 pixels_per_scan_line = info->pixels_per_scan_line;
284 fb_base = current_fb_base;
287 * Once we've found a GOP supporting ConOut,
288 * don't bother looking any further.
296 /* Did we find any GOPs? */
300 /* EFI framebuffer */
301 si->orig_video_isVGA = VIDEO_TYPE_EFI;
303 si->lfb_width = width;
304 si->lfb_height = height;
305 si->lfb_base = fb_base;
307 ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
309 si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
310 si->ext_lfb_base = ext_lfb_base;
315 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
317 si->lfb_size = si->lfb_linelength * si->lfb_height;
319 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
325 * See if we have Graphics Output Protocol
327 efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
328 struct screen_info *si, efi_guid_t *proto,
332 void **gop_handle = NULL;
334 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
335 size, (void **)&gop_handle);
336 if (status != EFI_SUCCESS)
339 status = efi_call_early(locate_handle,
340 EFI_LOCATE_BY_PROTOCOL,
341 proto, NULL, &size, gop_handle);
342 if (status != EFI_SUCCESS)
345 if (efi_is_64bit()) {
346 status = setup_gop64(sys_table_arg, si, proto, size,
349 status = setup_gop32(sys_table_arg, si, proto, size,
354 efi_call_early(free_pool, gop_handle);