Commit f399ecb4 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Thomas Gleixner:
 "Three fixes from EFI land:

   - prevent accessing a Graphic Output Device (GOP) which the kernel
     does not know to handle

   - prevent PCI reconfiguration to modify a BAR which covers the
     framebuffer because that's already in use through the EFI GOP
     interface

   - avoid reserving EFI runtime regions as this results in bogus memory
     mappings"

* 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/efi: Don't try to reserve runtime regions
  efi/fb: Avoid reconfiguration of BAR that covers the framebuffer
  efi/libstub: Skip GOP with PIXEL_BLT_ONLY format
parents 4b31ac48 6f6266a5
...@@ -201,6 +201,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) ...@@ -201,6 +201,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
return; return;
} }
/* No need to reserve regions that will never be freed. */
if (md.attribute & EFI_MEMORY_RUNTIME)
return;
size += addr % EFI_PAGE_SIZE; size += addr % EFI_PAGE_SIZE;
size = round_up(size, EFI_PAGE_SIZE); size = round_up(size, EFI_PAGE_SIZE);
addr = round_down(addr, EFI_PAGE_SIZE); addr = round_down(addr, EFI_PAGE_SIZE);
......
...@@ -149,7 +149,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si, ...@@ -149,7 +149,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
status = __gop_query32(sys_table_arg, gop32, &info, &size, status = __gop_query32(sys_table_arg, gop32, &info, &size,
&current_fb_base); &current_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) { if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
info->pixel_format != PIXEL_BLT_ONLY) {
/* /*
* Systems that use the UEFI Console Splitter may * Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are * provide multiple GOP devices, not all of which are
...@@ -266,7 +267,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si, ...@@ -266,7 +267,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
status = __gop_query64(sys_table_arg, gop64, &info, &size, status = __gop_query64(sys_table_arg, gop64, &info, &size,
&current_fb_base); &current_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) { if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
info->pixel_format != PIXEL_BLT_ONLY) {
/* /*
* Systems that use the UEFI Console Splitter may * Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are * provide multiple GOP devices, not all of which are
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/screen_info.h> #include <linux/screen_info.h>
#include <video/vga.h> #include <video/vga.h>
...@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = { ...@@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
}; };
ATTRIBUTE_GROUPS(efifb); ATTRIBUTE_GROUPS(efifb);
static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
static int efifb_probe(struct platform_device *dev) static int efifb_probe(struct platform_device *dev)
{ {
struct fb_info *info; struct fb_info *info;
...@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev) ...@@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
unsigned int size_total; unsigned int size_total;
char *option = NULL; char *option = NULL;
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV; return -ENODEV;
if (fb_get_options("efifb", &option)) if (fb_get_options("efifb", &option))
...@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = { ...@@ -360,3 +363,64 @@ static struct platform_driver efifb_driver = {
}; };
builtin_platform_driver(efifb_driver); builtin_platform_driver(efifb_driver);
#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
static void claim_efifb_bar(struct pci_dev *dev, int idx)
{
u16 word;
pci_bar_found = true;
pci_read_config_word(dev, PCI_COMMAND, &word);
if (!(word & PCI_COMMAND_MEMORY)) {
pci_dev_disabled = true;
dev_err(&dev->dev,
"BAR %d: assigned to efifb but device is disabled!\n",
idx);
return;
}
if (pci_claim_resource(dev, idx)) {
pci_dev_disabled = true;
dev_err(&dev->dev,
"BAR %d: failed to claim resource for efifb!\n", idx);
return;
}
dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
}
static void efifb_fixup_resources(struct pci_dev *dev)
{
u64 base = screen_info.lfb_base;
u64 size = screen_info.lfb_size;
int i;
if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return;
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
base |= (u64)screen_info.ext_lfb_base << 32;
if (!base)
return;
for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
struct resource *res = &dev->resource[i];
if (!(res->flags & IORESOURCE_MEM))
continue;
if (res->start <= base && res->end >= base + size - 1) {
claim_efifb_bar(dev, i);
break;
}
}
}
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
16, efifb_fixup_resources);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment