diff options
| -rw-r--r-- | arch/x86/boot/compressed/Makefile | 3 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/eboot.c | 34 | ||||
| -rw-r--r-- | arch/x86/boot/compressed/eboot.h | 4 | ||||
| -rw-r--r-- | arch/x86/platform/efi/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi-bgrt.c | 76 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 66 | ||||
| -rw-r--r-- | drivers/acpi/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/acpi/bgrt.c | 76 | ||||
| -rw-r--r-- | drivers/video/efifb.c | 4 | ||||
| -rw-r--r-- | include/linux/efi-bgrt.h | 21 | ||||
| -rw-r--r-- | include/linux/efi.h | 8 | ||||
| -rw-r--r-- | include/linux/screen_info.h | 2 | ||||
| -rw-r--r-- | init/main.c | 5 |
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 | |||
| 31 | ifeq ($(CONFIG_EFI_STUB), y) | 34 | ifeq ($(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 |
| 33 | endif | 36 | endif |
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 | |||
| 379 | free_handle: | 385 | free_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 @@ | |||
| 1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 1 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
| 2 | obj-$(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 | |||
| 18 | struct acpi_table_bgrt *bgrt_tab; | ||
| 19 | void *bgrt_image; | ||
| 20 | size_t bgrt_image_size; | ||
| 21 | |||
| 22 | struct bmp_header { | ||
| 23 | u16 id; | ||
| 24 | u32 size; | ||
| 25 | } __packed; | ||
| 26 | |||
| 27 | void 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 | ||
| 422 | static void __init efi_free_boot_services(void) | 423 | static 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 | |||
| 431 | void __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 | ||
| 443 | static int __init efi_systab_init(void *phys) | 457 | static int __init efi_systab_init(void *phys) |
| @@ -732,6 +746,11 @@ void __init efi_init(void) | |||
| 732 | #endif | 746 | #endif |
| 733 | } | 747 | } |
| 734 | 748 | ||
| 749 | void __init efi_late_init(void) | ||
| 750 | { | ||
| 751 | efi_bgrt_init(); | ||
| 752 | } | ||
| 753 | |||
| 735 | void __init efi_set_executable(efi_memory_desc_t *md, bool executable) | 754 | void __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 | */ | ||
| 790 | void __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 | ||
| 909 | out: | ||
| 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 | ||
| 387 | config ACPI_BGRT | 387 | config 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 | ||
| 18 | static struct acpi_table_bgrt *bgrt_tab; | ||
| 19 | static struct kobject *bgrt_kobj; | 17 | static struct kobject *bgrt_kobj; |
| 20 | 18 | ||
| 21 | struct bmp_header { | ||
| 22 | u16 id; | ||
| 23 | u32 size; | ||
| 24 | } __attribute ((packed)); | ||
| 25 | |||
| 26 | static struct bmp_header bmp_header; | ||
| 27 | |||
| 28 | static ssize_t show_version(struct device *dev, | 19 | static 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); | |||
| 63 | static ssize_t show_image(struct file *file, struct kobject *kobj, | 54 | static 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 | ||
| 102 | static int __init bgrt_init(void) | 82 | static 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); |
| 156 | out_kobject: | 109 | out_kobject: |
| 157 | kobject_put(bgrt_kobj); | 110 | kobject_put(bgrt_kobj); |
| 158 | out_iounmap: | ||
| 159 | iounmap(image_attr.private); | ||
| 160 | out_err: | ||
| 161 | return ret; | 111 | return ret; |
| 162 | } | 112 | } |
| 163 | 113 | ||
| 164 | static 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 | |||
| 171 | module_init(bgrt_init); | 114 | module_init(bgrt_init); |
| 172 | module_exit(bgrt_exit); | ||
| 173 | 115 | ||
| 174 | MODULE_AUTHOR("Matthew Garrett"); | 116 | MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>"); |
| 175 | MODULE_DESCRIPTION("BGRT boot graphic support"); | 117 | MODULE_DESCRIPTION("BGRT boot graphic support"); |
| 176 | MODULE_LICENSE("GPL"); | 118 | MODULE_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 | |||
| 8 | void efi_bgrt_init(void); | ||
| 9 | |||
| 10 | /* The BGRT data itself; only valid if bgrt_image != NULL. */ | ||
| 11 | extern void *bgrt_image; | ||
| 12 | extern size_t bgrt_image_size; | ||
| 13 | extern struct acpi_table_bgrt *bgrt_tab; | ||
| 14 | |||
| 15 | #else /* !CONFIG_ACPI_BGRT */ | ||
| 16 | |||
| 17 | static 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); | |||
| 496 | extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); | 496 | extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); |
| 497 | extern void efi_gettimeofday (struct timespec *ts); | 497 | extern void efi_gettimeofday (struct timespec *ts); |
| 498 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ | 498 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ |
| 499 | #ifdef CONFIG_X86 | ||
| 500 | extern void efi_late_init(void); | ||
| 501 | extern void efi_free_boot_services(void); | ||
| 502 | #else | ||
| 503 | static inline void efi_late_init(void) {} | ||
| 504 | static inline void efi_free_boot_services(void) {} | ||
| 505 | #endif | ||
| 506 | extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); | ||
| 499 | extern u64 efi_get_iobase (void); | 507 | extern u64 efi_get_iobase (void); |
| 500 | extern u32 efi_mem_type (unsigned long phys_addr); | 508 | extern u32 efi_mem_type (unsigned long phys_addr); |
| 501 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 509 | extern 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__ |
| 72 | extern struct screen_info screen_info; | 74 | extern 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 */ |
