aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 14:08:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-01 14:08:12 -0400
commit3b29b03a462346473b7d0e6c6013fe093a4ac0d1 (patch)
tree25f6e316344369c9b66010a9d67612488e24aca3
parent58ae9c0d54ae3916614fa1f3756dadb954f16e6c (diff)
parent2223af389032425e3d1a70f9cb3a63feaa654ced (diff)
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/EFI changes from Ingo Molnar: "EFI loader robustness enhancements plus smaller fixes" * 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi: Fix the ACPI BGRT driver for images located in EFI boot services memory efi: Add a function to look up existing IO memory mappings efi: Defer freeing boot services memory until after ACPI init x86, EFI: Calculate the EFI framebuffer size instead of trusting the firmware efifb: Skip DMI checks if the bootloader knows what it's doing efi: initialize efi.runtime_version to make query_variable_info/update_capsule workable efi: Build EFI stub with EFI-appropriate options X86: Improve GOP detection in the EFI boot stub
-rw-r--r--arch/x86/boot/compressed/Makefile3
-rw-r--r--arch/x86/boot/compressed/eboot.c34
-rw-r--r--arch/x86/boot/compressed/eboot.h4
-rw-r--r--arch/x86/platform/efi/Makefile1
-rw-r--r--arch/x86/platform/efi/efi-bgrt.c76
-rw-r--r--arch/x86/platform/efi/efi.c66
-rw-r--r--drivers/acpi/Kconfig4
-rw-r--r--drivers/acpi/bgrt.c76
-rw-r--r--drivers/video/efifb.c4
-rw-r--r--include/linux/efi-bgrt.h21
-rw-r--r--include/linux/efi.h8
-rw-r--r--include/linux/screen_info.h2
-rw-r--r--init/main.c5
13 files changed, 207 insertions, 97 deletions
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index e398bb5d63bb..8a84501acb1b 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
28 $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ 28 $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
29 $(obj)/piggy.o 29 $(obj)/piggy.o
30 30
31$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
32$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone
33
31ifeq ($(CONFIG_EFI_STUB), y) 34ifeq ($(CONFIG_EFI_STUB), y)
32 VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o 35 VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
33endif 36endif
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b3e0227df2c9..c760e073963e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -276,8 +276,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
276 nr_gops = size / sizeof(void *); 276 nr_gops = size / sizeof(void *);
277 for (i = 0; i < nr_gops; i++) { 277 for (i = 0; i < nr_gops; i++) {
278 struct efi_graphics_output_mode_info *info; 278 struct efi_graphics_output_mode_info *info;
279 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; 279 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
280 void *pciio; 280 bool conout_found = false;
281 void *dummy;
281 void *h = gop_handle[i]; 282 void *h = gop_handle[i];
282 283
283 status = efi_call_phys3(sys_table->boottime->handle_protocol, 284 status = efi_call_phys3(sys_table->boottime->handle_protocol,
@@ -285,19 +286,21 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
285 if (status != EFI_SUCCESS) 286 if (status != EFI_SUCCESS)
286 continue; 287 continue;
287 288
288 efi_call_phys3(sys_table->boottime->handle_protocol, 289 status = efi_call_phys3(sys_table->boottime->handle_protocol,
289 h, &pciio_proto, &pciio); 290 h, &conout_proto, &dummy);
291
292 if (status == EFI_SUCCESS)
293 conout_found = true;
290 294
291 status = efi_call_phys4(gop->query_mode, gop, 295 status = efi_call_phys4(gop->query_mode, gop,
292 gop->mode->mode, &size, &info); 296 gop->mode->mode, &size, &info);
293 if (status == EFI_SUCCESS && (!first_gop || pciio)) { 297 if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
294 /* 298 /*
295 * Apple provide GOPs that are not backed by 299 * Systems that use the UEFI Console Splitter may
296 * real hardware (they're used to handle 300 * provide multiple GOP devices, not all of which are
297 * multiple displays). The workaround is to 301 * backed by real hardware. The workaround is to search
298 * search for a GOP implementing the PCIIO 302 * for a GOP implementing the ConOut protocol, and if
299 * protocol, and if one isn't found, to just 303 * one isn't found, to just fall back to the first GOP.
300 * fallback to the first GOP.
301 */ 304 */
302 width = info->horizontal_resolution; 305 width = info->horizontal_resolution;
303 height = info->vertical_resolution; 306 height = info->vertical_resolution;
@@ -308,10 +311,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
308 pixels_per_scan_line = info->pixels_per_scan_line; 311 pixels_per_scan_line = info->pixels_per_scan_line;
309 312
310 /* 313 /*
311 * Once we've found a GOP supporting PCIIO, 314 * Once we've found a GOP supporting ConOut,
312 * don't bother looking any further. 315 * don't bother looking any further.
313 */ 316 */
314 if (pciio) 317 if (conout_found)
315 break; 318 break;
316 319
317 first_gop = gop; 320 first_gop = gop;
@@ -328,7 +331,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
328 si->lfb_width = width; 331 si->lfb_width = width;
329 si->lfb_height = height; 332 si->lfb_height = height;
330 si->lfb_base = fb_base; 333 si->lfb_base = fb_base;
331 si->lfb_size = fb_size;
332 si->pages = 1; 334 si->pages = 1;
333 335
334 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 336 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
@@ -376,6 +378,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
376 si->rsvd_pos = 0; 378 si->rsvd_pos = 0;
377 } 379 }
378 380
381 si->lfb_size = si->lfb_linelength * si->lfb_height;
382
383 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
384
379free_handle: 385free_handle:
380 efi_call_phys1(sys_table->boottime->free_pool, gop_handle); 386 efi_call_phys1(sys_table->boottime->free_pool, gop_handle);
381 return status; 387 return status;
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index 3b6e15627c55..e5b0a8f91c5f 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -14,6 +14,10 @@
14#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) 14#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
15#define EFI_READ_CHUNK_SIZE (1024 * 1024) 15#define EFI_READ_CHUNK_SIZE (1024 * 1024)
16 16
17#define EFI_CONSOLE_OUT_DEVICE_GUID \
18 EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
19 0x3f, 0xc1, 0x4d)
20
17#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0 21#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR 0
18#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1 22#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR 1
19#define PIXEL_BIT_MASK 2 23#define PIXEL_BIT_MASK 2
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 73b8be0f3675..6db1cc4c7534 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o 1obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
2obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c
new file mode 100644
index 000000000000..f6a0c1b8e518
--- /dev/null
+++ b/arch/x86/platform/efi/efi-bgrt.c
@@ -0,0 +1,76 @@
1/*
2 * Copyright 2012 Intel Corporation
3 * Author: Josh Triplett <josh@joshtriplett.org>
4 *
5 * Based on the bgrt driver:
6 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
7 * Author: Matthew Garrett
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/acpi.h>
15#include <linux/efi.h>
16#include <linux/efi-bgrt.h>
17
18struct acpi_table_bgrt *bgrt_tab;
19void *bgrt_image;
20size_t bgrt_image_size;
21
22struct bmp_header {
23 u16 id;
24 u32 size;
25} __packed;
26
27void efi_bgrt_init(void)
28{
29 acpi_status status;
30 void __iomem *image;
31 bool ioremapped = false;
32 struct bmp_header bmp_header;
33
34 if (acpi_disabled)
35 return;
36
37 status = acpi_get_table("BGRT", 0,
38 (struct acpi_table_header **)&bgrt_tab);
39 if (ACPI_FAILURE(status))
40 return;
41
42 if (bgrt_tab->version != 1)
43 return;
44 if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
45 return;
46
47 image = efi_lookup_mapped_addr(bgrt_tab->image_address);
48 if (!image) {
49 image = ioremap(bgrt_tab->image_address, sizeof(bmp_header));
50 ioremapped = true;
51 if (!image)
52 return;
53 }
54
55 memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
56 if (ioremapped)
57 iounmap(image);
58 bgrt_image_size = bmp_header.size;
59
60 bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL);
61 if (!bgrt_image)
62 return;
63
64 if (ioremapped) {
65 image = ioremap(bgrt_tab->image_address, bmp_header.size);
66 if (!image) {
67 kfree(bgrt_image);
68 bgrt_image = NULL;
69 return;
70 }
71 }
72
73 memcpy_fromio(bgrt_image, image, bgrt_image_size);
74 if (ioremapped)
75 iounmap(image);
76}
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 92660edaa1e7..aded2a91162a 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -31,6 +31,7 @@
31#include <linux/kernel.h> 31#include <linux/kernel.h>
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/efi.h> 33#include <linux/efi.h>
34#include <linux/efi-bgrt.h>
34#include <linux/export.h> 35#include <linux/export.h>
35#include <linux/bootmem.h> 36#include <linux/bootmem.h>
36#include <linux/memblock.h> 37#include <linux/memblock.h>
@@ -419,10 +420,21 @@ void __init efi_reserve_boot_services(void)
419 } 420 }
420} 421}
421 422
422static void __init efi_free_boot_services(void) 423static void __init efi_unmap_memmap(void)
424{
425 if (memmap.map) {
426 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
427 memmap.map = NULL;
428 }
429}
430
431void __init efi_free_boot_services(void)
423{ 432{
424 void *p; 433 void *p;
425 434
435 if (!efi_native)
436 return;
437
426 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 438 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
427 efi_memory_desc_t *md = p; 439 efi_memory_desc_t *md = p;
428 unsigned long long start = md->phys_addr; 440 unsigned long long start = md->phys_addr;
@@ -438,6 +450,8 @@ static void __init efi_free_boot_services(void)
438 450
439 free_bootmem_late(start, size); 451 free_bootmem_late(start, size);
440 } 452 }
453
454 efi_unmap_memmap();
441} 455}
442 456
443static int __init efi_systab_init(void *phys) 457static int __init efi_systab_init(void *phys)
@@ -732,6 +746,11 @@ void __init efi_init(void)
732#endif 746#endif
733} 747}
734 748
749void __init efi_late_init(void)
750{
751 efi_bgrt_init();
752}
753
735void __init efi_set_executable(efi_memory_desc_t *md, bool executable) 754void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
736{ 755{
737 u64 addr, npages; 756 u64 addr, npages;
@@ -764,6 +783,34 @@ static void __init runtime_code_page_mkexec(void)
764} 783}
765 784
766/* 785/*
786 * We can't ioremap data in EFI boot services RAM, because we've already mapped
787 * it as RAM. So, look it up in the existing EFI memory map instead. Only
788 * callable after efi_enter_virtual_mode and before efi_free_boot_services.
789 */
790void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
791{
792 void *p;
793 if (WARN_ON(!memmap.map))
794 return NULL;
795 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
796 efi_memory_desc_t *md = p;
797 u64 size = md->num_pages << EFI_PAGE_SHIFT;
798 u64 end = md->phys_addr + size;
799 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
800 md->type != EFI_BOOT_SERVICES_CODE &&
801 md->type != EFI_BOOT_SERVICES_DATA)
802 continue;
803 if (!md->virt_addr)
804 continue;
805 if (phys_addr >= md->phys_addr && phys_addr < end) {
806 phys_addr += md->virt_addr - md->phys_addr;
807 return (__force void __iomem *)(unsigned long)phys_addr;
808 }
809 }
810 return NULL;
811}
812
813/*
767 * This function will switch the EFI runtime services to virtual mode. 814 * This function will switch the EFI runtime services to virtual mode.
768 * Essentially, look through the EFI memmap and map every region that 815 * Essentially, look through the EFI memmap and map every region that
769 * has the runtime attribute bit set in its memory descriptor and update 816 * has the runtime attribute bit set in its memory descriptor and update
@@ -787,8 +834,10 @@ void __init efi_enter_virtual_mode(void)
787 * non-native EFI 834 * non-native EFI
788 */ 835 */
789 836
790 if (!efi_native) 837 if (!efi_native) {
791 goto out; 838 efi_unmap_memmap();
839 return;
840 }
792 841
793 /* Merge contiguous regions of the same type and attribute */ 842 /* Merge contiguous regions of the same type and attribute */
794 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 843 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -878,18 +927,12 @@ void __init efi_enter_virtual_mode(void)
878 } 927 }
879 928
880 /* 929 /*
881 * Thankfully, it does seem that no runtime services other than
882 * SetVirtualAddressMap() will touch boot services code, so we can
883 * get rid of it all at this point
884 */
885 efi_free_boot_services();
886
887 /*
888 * Now that EFI is in virtual mode, update the function 930 * Now that EFI is in virtual mode, update the function
889 * pointers in the runtime service table to the new virtual addresses. 931 * pointers in the runtime service table to the new virtual addresses.
890 * 932 *
891 * Call EFI services through wrapper functions. 933 * Call EFI services through wrapper functions.
892 */ 934 */
935 efi.runtime_version = efi_systab.fw_revision;
893 efi.get_time = virt_efi_get_time; 936 efi.get_time = virt_efi_get_time;
894 efi.set_time = virt_efi_set_time; 937 efi.set_time = virt_efi_set_time;
895 efi.get_wakeup_time = virt_efi_get_wakeup_time; 938 efi.get_wakeup_time = virt_efi_get_wakeup_time;
@@ -906,9 +949,6 @@ void __init efi_enter_virtual_mode(void)
906 if (__supported_pte_mask & _PAGE_NX) 949 if (__supported_pte_mask & _PAGE_NX)
907 runtime_code_page_mkexec(); 950 runtime_code_page_mkexec();
908 951
909out:
910 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
911 memmap.map = NULL;
912 kfree(new_memmap); 952 kfree(new_memmap);
913} 953}
914 954
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 80998958cf45..119d58db8342 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -385,8 +385,8 @@ config ACPI_CUSTOM_METHOD
385 to override that restriction). 385 to override that restriction).
386 386
387config ACPI_BGRT 387config ACPI_BGRT
388 tristate "Boottime Graphics Resource Table support" 388 bool "Boottime Graphics Resource Table support"
389 default n 389 depends on EFI
390 help 390 help
391 This driver adds support for exposing the ACPI Boottime Graphics 391 This driver adds support for exposing the ACPI Boottime Graphics
392 Resource Table, which allows the operating system to obtain 392 Resource Table, which allows the operating system to obtain
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
index 6680df36b963..be6039958545 100644
--- a/drivers/acpi/bgrt.c
+++ b/drivers/acpi/bgrt.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright 2012 Red Hat, Inc <mjg@redhat.com> 2 * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
3 * Copyright 2012 Intel Corporation
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -11,20 +12,10 @@
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/device.h> 13#include <linux/device.h>
13#include <linux/sysfs.h> 14#include <linux/sysfs.h>
14#include <linux/io.h> 15#include <linux/efi-bgrt.h>
15#include <acpi/acpi.h>
16#include <acpi/acpi_bus.h>
17 16
18static struct acpi_table_bgrt *bgrt_tab;
19static struct kobject *bgrt_kobj; 17static struct kobject *bgrt_kobj;
20 18
21struct bmp_header {
22 u16 id;
23 u32 size;
24} __attribute ((packed));
25
26static struct bmp_header bmp_header;
27
28static ssize_t show_version(struct device *dev, 19static ssize_t show_version(struct device *dev,
29 struct device_attribute *attr, char *buf) 20 struct device_attribute *attr, char *buf)
30{ 21{
@@ -63,18 +54,7 @@ static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
63static ssize_t show_image(struct file *file, struct kobject *kobj, 54static ssize_t show_image(struct file *file, struct kobject *kobj,
64 struct bin_attribute *attr, char *buf, loff_t off, size_t count) 55 struct bin_attribute *attr, char *buf, loff_t off, size_t count)
65{ 56{
66 int size = attr->size; 57 memcpy(buf, attr->private + off, count);
67 void __iomem *image = attr->private;
68
69 if (off >= size) {
70 count = 0;
71 } else {
72 if (off + count > size)
73 count = size - off;
74
75 memcpy_fromio(buf, image+off, count);
76 }
77
78 return count; 58 return count;
79} 59}
80 60
@@ -101,45 +81,18 @@ static struct attribute_group bgrt_attribute_group = {
101 81
102static int __init bgrt_init(void) 82static int __init bgrt_init(void)
103{ 83{
104 acpi_status status;
105 int ret; 84 int ret;
106 void __iomem *bgrt;
107 85
108 if (acpi_disabled) 86 if (!bgrt_image)
109 return -ENODEV;
110
111 status = acpi_get_table("BGRT", 0,
112 (struct acpi_table_header **)&bgrt_tab);
113
114 if (ACPI_FAILURE(status))
115 return -ENODEV; 87 return -ENODEV;
116 88
117 sysfs_bin_attr_init(&image_attr); 89 sysfs_bin_attr_init(&image_attr);
118 90 image_attr.private = bgrt_image;
119 bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); 91 image_attr.size = bgrt_image_size;
120
121 if (!bgrt) {
122 ret = -EINVAL;
123 goto out_err;
124 }
125
126 memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header));
127 image_attr.size = bmp_header.size;
128 iounmap(bgrt);
129
130 image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size);
131
132 if (!image_attr.private) {
133 ret = -EINVAL;
134 goto out_err;
135 }
136
137 92
138 bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); 93 bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
139 if (!bgrt_kobj) { 94 if (!bgrt_kobj)
140 ret = -EINVAL; 95 return -EINVAL;
141 goto out_iounmap;
142 }
143 96
144 ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); 97 ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group);
145 if (ret) 98 if (ret)
@@ -155,22 +108,11 @@ out_group:
155 sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); 108 sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
156out_kobject: 109out_kobject:
157 kobject_put(bgrt_kobj); 110 kobject_put(bgrt_kobj);
158out_iounmap:
159 iounmap(image_attr.private);
160out_err:
161 return ret; 111 return ret;
162} 112}
163 113
164static void __exit bgrt_exit(void)
165{
166 iounmap(image_attr.private);
167 sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
168 sysfs_remove_bin_file(bgrt_kobj, &image_attr);
169}
170
171module_init(bgrt_init); 114module_init(bgrt_init);
172module_exit(bgrt_exit);
173 115
174MODULE_AUTHOR("Matthew Garrett"); 116MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>");
175MODULE_DESCRIPTION("BGRT boot graphic support"); 117MODULE_DESCRIPTION("BGRT boot graphic support");
176MODULE_LICENSE("GPL"); 118MODULE_LICENSE("GPL");
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index b4a632ada401..932abaa58a89 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -553,7 +553,9 @@ static int __init efifb_init(void)
553 int ret; 553 int ret;
554 char *option = NULL; 554 char *option = NULL;
555 555
556 dmi_check_system(dmi_system_table); 556 if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
557 !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
558 dmi_check_system(dmi_system_table);
557 559
558 if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) 560 if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
559 return -ENODEV; 561 return -ENODEV;
diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h
new file mode 100644
index 000000000000..051b21fedf68
--- /dev/null
+++ b/include/linux/efi-bgrt.h
@@ -0,0 +1,21 @@
1#ifndef _LINUX_EFI_BGRT_H
2#define _LINUX_EFI_BGRT_H
3
4#ifdef CONFIG_ACPI_BGRT
5
6#include <linux/acpi.h>
7
8void efi_bgrt_init(void);
9
10/* The BGRT data itself; only valid if bgrt_image != NULL. */
11extern void *bgrt_image;
12extern size_t bgrt_image_size;
13extern struct acpi_table_bgrt *bgrt_tab;
14
15#else /* !CONFIG_ACPI_BGRT */
16
17static inline void efi_bgrt_init(void) {}
18
19#endif /* !CONFIG_ACPI_BGRT */
20
21#endif /* _LINUX_EFI_BGRT_H */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ec45ccd8708a..8670eb1eb8cd 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -496,6 +496,14 @@ extern void efi_map_pal_code (void);
496extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); 496extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
497extern void efi_gettimeofday (struct timespec *ts); 497extern void efi_gettimeofday (struct timespec *ts);
498extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ 498extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
499#ifdef CONFIG_X86
500extern void efi_late_init(void);
501extern void efi_free_boot_services(void);
502#else
503static inline void efi_late_init(void) {}
504static inline void efi_free_boot_services(void) {}
505#endif
506extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
499extern u64 efi_get_iobase (void); 507extern u64 efi_get_iobase (void);
500extern u32 efi_mem_type (unsigned long phys_addr); 508extern u32 efi_mem_type (unsigned long phys_addr);
501extern u64 efi_mem_attributes (unsigned long phys_addr); 509extern u64 efi_mem_attributes (unsigned long phys_addr);
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 899fbb487c94..fb3c5a8fef3d 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -68,6 +68,8 @@ struct screen_info {
68 68
69#define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */ 69#define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */
70 70
71#define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0)
72
71#ifdef __KERNEL__ 73#ifdef __KERNEL__
72extern struct screen_info screen_info; 74extern struct screen_info screen_info;
73 75
diff --git a/init/main.c b/init/main.c
index b28673087ac0..db34c0ec4711 100644
--- a/init/main.c
+++ b/init/main.c
@@ -631,6 +631,11 @@ asmlinkage void __init start_kernel(void)
631 acpi_early_init(); /* before LAPIC and SMP init */ 631 acpi_early_init(); /* before LAPIC and SMP init */
632 sfi_init_late(); 632 sfi_init_late();
633 633
634 if (efi_enabled) {
635 efi_late_init();
636 efi_free_boot_services();
637 }
638
634 ftrace_init(); 639 ftrace_init();
635 640
636 /* Do the rest non-__init'ed, we're now alive */ 641 /* Do the rest non-__init'ed, we're now alive */