Commit 9a1663bc authored by Arvind Sankar's avatar Arvind Sankar Committed by Ard Biesheuvel
Browse files

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: default avatarArvind Sankar <nivedita@alum.mit.edu>
Link: https://lore.kernel.org/r/20200320020028.1936003-14-nivedita@alum.mit.edu


Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent d9ff0323
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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>
+43 −5
Original line number Diff line number Diff line
@@ -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);
	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;
	}