mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 21:44:06 +08:00
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
This commit is contained in:
commit
f399ecb4b4
@ -201,6 +201,10 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
|
||||
return;
|
||||
}
|
||||
|
||||
/* No need to reserve regions that will never be freed. */
|
||||
if (md.attribute & EFI_MEMORY_RUNTIME)
|
||||
return;
|
||||
|
||||
size += addr % EFI_PAGE_SIZE;
|
||||
size = round_up(size, 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,
|
||||
|
||||
status = __gop_query32(sys_table_arg, gop32, &info, &size,
|
||||
¤t_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
|
||||
* 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,
|
||||
|
||||
status = __gop_query64(sys_table_arg, gop64, &info, &size,
|
||||
¤t_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
|
||||
* provide multiple GOP devices, not all of which are
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/efi.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <video/vga.h>
|
||||
@ -143,6 +144,8 @@ static struct attribute *efifb_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(efifb);
|
||||
|
||||
static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
|
||||
|
||||
static int efifb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
@ -152,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
|
||||
unsigned int size_total;
|
||||
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;
|
||||
|
||||
if (fb_get_options("efifb", &option))
|
||||
@ -360,3 +363,64 @@ static struct 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
|
||||
|
Loading…
Reference in New Issue
Block a user