efi/gop: Allow specifying mode number on command line
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> Link: https://lore.kernel.org/r/20200320020028.1936003-12-nivedita@alum.mit.edu Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
b4b89a0272
commit
fffb68047e
|
@ -2,8 +2,10 @@
|
||||||
What is efifb?
|
What is efifb?
|
||||||
==============
|
==============
|
||||||
|
|
||||||
This is a generic EFI platform driver for Intel based Apple computers.
|
This is a generic EFI platform driver for systems with UEFI firmware. The
|
||||||
efifb is only for EFI booted Intel Macs.
|
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
|
Supported Hardware
|
||||||
==================
|
==================
|
||||||
|
@ -12,11 +14,14 @@ Supported Hardware
|
||||||
- Macbook
|
- Macbook
|
||||||
- Macbook Pro 15"/17"
|
- Macbook Pro 15"/17"
|
||||||
- MacMini
|
- MacMini
|
||||||
|
- ARM/ARM64/X86 systems with UEFI firmware
|
||||||
|
|
||||||
How to use it?
|
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::
|
You have to add the following kernel parameters in your elilo.conf::
|
||||||
|
|
||||||
Macbook :
|
Macbook :
|
||||||
|
@ -28,6 +33,9 @@ You have to add the following kernel parameters in your elilo.conf::
|
||||||
Macbook Pro 17", iMac 20" :
|
Macbook Pro 17", iMac 20" :
|
||||||
video=efifb:i20
|
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:
|
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.
|
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>
|
Edgar Hucek <gimli@dark-green.com>
|
||||||
|
|
|
@ -105,6 +105,9 @@ efi_status_t efi_parse_options(char const *cmdline)
|
||||||
efi_disable_pci_dma = true;
|
efi_disable_pci_dma = true;
|
||||||
if (parse_option_str(val, "no_disable_early_pci_dma"))
|
if (parse_option_str(val, "no_disable_early_pci_dma"))
|
||||||
efi_disable_pci_dma = false;
|
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);
|
efi_bs_call(free_pool, buf);
|
||||||
|
|
|
@ -666,6 +666,8 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
|
||||||
|
|
||||||
efi_status_t efi_parse_options(char const *cmdline);
|
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,
|
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||||
unsigned long size);
|
unsigned long size);
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,115 @@
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/efi.h>
|
#include <linux/efi.h>
|
||||||
#include <linux/screen_info.h>
|
#include <linux/screen_info.h>
|
||||||
|
#include <linux/string.h>
|
||||||
#include <asm/efi.h>
|
#include <asm/efi.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
#include "efistub.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)
|
static void find_bits(u32 mask, u8 *pos, u8 *size)
|
||||||
{
|
{
|
||||||
if (!mask) {
|
if (!mask) {
|
||||||
|
@ -124,6 +228,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||||
if (!gop)
|
if (!gop)
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
/* Change mode if requested */
|
||||||
|
set_mode(gop);
|
||||||
|
|
||||||
/* EFI framebuffer */
|
/* EFI framebuffer */
|
||||||
mode = efi_table_attr(gop, mode);
|
mode = efi_table_attr(gop, mode);
|
||||||
info = efi_table_attr(mode, info);
|
info = efi_table_attr(mode, info);
|
||||||
|
|
Loading…
Reference in New Issue