mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
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?
|
||||
==============
|
||||
|
||||
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>
|
||||
|
@ -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);
|
||||
|
@ -666,6 +666,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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user