All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arvind Sankar <nivedita@alum.mit.edu>
To: Ard Biesheuvel <ardb@kernel.org>
Cc: Hans de Goede <hdegoede@redhat.com>,
	linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 11/14] efi/gop: Allow specifying mode number on command line
Date: Thu, 19 Mar 2020 22:00:25 -0400	[thread overview]
Message-ID: <20200320020028.1936003-12-nivedita@alum.mit.edu> (raw)
In-Reply-To: <20200319192855.29876-1-nivedita@alum.mit.edu>

Add the ability to choose a video mode for the selected gop by using a
command-line argument of the form
	video=efifb:mode=<n>

Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu>
---
 Documentation/fb/efifb.rst                    |  20 +++-
 .../firmware/efi/libstub/efi-stub-helper.c    |   3 +
 drivers/firmware/efi/libstub/efistub.h        |   2 +
 drivers/firmware/efi/libstub/gop.c            | 107 ++++++++++++++++++
 4 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/Documentation/fb/efifb.rst b/Documentation/fb/efifb.rst
index 04840331a00e..367fbda2f4da 100644
--- a/Documentation/fb/efifb.rst
+++ b/Documentation/fb/efifb.rst
@@ -2,8 +2,10 @@
 What is efifb?
 ==============
 
-This is a generic EFI platform driver for Intel based Apple computers.
-efifb is only for EFI booted Intel Macs.
+This is a generic EFI platform driver for systems with UEFI firmware. The
+system must be booted via the EFI stub for this to be usable. efifb supports
+both firmware with Graphics Output Protocol (GOP) displays as well as older
+systems with only Universal Graphics Adapter (UGA) displays.
 
 Supported Hardware
 ==================
@@ -12,11 +14,14 @@ Supported Hardware
 - Macbook
 - Macbook Pro 15"/17"
 - MacMini
+- ARM/ARM64/X86 systems with UEFI firmware
 
 How to use it?
 ==============
 
-efifb does not have any kind of autodetection of your machine.
+For UGA displays, efifb does not have any kind of autodetection of your
+machine.
+
 You have to add the following kernel parameters in your elilo.conf::
 
 	Macbook :
@@ -28,6 +33,9 @@ You have to add the following kernel parameters in your elilo.conf::
 	Macbook Pro 17", iMac 20" :
 		video=efifb:i20
 
+For GOP displays, efifb can autodetect the display's resolution and framebuffer
+address, so these should work out of the box without any special parameters.
+
 Accepted options:
 
 ======= ===========================================================
@@ -36,4 +44,10 @@ nowc	Don't map the framebuffer write combined. This can be used
 	when large amounts of console data are written.
 ======= ===========================================================
 
+Options for GOP displays:
+
+mode=n
+        The EFI stub will set the mode of the display to mode number n if
+        possible.
+
 Edgar Hucek <gimli@dark-green.com>
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 9f34c7242939..c6092b6038cf 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -105,6 +105,9 @@ efi_status_t efi_parse_options(char const *cmdline)
 				efi_disable_pci_dma = true;
 			if (parse_option_str(val, "no_disable_early_pci_dma"))
 				efi_disable_pci_dma = false;
+		} else if (!strcmp(param, "video") &&
+			   val && strstarts(val, "efifb:")) {
+			efi_parse_option_graphics(val + strlen("efifb:"));
 		}
 	}
 	efi_bs_call(free_pool, buf);
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index c400fd88fe38..4844c3bd40df 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -650,6 +650,8 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
 
 efi_status_t efi_parse_options(char const *cmdline);
 
+void efi_parse_option_graphics(char *option);
+
 efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
 			   unsigned long size);
 
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 2d91699e3061..a32b784b4577 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -8,11 +8,115 @@
 #include <linux/bitops.h>
 #include <linux/efi.h>
 #include <linux/screen_info.h>
+#include <linux/string.h>
 #include <asm/efi.h>
 #include <asm/setup.h>
 
 #include "efistub.h"
 
+enum efi_cmdline_option {
+	EFI_CMDLINE_NONE,
+	EFI_CMDLINE_MODE_NUM,
+};
+
+static struct {
+	enum efi_cmdline_option option;
+	u32 mode;
+} cmdline __efistub_global = { .option = EFI_CMDLINE_NONE };
+
+static bool parse_modenum(char *option, char **next)
+{
+	u32 m;
+
+	if (!strstarts(option, "mode="))
+		return false;
+	option += strlen("mode=");
+	m = simple_strtoull(option, &option, 0);
+	if (*option && *option++ != ',')
+		return false;
+	cmdline.option = EFI_CMDLINE_MODE_NUM;
+	cmdline.mode   = m;
+
+	*next = option;
+	return true;
+}
+
+void efi_parse_option_graphics(char *option)
+{
+	while (*option) {
+		if (parse_modenum(option, &option))
+			continue;
+
+		while (*option && *option++ != ',')
+			;
+	}
+}
+
+static u32 choose_mode_modenum(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;
+
+	mode = efi_table_attr(gop, mode);
+
+	cur_mode = efi_table_attr(mode, mode);
+	if (cmdline.mode == cur_mode)
+		return cur_mode;
+
+	max_mode = efi_table_attr(mode, max_mode);
+	if (cmdline.mode >= max_mode) {
+		efi_printk("Requested mode is invalid\n");
+		return cur_mode;
+	}
+
+	status = efi_call_proto(gop, query_mode, cmdline.mode,
+				&info_size, &info);
+	if (status != EFI_SUCCESS) {
+		efi_printk("Couldn't get mode information\n");
+		return cur_mode;
+	}
+
+	pf = info->pixel_format;
+
+	efi_bs_call(free_pool, info);
+
+	if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
+		efi_printk("Invalid PixelFormat\n");
+		return cur_mode;
+	}
+
+	return cmdline.mode;
+}
+
+static void set_mode(efi_graphics_output_protocol_t *gop)
+{
+	efi_graphics_output_protocol_mode_t *mode;
+	u32 cur_mode, new_mode;
+
+	switch (cmdline.option) {
+	case EFI_CMDLINE_MODE_NUM:
+		new_mode = choose_mode_modenum(gop);
+		break;
+	default:
+		return;
+	}
+
+	mode = efi_table_attr(gop, mode);
+	cur_mode = efi_table_attr(mode, mode);
+
+	if (new_mode == cur_mode)
+		return;
+
+	if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS)
+		efi_printk("Failed to set requested mode\n");
+}
+
 static void find_bits(u32 mask, u8 *pos, u8 *size)
 {
 	if (!mask) {
@@ -124,6 +228,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 	if (!gop)
 		return EFI_NOT_FOUND;
 
+	/* Change mode if requested */
+	set_mode(gop);
+
 	/* EFI framebuffer */
 	mode = efi_table_attr(gop, mode);
 	info = efi_table_attr(mode, info);
-- 
2.24.1


  parent reply	other threads:[~2020-03-20  2:00 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-19 19:28 [PATCH 00/14] efi/gop: Refactoring + mode-setting feature Arvind Sankar
2020-03-19 19:28 ` [PATCH 01/14] efi/gop: Remove redundant current_fb_base Arvind Sankar
2020-03-19 19:28 ` [PATCH 02/14] efi/gop: Move check for framebuffer before con_out Arvind Sankar
2020-03-19 19:28 ` [PATCH 03/14] efi/gop: Get mode information outside the loop Arvind Sankar
2020-03-19 19:28 ` [PATCH 04/14] efi/gop: Factor out locating the gop into a function Arvind Sankar
2020-03-19 19:28 ` [PATCH 05/14] efi/gop: Slightly re-arrange logic of find_gop Arvind Sankar
2020-03-19 19:28 ` [PATCH 06/14] efi/gop: Move variable declarations into loop block Arvind Sankar
2020-03-19 19:28 ` [PATCH 07/14] efi/gop: Use helper macros for populating lfb_base Arvind Sankar
2020-03-19 19:28 ` [PATCH 08/14] efi/gop: Use helper macros for find_bits Arvind Sankar
2020-03-19 19:28 ` [PATCH 09/14] efi/gop: Remove unreachable code from setup_pixel_info Arvind Sankar
2020-03-19 19:28 ` [PATCH 10/14] efi/gop: Add prototypes for query_mode and set_mode Arvind Sankar
2020-03-19 19:28 ` [PATCH 11/14] efi/gop: Allow specifying mode number on command line Arvind Sankar
2020-03-19 22:53   ` kbuild test robot
2020-03-19 22:53     ` kbuild test robot
2020-03-20  1:09   ` kbuild test robot
2020-03-20  1:09     ` kbuild test robot
2020-03-20 14:36   ` Dan Carpenter
2020-03-20 14:36     ` Dan Carpenter
2020-03-20 14:36     ` Dan Carpenter
2020-03-20 17:51     ` Arvind Sankar
2020-03-19 19:28 ` [PATCH 12/14] efi/gop: Allow specifying mode by <xres>x<yres> Arvind Sankar
2020-03-19 19:28 ` [PATCH 13/14] efi/gop: Allow specifying depth as well as resolution Arvind Sankar
2020-03-19 19:28 ` [PATCH 14/14] efi/gop: Allow automatically choosing the best mode Arvind Sankar
2020-03-19 20:02 ` [PATCH 00/14] efi/gop: Refactoring + mode-setting feature Ard Biesheuvel
2020-03-20  2:00 ` [PATCH v2 " Arvind Sankar
2020-03-25 16:41   ` Ard Biesheuvel
2020-03-25 22:10     ` Arvind Sankar
2020-03-25 23:36       ` Ard Biesheuvel
2020-03-26 10:41         ` Ard Biesheuvel
2020-03-28 16:06           ` efi/gop: skip cur_mode in choose_mode_auto Arvind Sankar
2020-03-28 16:06             ` [PATCH v3] efi/gop: Allow automatically choosing the best mode Arvind Sankar
2020-03-29  7:47             ` efi/gop: skip cur_mode in choose_mode_auto Ard Biesheuvel
2020-03-26 23:56         ` [PATCH v2 00/14] efi/gop: Refactoring + mode-setting feature Arvind Sankar
2020-03-28 15:43           ` Ard Biesheuvel
2020-03-25 16:50   ` Hans de Goede
2020-03-25 22:13     ` Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 01/14] efi/gop: Remove redundant current_fb_base Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 02/14] efi/gop: Move check for framebuffer before con_out Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 03/14] efi/gop: Get mode information outside the loop Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 04/14] efi/gop: Factor out locating the gop into a function Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 05/14] efi/gop: Slightly re-arrange logic of find_gop Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 06/14] efi/gop: Move variable declarations into loop block Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 07/14] efi/gop: Use helper macros for populating lfb_base Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 08/14] efi/gop: Use helper macros for find_bits Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 09/14] efi/gop: Remove unreachable code from setup_pixel_info Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 10/14] efi/gop: Add prototypes for query_mode and set_mode Arvind Sankar
2020-03-20  2:00 ` Arvind Sankar [this message]
2020-03-20  2:00 ` [PATCH v2 12/14] efi/gop: Allow specifying mode by <xres>x<yres> Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 13/14] efi/gop: Allow specifying depth as well as resolution Arvind Sankar
2020-03-20  2:00 ` [PATCH v2 14/14] efi/gop: Allow automatically choosing the best mode Arvind Sankar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200320020028.1936003-12-nivedita@alum.mit.edu \
    --to=nivedita@alum.mit.edu \
    --cc=ardb@kernel.org \
    --cc=hdegoede@redhat.com \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.