1 // SPDX-License-Identifier: GPL-2.0
2 /* -----------------------------------------------------------------------
4 * Copyright 2011 Intel Corporation; author Matt Fleming
6 * ----------------------------------------------------------------------- */
8 #include <linux/bitops.h>
10 #include <linux/screen_info.h>
11 #include <linux/string.h>
13 #include <asm/setup.h>
17 enum efi_cmdline_option
{
23 enum efi_cmdline_option option
;
25 } cmdline __efistub_global
= { .option
= EFI_CMDLINE_NONE
};
27 static bool parse_modenum(char *option
, char **next
)
31 if (!strstarts(option
, "mode="))
33 option
+= strlen("mode=");
34 m
= simple_strtoull(option
, &option
, 0);
35 if (*option
&& *option
++ != ',')
37 cmdline
.option
= EFI_CMDLINE_MODE_NUM
;
44 void efi_parse_option_graphics(char *option
)
47 if (parse_modenum(option
, &option
))
50 while (*option
&& *option
++ != ',')
55 static u32
choose_mode_modenum(efi_graphics_output_protocol_t
*gop
)
59 efi_graphics_output_protocol_mode_t
*mode
;
60 efi_graphics_output_mode_info_t
*info
;
61 unsigned long info_size
;
63 u32 max_mode
, cur_mode
;
66 mode
= efi_table_attr(gop
, mode
);
68 cur_mode
= efi_table_attr(mode
, mode
);
69 if (cmdline
.mode
== cur_mode
)
72 max_mode
= efi_table_attr(mode
, max_mode
);
73 if (cmdline
.mode
>= max_mode
) {
74 efi_printk("Requested mode is invalid\n");
78 status
= efi_call_proto(gop
, query_mode
, cmdline
.mode
,
80 if (status
!= EFI_SUCCESS
) {
81 efi_printk("Couldn't get mode information\n");
85 pf
= info
->pixel_format
;
87 efi_bs_call(free_pool
, info
);
89 if (pf
== PIXEL_BLT_ONLY
|| pf
>= PIXEL_FORMAT_MAX
) {
90 efi_printk("Invalid PixelFormat\n");
97 static void set_mode(efi_graphics_output_protocol_t
*gop
)
99 efi_graphics_output_protocol_mode_t
*mode
;
100 u32 cur_mode
, new_mode
;
102 switch (cmdline
.option
) {
103 case EFI_CMDLINE_MODE_NUM
:
104 new_mode
= choose_mode_modenum(gop
);
110 mode
= efi_table_attr(gop
, mode
);
111 cur_mode
= efi_table_attr(mode
, mode
);
113 if (new_mode
== cur_mode
)
116 if (efi_call_proto(gop
, set_mode
, new_mode
) != EFI_SUCCESS
)
117 efi_printk("Failed to set requested mode\n");
120 static void find_bits(u32 mask
, u8
*pos
, u8
*size
)
127 /* UEFI spec guarantees that the set bits are contiguous */
129 *size
= __fls(mask
) - *pos
+ 1;
133 setup_pixel_info(struct screen_info
*si
, u32 pixels_per_scan_line
,
134 efi_pixel_bitmask_t pixel_info
, int pixel_format
)
136 if (pixel_format
== PIXEL_BIT_MASK
) {
137 find_bits(pixel_info
.red_mask
,
138 &si
->red_pos
, &si
->red_size
);
139 find_bits(pixel_info
.green_mask
,
140 &si
->green_pos
, &si
->green_size
);
141 find_bits(pixel_info
.blue_mask
,
142 &si
->blue_pos
, &si
->blue_size
);
143 find_bits(pixel_info
.reserved_mask
,
144 &si
->rsvd_pos
, &si
->rsvd_size
);
145 si
->lfb_depth
= si
->red_size
+ si
->green_size
+
146 si
->blue_size
+ si
->rsvd_size
;
147 si
->lfb_linelength
= (pixels_per_scan_line
* si
->lfb_depth
) / 8;
149 if (pixel_format
== PIXEL_RGB_RESERVED_8BIT_PER_COLOR
) {
152 } else /* PIXEL_BGR_RESERVED_8BIT_PER_COLOR */ {
159 si
->red_size
= si
->green_size
=
160 si
->blue_size
= si
->rsvd_size
= 8;
163 si
->lfb_linelength
= pixels_per_scan_line
* 4;
167 static efi_graphics_output_protocol_t
*
168 find_gop(efi_guid_t
*proto
, unsigned long size
, void **handles
)
170 efi_graphics_output_protocol_t
*first_gop
;
176 for_each_efi_handle(h
, handles
, size
, i
) {
179 efi_graphics_output_protocol_t
*gop
;
180 efi_graphics_output_protocol_mode_t
*mode
;
181 efi_graphics_output_mode_info_t
*info
;
183 efi_guid_t conout_proto
= EFI_CONSOLE_OUT_DEVICE_GUID
;
186 status
= efi_bs_call(handle_protocol
, h
, proto
, (void **)&gop
);
187 if (status
!= EFI_SUCCESS
)
190 mode
= efi_table_attr(gop
, mode
);
191 info
= efi_table_attr(mode
, info
);
192 if (info
->pixel_format
== PIXEL_BLT_ONLY
||
193 info
->pixel_format
>= PIXEL_FORMAT_MAX
)
197 * Systems that use the UEFI Console Splitter may
198 * provide multiple GOP devices, not all of which are
199 * backed by real hardware. The workaround is to search
200 * for a GOP implementing the ConOut protocol, and if
201 * one isn't found, to just fall back to the first GOP.
203 * Once we've found a GOP supporting ConOut,
204 * don't bother looking any further.
206 status
= efi_bs_call(handle_protocol
, h
, &conout_proto
, &dummy
);
207 if (status
== EFI_SUCCESS
)
217 static efi_status_t
setup_gop(struct screen_info
*si
, efi_guid_t
*proto
,
218 unsigned long size
, void **handles
)
220 efi_graphics_output_protocol_t
*gop
;
221 efi_graphics_output_protocol_mode_t
*mode
;
222 efi_graphics_output_mode_info_t
*info
;
223 efi_physical_addr_t fb_base
;
225 gop
= find_gop(proto
, size
, handles
);
227 /* Did we find any GOPs? */
229 return EFI_NOT_FOUND
;
231 /* Change mode if requested */
234 /* EFI framebuffer */
235 mode
= efi_table_attr(gop
, mode
);
236 info
= efi_table_attr(mode
, info
);
238 si
->orig_video_isVGA
= VIDEO_TYPE_EFI
;
240 si
->lfb_width
= info
->horizontal_resolution
;
241 si
->lfb_height
= info
->vertical_resolution
;
243 fb_base
= efi_table_attr(mode
, frame_buffer_base
);
244 si
->lfb_base
= lower_32_bits(fb_base
);
245 si
->ext_lfb_base
= upper_32_bits(fb_base
);
246 if (si
->ext_lfb_base
)
247 si
->capabilities
|= VIDEO_CAPABILITY_64BIT_BASE
;
251 setup_pixel_info(si
, info
->pixels_per_scan_line
,
252 info
->pixel_information
, info
->pixel_format
);
254 si
->lfb_size
= si
->lfb_linelength
* si
->lfb_height
;
256 si
->capabilities
|= VIDEO_CAPABILITY_SKIP_QUIRKS
;
262 * See if we have Graphics Output Protocol
264 efi_status_t
efi_setup_gop(struct screen_info
*si
, efi_guid_t
*proto
,
268 void **gop_handle
= NULL
;
270 status
= efi_bs_call(allocate_pool
, EFI_LOADER_DATA
, size
,
271 (void **)&gop_handle
);
272 if (status
!= EFI_SUCCESS
)
275 status
= efi_bs_call(locate_handle
, EFI_LOCATE_BY_PROTOCOL
, proto
, NULL
,
277 if (status
!= EFI_SUCCESS
)
280 status
= setup_gop(si
, proto
, size
, gop_handle
);
283 efi_bs_call(free_pool
, gop_handle
);