Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'efi-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into core/efi

Pull v4.4 EFI updates from Matt Fleming:

- Make the EFI System Resource Table (ESRT) driver explicitly
non-modular by ripping out the module_* code since Kconfig doesn't
allow it to be built as a module anyway. (Paul Gortmaker)

- Make the x86 efi=debug kernel parameter, which enables EFI debug
code and output, generic and usable by arm64. (Leif Lindholm)

- Add support to the x86 EFI boot stub for 64-bit Graphics Output
Protocol frame buffer addresses. (Matt Fleming)

- Detect when the UEFI v2.5 EFI_PROPERTIES_TABLE feature is enabled
in the firmware and set an efi.flags bit so the kernel knows when
it can apply more strict runtime mapping attributes - Ard Biesheuvel

- Auto-load the efi-pstore module on EFI systems, just like we
currently do for the efivars module. (Ben Hutchings)

- Add "efi_fake_mem" kernel parameter which allows the system's EFI
memory map to be updated with additional attributes for specific
memory ranges. This is useful for testing the kernel code that handles
the EFI_MEMORY_MORE_RELIABLE memmap bit even if your firmware
doesn't include support. (Taku Izumi)

Note: there is a semantic conflict between the following two commits:

8a53554e12e9 ("x86/efi: Fix multiple GOP device support")
ae2ee627dc87 ("efifb: Add support for 64-bit frame buffer addresses")

I fixed up the interaction in the merge commit, changing the type of
current_fb_base from u32 to u64.

Signed-off-by: Ingo Molnar <mingo@kernel.org>

+402 -67
-2
Documentation/arm/uefi.txt
··· 60 60 -------------------------------------------------------------------------------- 61 61 linux,uefi-stub-kern-ver | string | Copy of linux_banner from build. 62 62 -------------------------------------------------------------------------------- 63 - 64 - For verbose debug messages, specify 'uefi_debug' on the kernel command line.
+15
Documentation/kernel-parameters.txt
··· 1094 1094 you are really sure that your UEFI does sane gc and 1095 1095 fulfills the spec otherwise your board may brick. 1096 1096 1097 + efi_fake_mem= nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86] 1098 + Add arbitrary attribute to specific memory range by 1099 + updating original EFI memory map. 1100 + Region of memory which aa attribute is added to is 1101 + from ss to ss+nn. 1102 + If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000 1103 + is specified, EFI_MEMORY_MORE_RELIABLE(0x10000) 1104 + attribute is added to range 0x100000000-0x180000000 and 1105 + 0x10a0000000-0x1120000000. 1106 + 1107 + Using this parameter you can do debugging of EFI memmap 1108 + related feature. For example, you can do debugging of 1109 + Address Range Mirroring feature even if your box 1110 + doesn't support it. 1111 + 1097 1112 eisa_irq_edge= [PARISC,HW] 1098 1113 See header of drivers/parisc/eisa.c. 1099 1114
+5 -14
arch/arm64/kernel/efi.c
··· 51 51 INIT_MM_CONTEXT(efi_mm) 52 52 }; 53 53 54 - static int uefi_debug __initdata; 55 - static int __init uefi_debug_setup(char *str) 56 - { 57 - uefi_debug = 1; 58 - 59 - return 0; 60 - } 61 - early_param("uefi_debug", uefi_debug_setup); 62 - 63 54 static int __init is_normal_ram(efi_memory_desc_t *md) 64 55 { 65 56 if (md->attribute & EFI_MEMORY_WB) ··· 162 171 efi_memory_desc_t *md; 163 172 u64 paddr, npages, size; 164 173 165 - if (uefi_debug) 174 + if (efi_enabled(EFI_DBG)) 166 175 pr_info("Processing EFI memory map:\n"); 167 176 168 177 for_each_efi_memory_desc(&memmap, md) { 169 178 paddr = md->phys_addr; 170 179 npages = md->num_pages; 171 180 172 - if (uefi_debug) { 181 + if (efi_enabled(EFI_DBG)) { 173 182 char buf[64]; 174 183 175 184 pr_info(" 0x%012llx-0x%012llx %s", ··· 185 194 186 195 if (is_reserve_region(md)) { 187 196 memblock_reserve(paddr, size); 188 - if (uefi_debug) 197 + if (efi_enabled(EFI_DBG)) 189 198 pr_cont("*"); 190 199 } 191 200 192 - if (uefi_debug) 201 + if (efi_enabled(EFI_DBG)) 193 202 pr_cont("\n"); 194 203 } 195 204 ··· 201 210 struct efi_fdt_params params; 202 211 203 212 /* Grab UEFI information placed in FDT by stub */ 204 - if (!efi_get_fdt_params(&params, uefi_debug)) 213 + if (!efi_get_fdt_params(&params)) 205 214 return; 206 215 207 216 efi_system_table = params.system_table;
+22 -6
arch/x86/boot/compressed/eboot.c
··· 624 624 static efi_status_t 625 625 __gop_query32(struct efi_graphics_output_protocol_32 *gop32, 626 626 struct efi_graphics_output_mode_info **info, 627 - unsigned long *size, u32 *fb_base) 627 + unsigned long *size, u64 *fb_base) 628 628 { 629 629 struct efi_graphics_output_protocol_mode_32 *mode; 630 630 efi_status_t status; ··· 650 650 unsigned long nr_gops; 651 651 u16 width, height; 652 652 u32 pixels_per_scan_line; 653 - u32 fb_base; 653 + u32 ext_lfb_base; 654 + u64 fb_base; 654 655 struct efi_pixel_bitmask pixel_info; 655 656 int pixel_format; 656 657 efi_status_t status; ··· 668 667 bool conout_found = false; 669 668 void *dummy = NULL; 670 669 u32 h = handles[i]; 671 - u32 current_fb_base; 670 + u64 current_fb_base; 672 671 673 672 status = efi_call_early(handle_protocol, h, 674 673 proto, (void **)&gop32); ··· 716 715 si->lfb_width = width; 717 716 si->lfb_height = height; 718 717 si->lfb_base = fb_base; 718 + 719 + ext_lfb_base = (u64)(unsigned long)fb_base >> 32; 720 + if (ext_lfb_base) { 721 + si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; 722 + si->ext_lfb_base = ext_lfb_base; 723 + } 724 + 719 725 si->pages = 1; 720 726 721 727 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format); ··· 737 729 static efi_status_t 738 730 __gop_query64(struct efi_graphics_output_protocol_64 *gop64, 739 731 struct efi_graphics_output_mode_info **info, 740 - unsigned long *size, u32 *fb_base) 732 + unsigned long *size, u64 *fb_base) 741 733 { 742 734 struct efi_graphics_output_protocol_mode_64 *mode; 743 735 efi_status_t status; ··· 763 755 unsigned long nr_gops; 764 756 u16 width, height; 765 757 u32 pixels_per_scan_line; 766 - u32 fb_base; 758 + u32 ext_lfb_base; 759 + u64 fb_base; 767 760 struct efi_pixel_bitmask pixel_info; 768 761 int pixel_format; 769 762 efi_status_t status; ··· 781 772 bool conout_found = false; 782 773 void *dummy = NULL; 783 774 u64 h = handles[i]; 784 - u32 current_fb_base; 775 + u64 current_fb_base; 785 776 786 777 status = efi_call_early(handle_protocol, h, 787 778 proto, (void **)&gop64); ··· 829 820 si->lfb_width = width; 830 821 si->lfb_height = height; 831 822 si->lfb_base = fb_base; 823 + 824 + ext_lfb_base = (u64)(unsigned long)fb_base >> 32; 825 + if (ext_lfb_base) { 826 + si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; 827 + si->ext_lfb_base = ext_lfb_base; 828 + } 829 + 832 830 si->pages = 1; 833 831 834 832 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+1
arch/x86/include/asm/efi.h
··· 105 105 extern int __init efi_memblock_x86_reserve_range(void); 106 106 extern pgd_t * __init efi_call_phys_prolog(void); 107 107 extern void __init efi_call_phys_epilog(pgd_t *save_pgd); 108 + extern void __init efi_print_memmap(void); 108 109 extern void __init efi_unmap_memmap(void); 109 110 extern void __init efi_memory_uc(u64 addr, unsigned long size); 110 111 extern void __init efi_map_region(efi_memory_desc_t *md);
+3 -1
arch/x86/kernel/setup.c
··· 1079 1079 memblock_set_current_limit(ISA_END_ADDRESS); 1080 1080 memblock_x86_fill(); 1081 1081 1082 - if (efi_enabled(EFI_BOOT)) 1082 + if (efi_enabled(EFI_BOOT)) { 1083 + efi_fake_memmap(); 1083 1084 efi_find_mirror(); 1085 + } 1084 1086 1085 1087 /* 1086 1088 * The EFI specification says that boot service code won't be called
+2 -4
arch/x86/platform/efi/efi.c
··· 222 222 return 0; 223 223 } 224 224 225 - static void __init print_efi_memmap(void) 225 + void __init efi_print_memmap(void) 226 226 { 227 227 #ifdef EFI_DEBUG 228 228 efi_memory_desc_t *md; ··· 524 524 return; 525 525 526 526 if (efi_enabled(EFI_DBG)) 527 - print_efi_memmap(); 527 + efi_print_memmap(); 528 528 529 529 efi_esrt_init(); 530 530 } ··· 1026 1026 1027 1027 if (parse_option_str(str, "old_map")) 1028 1028 set_bit(EFI_OLD_MEMMAP, &efi.flags); 1029 - if (parse_option_str(str, "debug")) 1030 - set_bit(EFI_DBG, &efi.flags); 1031 1029 1032 1030 return 0; 1033 1031 }
+22
drivers/firmware/efi/Kconfig
··· 52 52 53 53 See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. 54 54 55 + config EFI_FAKE_MEMMAP 56 + bool "Enable EFI fake memory map" 57 + depends on EFI && X86 58 + default n 59 + help 60 + Saying Y here will enable "efi_fake_mem" boot option. 61 + By specifying this parameter, you can add arbitrary attribute 62 + to specific memory range by updating original (firmware provided) 63 + EFI memmap. 64 + This is useful for debugging of EFI memmap related feature. 65 + e.g. Address Range Mirroring feature. 66 + 67 + config EFI_MAX_FAKE_MEM 68 + int "maximum allowable number of ranges in efi_fake_mem boot option" 69 + depends on EFI_FAKE_MEMMAP 70 + range 1 128 71 + default 8 72 + help 73 + Maximum allowable number of ranges in efi_fake_mem boot option. 74 + Ranges can be set up to this value using comma-separated list. 75 + The default value is 8. 76 + 55 77 config EFI_PARAMS_FROM_FDT 56 78 bool 57 79 help
+1
drivers/firmware/efi/Makefile
··· 9 9 obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o 10 10 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o 11 11 obj-$(CONFIG_EFI_STUB) += libstub/ 12 + obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
+1
drivers/firmware/efi/efi-pstore.c
··· 400 400 401 401 MODULE_DESCRIPTION("EFI variable backend for pstore"); 402 402 MODULE_LICENSE("GPL"); 403 + MODULE_ALIAS("platform:efivars");
+42 -20
drivers/firmware/efi/efi.c
··· 26 26 #include <linux/platform_device.h> 27 27 28 28 struct efi __read_mostly efi = { 29 - .mps = EFI_INVALID_TABLE_ADDR, 30 - .acpi = EFI_INVALID_TABLE_ADDR, 31 - .acpi20 = EFI_INVALID_TABLE_ADDR, 32 - .smbios = EFI_INVALID_TABLE_ADDR, 33 - .smbios3 = EFI_INVALID_TABLE_ADDR, 34 - .sal_systab = EFI_INVALID_TABLE_ADDR, 35 - .boot_info = EFI_INVALID_TABLE_ADDR, 36 - .hcdp = EFI_INVALID_TABLE_ADDR, 37 - .uga = EFI_INVALID_TABLE_ADDR, 38 - .uv_systab = EFI_INVALID_TABLE_ADDR, 39 - .fw_vendor = EFI_INVALID_TABLE_ADDR, 40 - .runtime = EFI_INVALID_TABLE_ADDR, 41 - .config_table = EFI_INVALID_TABLE_ADDR, 42 - .esrt = EFI_INVALID_TABLE_ADDR, 29 + .mps = EFI_INVALID_TABLE_ADDR, 30 + .acpi = EFI_INVALID_TABLE_ADDR, 31 + .acpi20 = EFI_INVALID_TABLE_ADDR, 32 + .smbios = EFI_INVALID_TABLE_ADDR, 33 + .smbios3 = EFI_INVALID_TABLE_ADDR, 34 + .sal_systab = EFI_INVALID_TABLE_ADDR, 35 + .boot_info = EFI_INVALID_TABLE_ADDR, 36 + .hcdp = EFI_INVALID_TABLE_ADDR, 37 + .uga = EFI_INVALID_TABLE_ADDR, 38 + .uv_systab = EFI_INVALID_TABLE_ADDR, 39 + .fw_vendor = EFI_INVALID_TABLE_ADDR, 40 + .runtime = EFI_INVALID_TABLE_ADDR, 41 + .config_table = EFI_INVALID_TABLE_ADDR, 42 + .esrt = EFI_INVALID_TABLE_ADDR, 43 + .properties_table = EFI_INVALID_TABLE_ADDR, 43 44 }; 44 45 EXPORT_SYMBOL(efi); 45 46 ··· 63 62 pr_warn("need at least one option\n"); 64 63 return -EINVAL; 65 64 } 65 + 66 + if (parse_option_str(str, "debug")) 67 + set_bit(EFI_DBG, &efi.flags); 66 68 67 69 if (parse_option_str(str, "noruntime")) 68 70 disable_runtime = true; ··· 366 362 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, 367 363 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, 368 364 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, 365 + {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, 369 366 {NULL_GUID, NULL, NULL}, 370 367 }; 371 368 ··· 426 421 } 427 422 pr_cont("\n"); 428 423 set_bit(EFI_CONFIG_TABLES, &efi.flags); 424 + 425 + /* Parse the EFI Properties table if it exists */ 426 + if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { 427 + efi_properties_table_t *tbl; 428 + 429 + tbl = early_memremap(efi.properties_table, sizeof(*tbl)); 430 + if (tbl == NULL) { 431 + pr_err("Could not map Properties table!\n"); 432 + return -ENOMEM; 433 + } 434 + 435 + if (tbl->memory_protection_attribute & 436 + EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) 437 + set_bit(EFI_NX_PE_DATA, &efi.flags); 438 + 439 + early_memunmap(tbl, sizeof(*tbl)); 440 + } 441 + 429 442 return 0; 430 443 } 431 444 ··· 512 489 }; 513 490 514 491 struct param_info { 515 - int verbose; 516 492 int found; 517 493 void *params; 518 494 }; ··· 542 520 else 543 521 *(u64 *)dest = val; 544 522 545 - if (info->verbose) 523 + if (efi_enabled(EFI_DBG)) 546 524 pr_info(" %s: 0x%0*llx\n", dt_params[i].name, 547 525 dt_params[i].size * 2, val); 548 526 } 549 527 return 1; 550 528 } 551 529 552 - int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) 530 + int __init efi_get_fdt_params(struct efi_fdt_params *params) 553 531 { 554 532 struct param_info info; 555 533 int ret; 556 534 557 535 pr_info("Getting EFI parameters from FDT:\n"); 558 536 559 - info.verbose = verbose; 560 537 info.found = 0; 561 538 info.params = params; 562 539 ··· 611 590 if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | 612 591 EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | 613 592 EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | 614 - EFI_MEMORY_RUNTIME)) 593 + EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE)) 615 594 snprintf(pos, size, "|attr=0x%016llx]", 616 595 (unsigned long long)attr); 617 596 else 618 - snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", 597 + snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", 619 598 attr & EFI_MEMORY_RUNTIME ? "RUN" : "", 599 + attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", 620 600 attr & EFI_MEMORY_XP ? "XP" : "", 621 601 attr & EFI_MEMORY_RP ? "RP" : "", 622 602 attr & EFI_MEMORY_WP ? "WP" : "",
+3 -16
drivers/firmware/efi/esrt.c
··· 20 20 #include <linux/kobject.h> 21 21 #include <linux/list.h> 22 22 #include <linux/memblock.h> 23 - #include <linux/module.h> 24 23 #include <linux/slab.h> 25 24 #include <linux/types.h> 26 25 ··· 449 450 esrt = NULL; 450 451 return error; 451 452 } 453 + device_initcall(esrt_sysfs_init); 452 454 453 - static void __exit esrt_sysfs_exit(void) 454 - { 455 - pr_debug("esrt-sysfs: unloading.\n"); 456 - cleanup_entry_list(); 457 - kset_unregister(esrt_kset); 458 - sysfs_remove_group(esrt_kobj, &esrt_attr_group); 459 - kfree(esrt); 460 - esrt = NULL; 461 - kobject_del(esrt_kobj); 462 - kobject_put(esrt_kobj); 463 - } 464 - 465 - module_init(esrt_sysfs_init); 466 - module_exit(esrt_sysfs_exit); 467 - 455 + /* 468 456 MODULE_AUTHOR("Peter Jones <pjones@redhat.com>"); 469 457 MODULE_DESCRIPTION("EFI System Resource Table support"); 470 458 MODULE_LICENSE("GPL"); 459 + */
+238
drivers/firmware/efi/fake_mem.c
··· 1 + /* 2 + * fake_mem.c 3 + * 4 + * Copyright (C) 2015 FUJITSU LIMITED 5 + * Author: Taku Izumi <izumi.taku@jp.fujitsu.com> 6 + * 7 + * This code introduces new boot option named "efi_fake_mem" 8 + * By specifying this parameter, you can add arbitrary attribute to 9 + * specific memory range by updating original (firmware provided) EFI 10 + * memmap. 11 + * 12 + * This program is free software; you can redistribute it and/or modify it 13 + * under the terms and conditions of the GNU General Public License, 14 + * version 2, as published by the Free Software Foundation. 15 + * 16 + * This program is distributed in the hope it will be useful, but WITHOUT 17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19 + * more details. 20 + * 21 + * You should have received a copy of the GNU General Public License along with 22 + * this program; if not, see <http://www.gnu.org/licenses/>. 23 + * 24 + * The full GNU General Public License is included in this distribution in 25 + * the file called "COPYING". 26 + */ 27 + 28 + #include <linux/kernel.h> 29 + #include <linux/efi.h> 30 + #include <linux/init.h> 31 + #include <linux/memblock.h> 32 + #include <linux/types.h> 33 + #include <linux/sort.h> 34 + #include <asm/efi.h> 35 + 36 + #define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM 37 + 38 + struct fake_mem { 39 + struct range range; 40 + u64 attribute; 41 + }; 42 + static struct fake_mem fake_mems[EFI_MAX_FAKEMEM]; 43 + static int nr_fake_mem; 44 + 45 + static int __init cmp_fake_mem(const void *x1, const void *x2) 46 + { 47 + const struct fake_mem *m1 = x1; 48 + const struct fake_mem *m2 = x2; 49 + 50 + if (m1->range.start < m2->range.start) 51 + return -1; 52 + if (m1->range.start > m2->range.start) 53 + return 1; 54 + return 0; 55 + } 56 + 57 + void __init efi_fake_memmap(void) 58 + { 59 + u64 start, end, m_start, m_end, m_attr; 60 + int new_nr_map = memmap.nr_map; 61 + efi_memory_desc_t *md; 62 + u64 new_memmap_phy; 63 + void *new_memmap; 64 + void *old, *new; 65 + int i; 66 + 67 + if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP)) 68 + return; 69 + 70 + /* count up the number of EFI memory descriptor */ 71 + for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) { 72 + md = old; 73 + start = md->phys_addr; 74 + end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; 75 + 76 + for (i = 0; i < nr_fake_mem; i++) { 77 + /* modifying range */ 78 + m_start = fake_mems[i].range.start; 79 + m_end = fake_mems[i].range.end; 80 + 81 + if (m_start <= start) { 82 + /* split into 2 parts */ 83 + if (start < m_end && m_end < end) 84 + new_nr_map++; 85 + } 86 + if (start < m_start && m_start < end) { 87 + /* split into 3 parts */ 88 + if (m_end < end) 89 + new_nr_map += 2; 90 + /* split into 2 parts */ 91 + if (end <= m_end) 92 + new_nr_map++; 93 + } 94 + } 95 + } 96 + 97 + /* allocate memory for new EFI memmap */ 98 + new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map, 99 + PAGE_SIZE); 100 + if (!new_memmap_phy) 101 + return; 102 + 103 + /* create new EFI memmap */ 104 + new_memmap = early_memremap(new_memmap_phy, 105 + memmap.desc_size * new_nr_map); 106 + if (!new_memmap) { 107 + memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map); 108 + return; 109 + } 110 + 111 + for (old = memmap.map, new = new_memmap; 112 + old < memmap.map_end; 113 + old += memmap.desc_size, new += memmap.desc_size) { 114 + 115 + /* copy original EFI memory descriptor */ 116 + memcpy(new, old, memmap.desc_size); 117 + md = new; 118 + start = md->phys_addr; 119 + end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; 120 + 121 + for (i = 0; i < nr_fake_mem; i++) { 122 + /* modifying range */ 123 + m_start = fake_mems[i].range.start; 124 + m_end = fake_mems[i].range.end; 125 + m_attr = fake_mems[i].attribute; 126 + 127 + if (m_start <= start && end <= m_end) 128 + md->attribute |= m_attr; 129 + 130 + if (m_start <= start && 131 + (start < m_end && m_end < end)) { 132 + /* first part */ 133 + md->attribute |= m_attr; 134 + md->num_pages = (m_end - md->phys_addr + 1) >> 135 + EFI_PAGE_SHIFT; 136 + /* latter part */ 137 + new += memmap.desc_size; 138 + memcpy(new, old, memmap.desc_size); 139 + md = new; 140 + md->phys_addr = m_end + 1; 141 + md->num_pages = (end - md->phys_addr + 1) >> 142 + EFI_PAGE_SHIFT; 143 + } 144 + 145 + if ((start < m_start && m_start < end) && m_end < end) { 146 + /* first part */ 147 + md->num_pages = (m_start - md->phys_addr) >> 148 + EFI_PAGE_SHIFT; 149 + /* middle part */ 150 + new += memmap.desc_size; 151 + memcpy(new, old, memmap.desc_size); 152 + md = new; 153 + md->attribute |= m_attr; 154 + md->phys_addr = m_start; 155 + md->num_pages = (m_end - m_start + 1) >> 156 + EFI_PAGE_SHIFT; 157 + /* last part */ 158 + new += memmap.desc_size; 159 + memcpy(new, old, memmap.desc_size); 160 + md = new; 161 + md->phys_addr = m_end + 1; 162 + md->num_pages = (end - m_end) >> 163 + EFI_PAGE_SHIFT; 164 + } 165 + 166 + if ((start < m_start && m_start < end) && 167 + (end <= m_end)) { 168 + /* first part */ 169 + md->num_pages = (m_start - md->phys_addr) >> 170 + EFI_PAGE_SHIFT; 171 + /* latter part */ 172 + new += memmap.desc_size; 173 + memcpy(new, old, memmap.desc_size); 174 + md = new; 175 + md->phys_addr = m_start; 176 + md->num_pages = (end - md->phys_addr + 1) >> 177 + EFI_PAGE_SHIFT; 178 + md->attribute |= m_attr; 179 + } 180 + } 181 + } 182 + 183 + /* swap into new EFI memmap */ 184 + efi_unmap_memmap(); 185 + memmap.map = new_memmap; 186 + memmap.phys_map = (void *)new_memmap_phy; 187 + memmap.nr_map = new_nr_map; 188 + memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size; 189 + set_bit(EFI_MEMMAP, &efi.flags); 190 + 191 + /* print new EFI memmap */ 192 + efi_print_memmap(); 193 + } 194 + 195 + static int __init setup_fake_mem(char *p) 196 + { 197 + u64 start = 0, mem_size = 0, attribute = 0; 198 + int i; 199 + 200 + if (!p) 201 + return -EINVAL; 202 + 203 + while (*p != '\0') { 204 + mem_size = memparse(p, &p); 205 + if (*p == '@') 206 + start = memparse(p+1, &p); 207 + else 208 + break; 209 + 210 + if (*p == ':') 211 + attribute = simple_strtoull(p+1, &p, 0); 212 + else 213 + break; 214 + 215 + if (nr_fake_mem >= EFI_MAX_FAKEMEM) 216 + break; 217 + 218 + fake_mems[nr_fake_mem].range.start = start; 219 + fake_mems[nr_fake_mem].range.end = start + mem_size - 1; 220 + fake_mems[nr_fake_mem].attribute = attribute; 221 + nr_fake_mem++; 222 + 223 + if (*p == ',') 224 + p++; 225 + } 226 + 227 + sort(fake_mems, nr_fake_mem, sizeof(struct fake_mem), 228 + cmp_fake_mem, NULL); 229 + 230 + for (i = 0; i < nr_fake_mem; i++) 231 + pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]", 232 + fake_mems[i].attribute, fake_mems[i].range.start, 233 + fake_mems[i].range.end); 234 + 235 + return *p == '\0' ? 0 : -EINVAL; 236 + } 237 + 238 + early_param("efi_fake_mem", setup_fake_mem);
+23 -1
drivers/video/fbdev/efifb.c
··· 114 114 return 0; 115 115 } 116 116 117 + static inline bool fb_base_is_valid(void) 118 + { 119 + if (screen_info.lfb_base) 120 + return true; 121 + 122 + if (!(screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)) 123 + return false; 124 + 125 + if (screen_info.ext_lfb_base) 126 + return true; 127 + 128 + return false; 129 + } 130 + 117 131 static int efifb_probe(struct platform_device *dev) 118 132 { 119 133 struct fb_info *info; ··· 155 141 screen_info.lfb_depth = 32; 156 142 if (!screen_info.pages) 157 143 screen_info.pages = 1; 158 - if (!screen_info.lfb_base) { 144 + if (!fb_base_is_valid()) { 159 145 printk(KERN_DEBUG "efifb: invalid framebuffer address\n"); 160 146 return -ENODEV; 161 147 } ··· 174 160 } 175 161 176 162 efifb_fix.smem_start = screen_info.lfb_base; 163 + 164 + if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) { 165 + u64 ext_lfb_base; 166 + 167 + ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32; 168 + efifb_fix.smem_start |= ext_lfb_base; 169 + } 170 + 177 171 efifb_defined.bits_per_pixel = screen_info.lfb_depth; 178 172 efifb_defined.xres = screen_info.lfb_width; 179 173 efifb_defined.yres = screen_info.lfb_height;
+21 -1
include/linux/efi.h
··· 596 596 #define DEVICE_TREE_GUID \ 597 597 EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 ) 598 598 599 + #define EFI_PROPERTIES_TABLE_GUID \ 600 + EFI_GUID( 0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5 ) 601 + 599 602 typedef struct { 600 603 efi_guid_t guid; 601 604 u64 table; ··· 812 809 #define EFI_FILE_MODE_WRITE 0x0000000000000002 813 810 #define EFI_FILE_MODE_CREATE 0x8000000000000000 814 811 812 + typedef struct { 813 + u32 version; 814 + u32 length; 815 + u64 memory_protection_attribute; 816 + } efi_properties_table_t; 817 + 818 + #define EFI_PROPERTIES_TABLE_VERSION 0x00010000 819 + #define EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA 0x1 820 + 815 821 #define EFI_INVALID_TABLE_ADDR (~0UL) 816 822 817 823 /* ··· 843 831 unsigned long runtime; /* runtime table */ 844 832 unsigned long config_table; /* config tables */ 845 833 unsigned long esrt; /* ESRT table */ 834 + unsigned long properties_table; /* properties table */ 846 835 efi_get_time_t *get_time; 847 836 efi_set_time_t *set_time; 848 837 efi_get_wakeup_time_t *get_wakeup_time; ··· 915 902 struct resource *data_resource, struct resource *bss_resource); 916 903 extern void efi_get_time(struct timespec *now); 917 904 extern void efi_reserve_boot_services(void); 918 - extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); 905 + extern int efi_get_fdt_params(struct efi_fdt_params *params); 919 906 extern struct efi_memory_map memmap; 920 907 extern struct kobject *efi_kobj; 921 908 922 909 extern int efi_reboot_quirk_mode; 923 910 extern bool efi_poweroff_required(void); 911 + 912 + #ifdef CONFIG_EFI_FAKE_MEMMAP 913 + extern void __init efi_fake_memmap(void); 914 + #else 915 + static inline void efi_fake_memmap(void) { } 916 + #endif 924 917 925 918 /* Iterate through an efi_memory_map */ 926 919 #define for_each_efi_memory_desc(m, md) \ ··· 979 960 #define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ 980 961 #define EFI_ARCH_1 7 /* First arch-specific bit */ 981 962 #define EFI_DBG 8 /* Print additional debug info at runtime */ 963 + #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */ 982 964 983 965 #ifdef CONFIG_EFI 984 966 /*
+3 -2
include/uapi/linux/screen_info.h
··· 43 43 __u16 pages; /* 0x32 */ 44 44 __u16 vesa_attributes; /* 0x34 */ 45 45 __u32 capabilities; /* 0x36 */ 46 - __u8 _reserved[6]; /* 0x3a */ 46 + __u32 ext_lfb_base; /* 0x3a */ 47 + __u8 _reserved[2]; /* 0x3e */ 47 48 } __attribute__((packed)); 48 49 49 50 #define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ ··· 70 69 #define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */ 71 70 72 71 #define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0) 73 - 72 + #define VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */ 74 73 75 74 #endif /* _UAPI_SCREEN_INFO_H */