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>
13 static void find_bits(unsigned long mask
, u8
*pos
, u8
*size
)
21 while (!(mask
& 0x1)) {
37 setup_pixel_info(struct screen_info
*si
, u32 pixels_per_scan_line
,
38 struct efi_pixel_bitmask pixel_info
, int pixel_format
)
40 if (pixel_format
== PIXEL_RGB_RESERVED_8BIT_PER_COLOR
) {
42 si
->lfb_linelength
= pixels_per_scan_line
* 4;
51 } else if (pixel_format
== PIXEL_BGR_RESERVED_8BIT_PER_COLOR
) {
53 si
->lfb_linelength
= pixels_per_scan_line
* 4;
62 } else if (pixel_format
== PIXEL_BIT_MASK
) {
63 find_bits(pixel_info
.red_mask
, &si
->red_pos
, &si
->red_size
);
64 find_bits(pixel_info
.green_mask
, &si
->green_pos
,
66 find_bits(pixel_info
.blue_mask
, &si
->blue_pos
, &si
->blue_size
);
67 find_bits(pixel_info
.reserved_mask
, &si
->rsvd_pos
,
69 si
->lfb_depth
= si
->red_size
+ si
->green_size
+
70 si
->blue_size
+ si
->rsvd_size
;
71 si
->lfb_linelength
= (pixels_per_scan_line
* si
->lfb_depth
) / 8;
74 si
->lfb_linelength
= si
->lfb_width
/ 2;
87 __gop_query32(efi_system_table_t
*sys_table_arg
,
88 struct efi_graphics_output_protocol_32
*gop32
,
89 struct efi_graphics_output_mode_info
**info
,
90 unsigned long *size
, u64
*fb_base
)
92 struct efi_graphics_output_protocol_mode_32
*mode
;
93 efi_graphics_output_protocol_query_mode query_mode
;
98 mode
= (struct efi_graphics_output_protocol_mode_32
*)m
;
99 query_mode
= (void *)(unsigned long)gop32
->query_mode
;
101 status
= __efi_call_early(query_mode
, (void *)gop32
, mode
->mode
, size
,
103 if (status
!= EFI_SUCCESS
)
106 *fb_base
= mode
->frame_buffer_base
;
111 setup_gop32(efi_system_table_t
*sys_table_arg
, struct screen_info
*si
,
112 efi_guid_t
*proto
, unsigned long size
, void **gop_handle
)
114 struct efi_graphics_output_protocol_32
*gop32
, *first_gop
;
115 unsigned long nr_gops
;
117 u32 pixels_per_scan_line
;
120 struct efi_pixel_bitmask pixel_info
;
122 efi_status_t status
= EFI_NOT_FOUND
;
123 u32
*handles
= (u32
*)(unsigned long)gop_handle
;
129 nr_gops
= size
/ sizeof(u32
);
130 for (i
= 0; i
< nr_gops
; i
++) {
131 struct efi_graphics_output_mode_info
*info
= NULL
;
132 efi_guid_t conout_proto
= EFI_CONSOLE_OUT_DEVICE_GUID
;
133 bool conout_found
= false;
135 efi_handle_t h
= (efi_handle_t
)(unsigned long)handles
[i
];
138 status
= efi_call_early(handle_protocol
, h
,
139 proto
, (void **)&gop32
);
140 if (status
!= EFI_SUCCESS
)
143 status
= efi_call_early(handle_protocol
, h
,
144 &conout_proto
, &dummy
);
145 if (status
== EFI_SUCCESS
)
148 status
= __gop_query32(sys_table_arg
, gop32
, &info
, &size
,
150 if (status
== EFI_SUCCESS
&& (!first_gop
|| conout_found
) &&
151 info
->pixel_format
!= PIXEL_BLT_ONLY
) {
153 * Systems that use the UEFI Console Splitter may
154 * provide multiple GOP devices, not all of which are
155 * backed by real hardware. The workaround is to search
156 * for a GOP implementing the ConOut protocol, and if
157 * one isn't found, to just fall back to the first GOP.
159 width
= info
->horizontal_resolution
;
160 height
= info
->vertical_resolution
;
161 pixel_format
= info
->pixel_format
;
162 pixel_info
= info
->pixel_information
;
163 pixels_per_scan_line
= info
->pixels_per_scan_line
;
164 fb_base
= current_fb_base
;
167 * Once we've found a GOP supporting ConOut,
168 * don't bother looking any further.
176 /* Did we find any GOPs? */
180 /* EFI framebuffer */
181 si
->orig_video_isVGA
= VIDEO_TYPE_EFI
;
183 si
->lfb_width
= width
;
184 si
->lfb_height
= height
;
185 si
->lfb_base
= fb_base
;
187 ext_lfb_base
= (u64
)(unsigned long)fb_base
>> 32;
189 si
->capabilities
|= VIDEO_CAPABILITY_64BIT_BASE
;
190 si
->ext_lfb_base
= ext_lfb_base
;
195 setup_pixel_info(si
, pixels_per_scan_line
, pixel_info
, pixel_format
);
197 si
->lfb_size
= si
->lfb_linelength
* si
->lfb_height
;
199 si
->capabilities
|= VIDEO_CAPABILITY_SKIP_QUIRKS
;
205 __gop_query64(efi_system_table_t
*sys_table_arg
,
206 struct efi_graphics_output_protocol_64
*gop64
,
207 struct efi_graphics_output_mode_info
**info
,
208 unsigned long *size
, u64
*fb_base
)
210 struct efi_graphics_output_protocol_mode_64
*mode
;
211 efi_graphics_output_protocol_query_mode query_mode
;
216 mode
= (struct efi_graphics_output_protocol_mode_64
*)m
;
217 query_mode
= (void *)(unsigned long)gop64
->query_mode
;
219 status
= __efi_call_early(query_mode
, (void *)gop64
, mode
->mode
, size
,
221 if (status
!= EFI_SUCCESS
)
224 *fb_base
= mode
->frame_buffer_base
;
229 setup_gop64(efi_system_table_t
*sys_table_arg
, struct screen_info
*si
,
230 efi_guid_t
*proto
, unsigned long size
, void **gop_handle
)
232 struct efi_graphics_output_protocol_64
*gop64
, *first_gop
;
233 unsigned long nr_gops
;
235 u32 pixels_per_scan_line
;
238 struct efi_pixel_bitmask pixel_info
;
240 efi_status_t status
= EFI_NOT_FOUND
;
241 u64
*handles
= (u64
*)(unsigned long)gop_handle
;
247 nr_gops
= size
/ sizeof(u64
);
248 for (i
= 0; i
< nr_gops
; i
++) {
249 struct efi_graphics_output_mode_info
*info
= NULL
;
250 efi_guid_t conout_proto
= EFI_CONSOLE_OUT_DEVICE_GUID
;
251 bool conout_found
= false;
253 efi_handle_t h
= (efi_handle_t
)(unsigned long)handles
[i
];
256 status
= efi_call_early(handle_protocol
, h
,
257 proto
, (void **)&gop64
);
258 if (status
!= EFI_SUCCESS
)
261 status
= efi_call_early(handle_protocol
, h
,
262 &conout_proto
, &dummy
);
263 if (status
== EFI_SUCCESS
)
266 status
= __gop_query64(sys_table_arg
, gop64
, &info
, &size
,
268 if (status
== EFI_SUCCESS
&& (!first_gop
|| conout_found
) &&
269 info
->pixel_format
!= PIXEL_BLT_ONLY
) {
271 * Systems that use the UEFI Console Splitter may
272 * provide multiple GOP devices, not all of which are
273 * backed by real hardware. The workaround is to search
274 * for a GOP implementing the ConOut protocol, and if
275 * one isn't found, to just fall back to the first GOP.
277 width
= info
->horizontal_resolution
;
278 height
= info
->vertical_resolution
;
279 pixel_format
= info
->pixel_format
;
280 pixel_info
= info
->pixel_information
;
281 pixels_per_scan_line
= info
->pixels_per_scan_line
;
282 fb_base
= current_fb_base
;
285 * Once we've found a GOP supporting ConOut,
286 * don't bother looking any further.
294 /* Did we find any GOPs? */
298 /* EFI framebuffer */
299 si
->orig_video_isVGA
= VIDEO_TYPE_EFI
;
301 si
->lfb_width
= width
;
302 si
->lfb_height
= height
;
303 si
->lfb_base
= fb_base
;
305 ext_lfb_base
= (u64
)(unsigned long)fb_base
>> 32;
307 si
->capabilities
|= VIDEO_CAPABILITY_64BIT_BASE
;
308 si
->ext_lfb_base
= ext_lfb_base
;
313 setup_pixel_info(si
, pixels_per_scan_line
, pixel_info
, pixel_format
);
315 si
->lfb_size
= si
->lfb_linelength
* si
->lfb_height
;
317 si
->capabilities
|= VIDEO_CAPABILITY_SKIP_QUIRKS
;
323 * See if we have Graphics Output Protocol
325 efi_status_t
efi_setup_gop(efi_system_table_t
*sys_table_arg
,
326 struct screen_info
*si
, efi_guid_t
*proto
,
330 void **gop_handle
= NULL
;
332 status
= efi_call_early(allocate_pool
, EFI_LOADER_DATA
,
333 size
, (void **)&gop_handle
);
334 if (status
!= EFI_SUCCESS
)
337 status
= efi_call_early(locate_handle
,
338 EFI_LOCATE_BY_PROTOCOL
,
339 proto
, NULL
, &size
, gop_handle
);
340 if (status
!= EFI_SUCCESS
)
343 if (efi_is_64bit()) {
344 status
= setup_gop64(sys_table_arg
, si
, proto
, size
,
347 status
= setup_gop32(sys_table_arg
, si
, proto
, size
,
352 efi_call_early(free_pool
, gop_handle
);