History

efi/gop: Add an option to list out the available GOP modes

Add video=efifb:list option to list the modes that are available.

Arvind Sankar committed 6 years ago

Commit 14c574f1 parent 9b47c525 files · +139 −1Browse files

Unified · Split

5 files
  1. Documentation/fb/efifb.rst +5 −0
  2. drivers/firmware/efi/libstub/efi-stub-helper.c +35 −0
  3. drivers/firmware/efi/libstub/efistub.h +2 −0
  4. drivers/firmware/efi/libstub/gop.c +96 −1
  5. include/linux/efi.h +1 −0
Documentation/fb/efifb.rst+5−0
@@ -63,4 +63,9 @@ auto · 62 unmodified lines
6363 with the highest resolution, it will choose one with the highest color
6464 depth.
6565
66+list
67+ The EFI stub will list out all the display modes that are available. A
68+ specific mode can then be chosen using one of the above options for the
69+ next boot.
70+
6671 Edgar Hucek <gimli@dark-green.com>
drivers/firmware/efi/libstub/efi-stub-helper.c+35−0
@@ -463,3 +463,38 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image, · 462 unmodified lines
463463
464464 return status;
465465 }
466+
467+efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
468+{
469+ efi_event_t events[2], timer;
470+ unsigned long index;
471+ efi_simple_text_input_protocol_t *con_in;
472+ efi_status_t status;
473+
474+ con_in = efi_table_attr(efi_system_table, con_in);
475+ if (!con_in)
476+ return EFI_UNSUPPORTED;
477+ efi_set_event_at(events, 0, efi_table_attr(con_in, wait_for_key));
478+
479+ status = efi_bs_call(create_event, EFI_EVT_TIMER, 0, NULL, NULL, &timer);
480+ if (status != EFI_SUCCESS)
481+ return status;
482+
483+ status = efi_bs_call(set_timer, timer, EfiTimerRelative,
484+ EFI_100NSEC_PER_USEC * usec);
485+ if (status != EFI_SUCCESS)
486+ return status;
487+ efi_set_event_at(events, 1, timer);
488+
489+ status = efi_bs_call(wait_for_event, 2, events, &index);
490+ if (status == EFI_SUCCESS) {
491+ if (index == 0)
492+ status = efi_call_proto(con_in, read_keystroke, key);
493+ else
494+ status = EFI_TIMEOUT;
495+ }
496+
497+ efi_bs_call(close_event, timer);
498+
499+ return status;
500+}
drivers/firmware/efi/libstub/efistub.h+2−0
@@ -323,6 +323,8 @@ union efi_simple_text_input_protocol { · 322 unmodified lines
323323 } mixed_mode;
324324 };
325325
326+efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key);
327+
326328 union efi_simple_text_output_protocol {
327329 struct {
328330 void *reset;
drivers/firmware/efi/libstub/gop.c+96−1
@@ -19,7 +19,8 @@ enum efi_cmdline_option { · 18 unmodified lines
1919 EFI_CMDLINE_NONE,
2020 EFI_CMDLINE_MODE_NUM,
2121 EFI_CMDLINE_RES,
22− EFI_CMDLINE_AUTO
22+ EFI_CMDLINE_AUTO,
23+ EFI_CMDLINE_LIST
2324 };
2425
2526 static struct {
@@ -100,6 +101,19 @@ static bool parse_auto(char *option, char **next) · 74 unmodified lines
100101 return true;
101102 }
102103
104+static bool parse_list(char *option, char **next)
105+{
106+ if (!strstarts(option, "list"))
107+ return false;
108+ option += strlen("list");
109+ if (*option && *option++ != ',')
110+ return false;
111+ cmdline.option = EFI_CMDLINE_LIST;
112+
113+ *next = option;
114+ return true;
115+}
116+
103117 void efi_parse_option_graphics(char *option)
104118 {
105119 while (*option) {
@@ -109,6 +123,8 @@ void efi_parse_option_graphics(char *option) · 3 unmodified lines
109123 continue;
110124 if (parse_auto(option, &option))
111125 continue;
126+ if (parse_list(option, &option))
127+ continue;
112128
113129 while (*option && *option++ != ',')
114130 ;
@@ -290,6 +306,82 @@ static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop) · 175 unmodified lines
290306 return best_mode;
291307 }
292308
309+static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
310+{
311+ efi_status_t status;
312+
313+ efi_graphics_output_protocol_mode_t *mode;
314+ efi_graphics_output_mode_info_t *info;
315+ unsigned long info_size;
316+
317+ u32 max_mode, cur_mode;
318+ int pf;
319+ efi_pixel_bitmask_t pi;
320+ u32 m, w, h;
321+ u8 d;
322+ const char *dstr;
323+ bool valid;
324+ efi_input_key_t key;
325+
326+ mode = efi_table_attr(gop, mode);
327+
328+ cur_mode = efi_table_attr(mode, mode);
329+ max_mode = efi_table_attr(mode, max_mode);
330+
331+ efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
332+ efi_puts(" * = current mode\n"
333+ " - = unusable mode\n");
334+ for (m = 0; m < max_mode; m++) {
335+ status = efi_call_proto(gop, query_mode, m,
336+ &info_size, &info);
337+ if (status != EFI_SUCCESS)
338+ continue;
339+
340+ pf = info->pixel_format;
341+ pi = info->pixel_information;
342+ w = info->horizontal_resolution;
343+ h = info->vertical_resolution;
344+
345+ efi_bs_call(free_pool, info);
346+
347+ valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
348+ d = 0;
349+ switch (pf) {
350+ case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
351+ dstr = "rgb";
352+ break;
353+ case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
354+ dstr = "bgr";
355+ break;
356+ case PIXEL_BIT_MASK:
357+ dstr = "";
358+ d = pixel_bpp(pf, pi);
359+ break;
360+ case PIXEL_BLT_ONLY:
361+ dstr = "blt";
362+ break;
363+ default:
364+ dstr = "xxx";
365+ break;
366+ }
367+
368+ efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
369+ m,
370+ m == cur_mode ? '*' : ' ',
371+ !valid ? '-' : ' ',
372+ w, h, dstr, d);
373+ }
374+
375+ efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
376+ status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
377+ if (status != EFI_SUCCESS && status != EFI_TIMEOUT) {
378+ efi_err("Unable to read key, continuing in 10 seconds\n");
379+ efi_bs_call(stall, 10 * EFI_USEC_PER_SEC);
380+ }
381+
382+ return cur_mode;
383+}
384+
293385 static void set_mode(efi_graphics_output_protocol_t *gop)
294386 {
295387 efi_graphics_output_protocol_mode_t *mode;
@@ -305,6 +397,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop) · 9 unmodified lines
305397 case EFI_CMDLINE_AUTO:
306398 new_mode = choose_mode_auto(gop);
307399 break;
400+ case EFI_CMDLINE_LIST:
401+ new_mode = choose_mode_list(gop);
402+ break;
308403 default:
309404 return;
310405 }
include/linux/efi.h+1−0
@@ -39,6 +39,7 @@ · 38 unmodified lines
3939 #define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
4040 #define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
4141 #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
42+#define EFI_TIMEOUT (18 | (1UL << (BITS_PER_LONG-1)))
4243 #define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1)))
4344 #define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
4445