1 // SPDX-License-Identifier: GPL-2.0
2 /* -----------------------------------------------------------------------
4 * Copyright 2011 Intel Corporation; author Matt Fleming
6 * ----------------------------------------------------------------------- */
9 #include <linux/screen_info.h>
11 #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 efi_pixel_bitmask_t 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;
88 static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
89 unsigned long size, void **handles)
91 efi_graphics_output_protocol_t *gop, *first_gop;
93 u32 pixels_per_scan_line;
95 efi_physical_addr_t fb_base;
96 efi_pixel_bitmask_t pixel_info;
105 for_each_efi_handle(h, handles, size, i) {
106 efi_graphics_output_protocol_mode_t *mode;
107 efi_graphics_output_mode_info_t *info = NULL;
108 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
109 bool conout_found = false;
112 status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
113 if (status != EFI_SUCCESS)
116 status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
117 if (status == EFI_SUCCESS)
120 mode = efi_table_attr(gop, mode);
121 info = efi_table_attr(mode, info);
123 if ((!first_gop || conout_found) &&
124 info->pixel_format != PIXEL_BLT_ONLY) {
126 * Systems that use the UEFI Console Splitter may
127 * provide multiple GOP devices, not all of which are
128 * backed by real hardware. The workaround is to search
129 * for a GOP implementing the ConOut protocol, and if
130 * one isn't found, to just fall back to the first GOP.
132 width = info->horizontal_resolution;
133 height = info->vertical_resolution;
134 pixel_format = info->pixel_format;
135 pixel_info = info->pixel_information;
136 pixels_per_scan_line = info->pixels_per_scan_line;
137 fb_base = efi_table_attr(mode, frame_buffer_base);
140 * Once we've found a GOP supporting ConOut,
141 * don't bother looking any further.
149 /* Did we find any GOPs? */
151 return EFI_NOT_FOUND;
153 /* EFI framebuffer */
154 si->orig_video_isVGA = VIDEO_TYPE_EFI;
156 si->lfb_width = width;
157 si->lfb_height = height;
158 si->lfb_base = fb_base;
160 ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
162 si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
163 si->ext_lfb_base = ext_lfb_base;
168 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
170 si->lfb_size = si->lfb_linelength * si->lfb_height;
172 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
178 * See if we have Graphics Output Protocol
180 efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
184 void **gop_handle = NULL;
186 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
187 (void **)&gop_handle);
188 if (status != EFI_SUCCESS)
191 status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL,
193 if (status != EFI_SUCCESS)
196 status = setup_gop(si, proto, size, gop_handle);
199 efi_bs_call(free_pool, gop_handle);