efi/gop: Allow specifying depth as well as resolution

Extend the video mode argument to handle an optional color depth
specification of the form
	video=efifb:<xres>x<yres>[-(rgb|bgr|<bpp>)]

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200320020028.1936003-14-nivedita@alum.mit.edu
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
Arvind Sankar 2020-03-19 22:00:27 -04:00 коммит произвёл Ard Biesheuvel
Родитель d9ff0323d0
Коммит 9a1663bc4d
2 изменённых файлов: 48 добавлений и 8 удалений

Просмотреть файл

@ -50,9 +50,11 @@ mode=n
The EFI stub will set the mode of the display to mode number n if
possible.
<xres>x<yres>
<xres>x<yres>[-(rgb|bgr|<bpp>)]
The EFI stub will search for a display mode that matches the specified
horizontal and vertical resolution, and set the mode of the display to
it if one is found.
horizontal and vertical resolution, and optionally bit depth, and set
the mode of the display to it if one is found. The bit depth can either
"rgb" or "bgr" to match specifically those pixel formats, or a number
for a mode with matching bits per pixel.
Edgar Hucek <gimli@dark-green.com>

Просмотреть файл

@ -27,6 +27,8 @@ static struct {
u32 mode;
struct {
u32 width, height;
int format;
u8 depth;
} res;
};
} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
@ -50,7 +52,8 @@ static bool parse_modenum(char *option, char **next)
static bool parse_res(char *option, char **next)
{
u32 w, h;
u32 w, h, d = 0;
int pf = -1;
if (!isdigit(*option))
return false;
@ -58,11 +61,26 @@ static bool parse_res(char *option, char **next)
if (*option++ != 'x' || !isdigit(*option))
return false;
h = simple_strtoull(option, &option, 10);
if (*option == '-') {
option++;
if (strstarts(option, "rgb")) {
option += strlen("rgb");
pf = PIXEL_RGB_RESERVED_8BIT_PER_COLOR;
} else if (strstarts(option, "bgr")) {
option += strlen("bgr");
pf = PIXEL_BGR_RESERVED_8BIT_PER_COLOR;
} else if (isdigit(*option))
d = simple_strtoull(option, &option, 10);
else
return false;
}
if (*option && *option++ != ',')
return false;
cmdline.option = EFI_CMDLINE_RES;
cmdline.res.width = w;
cmdline.res.height = h;
cmdline.res.format = pf;
cmdline.res.depth = d;
*next = option;
return true;
@ -123,6 +141,18 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
return cmdline.mode;
}
static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
{
if (pixel_format == PIXEL_BIT_MASK) {
u32 mask = pixel_info.red_mask | pixel_info.green_mask |
pixel_info.blue_mask | pixel_info.reserved_mask;
if (!mask)
return 0;
return __fls(mask) - __ffs(mask) + 1;
} else
return 32;
}
static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
{
efi_status_t status;
@ -133,16 +163,21 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
u32 max_mode, cur_mode;
int pf;
efi_pixel_bitmask_t pi;
u32 m, w, h;
mode = efi_table_attr(gop, mode);
cur_mode = efi_table_attr(mode, mode);
info = efi_table_attr(mode, info);
w = info->horizontal_resolution;
h = info->vertical_resolution;
pf = info->pixel_format;
pi = info->pixel_information;
w = info->horizontal_resolution;
h = info->vertical_resolution;
if (w == cmdline.res.width && h == cmdline.res.height)
if (w == cmdline.res.width && h == cmdline.res.height &&
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
return cur_mode;
max_mode = efi_table_attr(mode, max_mode);
@ -157,6 +192,7 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
continue;
pf = info->pixel_format;
pi = info->pixel_information;
w = info->horizontal_resolution;
h = info->vertical_resolution;
@ -164,7 +200,9 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
continue;
if (w == cmdline.res.width && h == cmdline.res.height)
if (w == cmdline.res.width && h == cmdline.res.height &&
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
return m;
}