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

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

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200518190716.751506-20-nivedita@alum.mit.edu
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
Arvind Sankar
2020-05-18 15:07:11 -04:00
committed by Ard Biesheuvel
parent 9b47c52756
commit 14c574f35c
5 changed files with 139 additions and 1 deletions

View File

@@ -19,7 +19,8 @@ enum efi_cmdline_option {
EFI_CMDLINE_NONE,
EFI_CMDLINE_MODE_NUM,
EFI_CMDLINE_RES,
EFI_CMDLINE_AUTO
EFI_CMDLINE_AUTO,
EFI_CMDLINE_LIST
};
static struct {
@@ -100,6 +101,19 @@ static bool parse_auto(char *option, char **next)
return true;
}
static bool parse_list(char *option, char **next)
{
if (!strstarts(option, "list"))
return false;
option += strlen("list");
if (*option && *option++ != ',')
return false;
cmdline.option = EFI_CMDLINE_LIST;
*next = option;
return true;
}
void efi_parse_option_graphics(char *option)
{
while (*option) {
@@ -109,6 +123,8 @@ void efi_parse_option_graphics(char *option)
continue;
if (parse_auto(option, &option))
continue;
if (parse_list(option, &option))
continue;
while (*option && *option++ != ',')
;
@@ -290,6 +306,82 @@ static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
return best_mode;
}
static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
{
efi_status_t status;
efi_graphics_output_protocol_mode_t *mode;
efi_graphics_output_mode_info_t *info;
unsigned long info_size;
u32 max_mode, cur_mode;
int pf;
efi_pixel_bitmask_t pi;
u32 m, w, h;
u8 d;
const char *dstr;
bool valid;
efi_input_key_t key;
mode = efi_table_attr(gop, mode);
cur_mode = efi_table_attr(mode, mode);
max_mode = efi_table_attr(mode, max_mode);
efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
efi_puts(" * = current mode\n"
" - = unusable mode\n");
for (m = 0; m < max_mode; m++) {
status = efi_call_proto(gop, query_mode, m,
&info_size, &info);
if (status != EFI_SUCCESS)
continue;
pf = info->pixel_format;
pi = info->pixel_information;
w = info->horizontal_resolution;
h = info->vertical_resolution;
efi_bs_call(free_pool, info);
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
d = 0;
switch (pf) {
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
dstr = "rgb";
break;
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
dstr = "bgr";
break;
case PIXEL_BIT_MASK:
dstr = "";
d = pixel_bpp(pf, pi);
break;
case PIXEL_BLT_ONLY:
dstr = "blt";
break;
default:
dstr = "xxx";
break;
}
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
m,
m == cur_mode ? '*' : ' ',
!valid ? '-' : ' ',
w, h, dstr, d);
}
efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
if (status != EFI_SUCCESS && status != EFI_TIMEOUT) {
efi_err("Unable to read key, continuing in 10 seconds\n");
efi_bs_call(stall, 10 * EFI_USEC_PER_SEC);
}
return cur_mode;
}
static void set_mode(efi_graphics_output_protocol_t *gop)
{
efi_graphics_output_protocol_mode_t *mode;
@@ -305,6 +397,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
case EFI_CMDLINE_AUTO:
new_mode = choose_mode_auto(gop);
break;
case EFI_CMDLINE_LIST:
new_mode = choose_mode_list(gop);
break;
default:
return;
}