Skip to content

Commit 45d97a7

Browse files
nivedita76ardbiesheuvel
authored andcommitted
efi/gop: Allow automatically choosing the best mode
Add the ability to automatically pick the highest resolution video mode (defined as the product of vertical and horizontal resolution) by using a command-line argument of the form video=efifb:auto If there are multiple modes with the highest resolution, pick one with the highest color depth. Signed-off-by: Arvind Sankar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 9a1663b commit 45d97a7

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

Documentation/fb/efifb.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,10 @@ mode=n
5757
"rgb" or "bgr" to match specifically those pixel formats, or a number
5858
for a mode with matching bits per pixel.
5959

60+
auto
61+
The EFI stub will choose the mode with the highest resolution (product
62+
of horizontal and vertical resolution). If there are multiple modes
63+
with the highest resolution, it will choose one with the highest color
64+
depth.
65+
6066
Edgar Hucek <[email protected]>

drivers/firmware/efi/libstub/gop.c

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
enum efi_cmdline_option {
1919
EFI_CMDLINE_NONE,
2020
EFI_CMDLINE_MODE_NUM,
21-
EFI_CMDLINE_RES
21+
EFI_CMDLINE_RES,
22+
EFI_CMDLINE_AUTO
2223
};
2324

2425
static struct {
@@ -86,13 +87,28 @@ static bool parse_res(char *option, char **next)
8687
return true;
8788
}
8889

90+
static bool parse_auto(char *option, char **next)
91+
{
92+
if (!strstarts(option, "auto"))
93+
return false;
94+
option += strlen("auto");
95+
if (*option && *option++ != ',')
96+
return false;
97+
cmdline.option = EFI_CMDLINE_AUTO;
98+
99+
*next = option;
100+
return true;
101+
}
102+
89103
void efi_parse_option_graphics(char *option)
90104
{
91105
while (*option) {
92106
if (parse_modenum(option, &option))
93107
continue;
94108
if (parse_res(option, &option))
95109
continue;
110+
if (parse_auto(option, &option))
111+
continue;
96112

97113
while (*option && *option++ != ',')
98114
;
@@ -211,6 +227,69 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
211227
return cur_mode;
212228
}
213229

230+
static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
231+
{
232+
efi_status_t status;
233+
234+
efi_graphics_output_protocol_mode_t *mode;
235+
efi_graphics_output_mode_info_t *info;
236+
unsigned long info_size;
237+
238+
u32 max_mode, cur_mode, best_mode, area;
239+
u8 depth;
240+
int pf;
241+
efi_pixel_bitmask_t pi;
242+
u32 m, w, h, a;
243+
u8 d;
244+
245+
mode = efi_table_attr(gop, mode);
246+
247+
cur_mode = efi_table_attr(mode, mode);
248+
max_mode = efi_table_attr(mode, max_mode);
249+
250+
info = efi_table_attr(mode, info);
251+
252+
pf = info->pixel_format;
253+
pi = info->pixel_information;
254+
w = info->horizontal_resolution;
255+
h = info->vertical_resolution;
256+
257+
best_mode = cur_mode;
258+
area = w * h;
259+
depth = pixel_bpp(pf, pi);
260+
261+
for (m = 0; m < max_mode; m++) {
262+
if (m == cur_mode)
263+
continue;
264+
265+
status = efi_call_proto(gop, query_mode, m,
266+
&info_size, &info);
267+
if (status != EFI_SUCCESS)
268+
continue;
269+
270+
pf = info->pixel_format;
271+
pi = info->pixel_information;
272+
w = info->horizontal_resolution;
273+
h = info->vertical_resolution;
274+
275+
efi_bs_call(free_pool, info);
276+
277+
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
278+
continue;
279+
a = w * h;
280+
if (a < area)
281+
continue;
282+
d = pixel_bpp(pf, pi);
283+
if (a > area || d > depth) {
284+
best_mode = m;
285+
area = a;
286+
depth = d;
287+
}
288+
}
289+
290+
return best_mode;
291+
}
292+
214293
static void set_mode(efi_graphics_output_protocol_t *gop)
215294
{
216295
efi_graphics_output_protocol_mode_t *mode;
@@ -223,6 +302,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
223302
case EFI_CMDLINE_RES:
224303
new_mode = choose_mode_res(gop);
225304
break;
305+
case EFI_CMDLINE_AUTO:
306+
new_mode = choose_mode_auto(gop);
307+
break;
226308
default:
227309
return;
228310
}

0 commit comments

Comments
 (0)