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_graphics_output_protocol_t
*
89 find_gop(efi_guid_t
*proto
, unsigned long size
, void **handles
)
91 efi_graphics_output_protocol_t
*gop
, *first_gop
;
92 efi_graphics_output_protocol_mode_t
*mode
;
93 efi_graphics_output_mode_info_t
*info
= NULL
;
100 for_each_efi_handle(h
, handles
, size
, i
) {
101 efi_guid_t conout_proto
= EFI_CONSOLE_OUT_DEVICE_GUID
;
102 bool conout_found
= false;
105 status
= efi_bs_call(handle_protocol
, h
, proto
, (void **)&gop
);
106 if (status
!= EFI_SUCCESS
)
109 mode
= efi_table_attr(gop
, mode
);
110 info
= efi_table_attr(mode
, info
);
111 if (info
->pixel_format
== PIXEL_BLT_ONLY
)
114 status
= efi_bs_call(handle_protocol
, h
, &conout_proto
, &dummy
);
115 if (status
== EFI_SUCCESS
)
118 if (!first_gop
|| conout_found
) {
120 * Systems that use the UEFI Console Splitter may
121 * provide multiple GOP devices, not all of which are
122 * backed by real hardware. The workaround is to search
123 * for a GOP implementing the ConOut protocol, and if
124 * one isn't found, to just fall back to the first GOP.
126 * Once we've found a GOP supporting ConOut,
127 * don't bother looking any further.
138 static efi_status_t
setup_gop(struct screen_info
*si
, efi_guid_t
*proto
,
139 unsigned long size
, void **handles
)
141 efi_graphics_output_protocol_t
*gop
;
142 efi_graphics_output_protocol_mode_t
*mode
;
143 efi_graphics_output_mode_info_t
*info
= NULL
;
144 efi_physical_addr_t fb_base
;
146 gop
= find_gop(proto
, size
, handles
);
148 /* Did we find any GOPs? */
150 return EFI_NOT_FOUND
;
152 /* EFI framebuffer */
153 mode
= efi_table_attr(gop
, mode
);
154 info
= efi_table_attr(mode
, info
);
156 si
->orig_video_isVGA
= VIDEO_TYPE_EFI
;
158 si
->lfb_width
= info
->horizontal_resolution
;
159 si
->lfb_height
= info
->vertical_resolution
;
161 fb_base
= efi_table_attr(mode
, frame_buffer_base
);
162 si
->lfb_base
= fb_base
;
163 si
->ext_lfb_base
= (u64
)(unsigned long)fb_base
>> 32;
164 if (si
->ext_lfb_base
)
165 si
->capabilities
|= VIDEO_CAPABILITY_64BIT_BASE
;
169 setup_pixel_info(si
, info
->pixels_per_scan_line
,
170 info
->pixel_information
, info
->pixel_format
);
172 si
->lfb_size
= si
->lfb_linelength
* si
->lfb_height
;
174 si
->capabilities
|= VIDEO_CAPABILITY_SKIP_QUIRKS
;
180 * See if we have Graphics Output Protocol
182 efi_status_t
efi_setup_gop(struct screen_info
*si
, efi_guid_t
*proto
,
186 void **gop_handle
= NULL
;
188 status
= efi_bs_call(allocate_pool
, EFI_LOADER_DATA
, size
,
189 (void **)&gop_handle
);
190 if (status
!= EFI_SUCCESS
)
193 status
= efi_bs_call(locate_handle
, EFI_LOCATE_BY_PROTOCOL
, proto
, NULL
,
195 if (status
!= EFI_SUCCESS
)
198 status
= setup_gop(si
, proto
, size
, gop_handle
);
201 efi_bs_call(free_pool
, gop_handle
);