Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f399ecb4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
+4 −2
Original line number Diff line number Diff line
@@ -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,
				       &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
			 * 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,
				       &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
			 * provide multiple GOP devices, not all of which are
+65 −1
Original line number Diff line number Diff line
@@ -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