diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 13:22:30 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-13 13:22:30 -0400 |
| commit | 9c65e12a55fea2da50f4069ec0dc47c50b7bd2bb (patch) | |
| tree | e371d6da040aaf8b56f060dd25a19b918229927e | |
| parent | 67dbb3a099d0fe04df5974edddc0b8c64a9f7529 (diff) | |
| parent | 84a87c628a12f95d8b0c86cc7b8edb28ea5edf90 (diff) | |
Merge branch 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI update from Ingo Molnar:
"This tree includes various fixes, cleanups, a new efi=debug boot
option and EFI boot stub memory allocation optimizations"
* 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi/libstub: Retrieve FDT size when loaded from UEFI config table
efi: Clean up the efi_call_phys_[prolog|epilog]() save/restore interaction
efi: Disable interrupts around EFI calls, not in the epilog/prolog calls
x86/efi: Add a "debug" option to the efi= cmdline
firmware: dmi_scan: Use direct access to static vars
firmware: dmi_scan: Use full dmi version for SMBIOS3
| -rw-r--r-- | Documentation/kernel-parameters.txt | 3 | ||||
| -rw-r--r-- | arch/x86/include/asm/efi.h | 6 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 17 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_32.c | 22 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi_64.c | 29 | ||||
| -rw-r--r-- | drivers/firmware/dmi_scan.c | 38 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 7 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 2 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/fdt.c | 7 | ||||
| -rw-r--r-- | include/linux/efi.h | 1 |
10 files changed, 79 insertions, 53 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index bfcb1a62a7b4..01aa47d3b6ab 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1036,7 +1036,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 1036 | Format: {"off" | "on" | "skip[mbr]"} | 1036 | Format: {"off" | "on" | "skip[mbr]"} |
| 1037 | 1037 | ||
| 1038 | efi= [EFI] | 1038 | efi= [EFI] |
| 1039 | Format: { "old_map", "nochunk", "noruntime" } | 1039 | Format: { "old_map", "nochunk", "noruntime", "debug" } |
| 1040 | old_map [X86-64]: switch to the old ioremap-based EFI | 1040 | old_map [X86-64]: switch to the old ioremap-based EFI |
| 1041 | runtime services mapping. 32-bit still uses this one by | 1041 | runtime services mapping. 32-bit still uses this one by |
| 1042 | default. | 1042 | default. |
| @@ -1044,6 +1044,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 1044 | boot stub, as chunking can cause problems with some | 1044 | boot stub, as chunking can cause problems with some |
| 1045 | firmware implementations. | 1045 | firmware implementations. |
| 1046 | noruntime : disable EFI runtime services support | 1046 | noruntime : disable EFI runtime services support |
| 1047 | debug: enable misc debug output | ||
| 1047 | 1048 | ||
| 1048 | efi_no_storage_paranoia [EFI; X86] | 1049 | efi_no_storage_paranoia [EFI; X86] |
| 1049 | Using this parameter you can use more than 50% of | 1050 | Using this parameter you can use more than 50% of |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 25bce45c6fc4..3738b138b843 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #define _ASM_X86_EFI_H | 2 | #define _ASM_X86_EFI_H |
| 3 | 3 | ||
| 4 | #include <asm/i387.h> | 4 | #include <asm/i387.h> |
| 5 | #include <asm/pgtable.h> | ||
| 6 | |||
| 5 | /* | 7 | /* |
| 6 | * We map the EFI regions needed for runtime services non-contiguously, | 8 | * We map the EFI regions needed for runtime services non-contiguously, |
| 7 | * with preserved alignment on virtual addresses starting from -4G down | 9 | * with preserved alignment on virtual addresses starting from -4G down |
| @@ -89,8 +91,8 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size, | |||
| 89 | extern struct efi_scratch efi_scratch; | 91 | extern struct efi_scratch efi_scratch; |
| 90 | extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable); | 92 | extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable); |
| 91 | extern int __init efi_memblock_x86_reserve_range(void); | 93 | extern int __init efi_memblock_x86_reserve_range(void); |
| 92 | extern void __init efi_call_phys_prolog(void); | 94 | extern pgd_t * __init efi_call_phys_prolog(void); |
| 93 | extern void __init efi_call_phys_epilog(void); | 95 | extern void __init efi_call_phys_epilog(pgd_t *save_pgd); |
| 94 | extern void __init efi_unmap_memmap(void); | 96 | extern void __init efi_unmap_memmap(void); |
| 95 | extern void __init efi_memory_uc(u64 addr, unsigned long size); | 97 | extern void __init efi_memory_uc(u64 addr, unsigned long size); |
| 96 | extern void __init efi_map_region(efi_memory_desc_t *md); | 98 | extern void __init efi_map_region(efi_memory_desc_t *md); |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index dbc8627a5cdf..02744df576d5 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
| @@ -85,12 +85,20 @@ static efi_status_t __init phys_efi_set_virtual_address_map( | |||
| 85 | efi_memory_desc_t *virtual_map) | 85 | efi_memory_desc_t *virtual_map) |
| 86 | { | 86 | { |
| 87 | efi_status_t status; | 87 | efi_status_t status; |
| 88 | unsigned long flags; | ||
| 89 | pgd_t *save_pgd; | ||
| 88 | 90 | ||
| 89 | efi_call_phys_prolog(); | 91 | save_pgd = efi_call_phys_prolog(); |
| 92 | |||
| 93 | /* Disable interrupts around EFI calls: */ | ||
| 94 | local_irq_save(flags); | ||
| 90 | status = efi_call_phys(efi_phys.set_virtual_address_map, | 95 | status = efi_call_phys(efi_phys.set_virtual_address_map, |
| 91 | memory_map_size, descriptor_size, | 96 | memory_map_size, descriptor_size, |
| 92 | descriptor_version, virtual_map); | 97 | descriptor_version, virtual_map); |
| 93 | efi_call_phys_epilog(); | 98 | local_irq_restore(flags); |
| 99 | |||
| 100 | efi_call_phys_epilog(save_pgd); | ||
| 101 | |||
| 94 | return status; | 102 | return status; |
| 95 | } | 103 | } |
| 96 | 104 | ||
| @@ -491,7 +499,8 @@ void __init efi_init(void) | |||
| 491 | if (efi_memmap_init()) | 499 | if (efi_memmap_init()) |
| 492 | return; | 500 | return; |
| 493 | 501 | ||
| 494 | print_efi_memmap(); | 502 | if (efi_enabled(EFI_DBG)) |
| 503 | print_efi_memmap(); | ||
| 495 | } | 504 | } |
| 496 | 505 | ||
| 497 | void __init efi_late_init(void) | 506 | void __init efi_late_init(void) |
| @@ -939,6 +948,8 @@ static int __init arch_parse_efi_cmdline(char *str) | |||
| 939 | { | 948 | { |
| 940 | if (parse_option_str(str, "old_map")) | 949 | if (parse_option_str(str, "old_map")) |
| 941 | set_bit(EFI_OLD_MEMMAP, &efi.flags); | 950 | set_bit(EFI_OLD_MEMMAP, &efi.flags); |
| 951 | if (parse_option_str(str, "debug")) | ||
| 952 | set_bit(EFI_DBG, &efi.flags); | ||
| 942 | 953 | ||
| 943 | return 0; | 954 | return 0; |
| 944 | } | 955 | } |
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 40e7cda52936..ed5b67338294 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c | |||
| @@ -33,11 +33,10 @@ | |||
| 33 | 33 | ||
| 34 | /* | 34 | /* |
| 35 | * To make EFI call EFI runtime service in physical addressing mode we need | 35 | * To make EFI call EFI runtime service in physical addressing mode we need |
| 36 | * prolog/epilog before/after the invocation to disable interrupt, to | 36 | * prolog/epilog before/after the invocation to claim the EFI runtime service |
| 37 | * claim EFI runtime service handler exclusively and to duplicate a memory in | 37 | * handler exclusively and to duplicate a memory mapping in low memory space, |
| 38 | * low memory space say 0 - 3G. | 38 | * say 0 - 3G. |
| 39 | */ | 39 | */ |
| 40 | static unsigned long efi_rt_eflags; | ||
| 41 | 40 | ||
| 42 | void efi_sync_low_kernel_mappings(void) {} | 41 | void efi_sync_low_kernel_mappings(void) {} |
| 43 | void __init efi_dump_pagetable(void) {} | 42 | void __init efi_dump_pagetable(void) {} |
| @@ -57,21 +56,24 @@ void __init efi_map_region(efi_memory_desc_t *md) | |||
| 57 | void __init efi_map_region_fixed(efi_memory_desc_t *md) {} | 56 | void __init efi_map_region_fixed(efi_memory_desc_t *md) {} |
| 58 | void __init parse_efi_setup(u64 phys_addr, u32 data_len) {} | 57 | void __init parse_efi_setup(u64 phys_addr, u32 data_len) {} |
| 59 | 58 | ||
| 60 | void __init efi_call_phys_prolog(void) | 59 | pgd_t * __init efi_call_phys_prolog(void) |
| 61 | { | 60 | { |
| 62 | struct desc_ptr gdt_descr; | 61 | struct desc_ptr gdt_descr; |
| 62 | pgd_t *save_pgd; | ||
| 63 | 63 | ||
| 64 | local_irq_save(efi_rt_eflags); | 64 | /* Current pgd is swapper_pg_dir, we'll restore it later: */ |
| 65 | 65 | save_pgd = swapper_pg_dir; | |
| 66 | load_cr3(initial_page_table); | 66 | load_cr3(initial_page_table); |
| 67 | __flush_tlb_all(); | 67 | __flush_tlb_all(); |
| 68 | 68 | ||
| 69 | gdt_descr.address = __pa(get_cpu_gdt_table(0)); | 69 | gdt_descr.address = __pa(get_cpu_gdt_table(0)); |
| 70 | gdt_descr.size = GDT_SIZE - 1; | 70 | gdt_descr.size = GDT_SIZE - 1; |
| 71 | load_gdt(&gdt_descr); | 71 | load_gdt(&gdt_descr); |
| 72 | |||
| 73 | return save_pgd; | ||
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | void __init efi_call_phys_epilog(void) | 76 | void __init efi_call_phys_epilog(pgd_t *save_pgd) |
| 75 | { | 77 | { |
| 76 | struct desc_ptr gdt_descr; | 78 | struct desc_ptr gdt_descr; |
| 77 | 79 | ||
| @@ -79,10 +81,8 @@ void __init efi_call_phys_epilog(void) | |||
| 79 | gdt_descr.size = GDT_SIZE - 1; | 81 | gdt_descr.size = GDT_SIZE - 1; |
| 80 | load_gdt(&gdt_descr); | 82 | load_gdt(&gdt_descr); |
| 81 | 83 | ||
| 82 | load_cr3(swapper_pg_dir); | 84 | load_cr3(save_pgd); |
| 83 | __flush_tlb_all(); | 85 | __flush_tlb_all(); |
| 84 | |||
| 85 | local_irq_restore(efi_rt_eflags); | ||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | void __init efi_runtime_mkexec(void) | 88 | void __init efi_runtime_mkexec(void) |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 17e80d829df0..a0ac0f9c307f 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
| @@ -41,9 +41,6 @@ | |||
| 41 | #include <asm/realmode.h> | 41 | #include <asm/realmode.h> |
| 42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
| 43 | 43 | ||
| 44 | static pgd_t *save_pgd __initdata; | ||
| 45 | static unsigned long efi_flags __initdata; | ||
| 46 | |||
| 47 | /* | 44 | /* |
| 48 | * We allocate runtime services regions bottom-up, starting from -4G, i.e. | 45 | * We allocate runtime services regions bottom-up, starting from -4G, i.e. |
| 49 | * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. | 46 | * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G. |
| @@ -78,17 +75,18 @@ static void __init early_code_mapping_set_exec(int executable) | |||
| 78 | } | 75 | } |
| 79 | } | 76 | } |
| 80 | 77 | ||
| 81 | void __init efi_call_phys_prolog(void) | 78 | pgd_t * __init efi_call_phys_prolog(void) |
| 82 | { | 79 | { |
| 83 | unsigned long vaddress; | 80 | unsigned long vaddress; |
| 81 | pgd_t *save_pgd; | ||
| 82 | |||
| 84 | int pgd; | 83 | int pgd; |
| 85 | int n_pgds; | 84 | int n_pgds; |
| 86 | 85 | ||
| 87 | if (!efi_enabled(EFI_OLD_MEMMAP)) | 86 | if (!efi_enabled(EFI_OLD_MEMMAP)) |
| 88 | return; | 87 | return NULL; |
| 89 | 88 | ||
| 90 | early_code_mapping_set_exec(1); | 89 | early_code_mapping_set_exec(1); |
| 91 | local_irq_save(efi_flags); | ||
| 92 | 90 | ||
| 93 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); | 91 | n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); |
| 94 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); | 92 | save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); |
| @@ -99,24 +97,29 @@ void __init efi_call_phys_prolog(void) | |||
| 99 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); | 97 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); |
| 100 | } | 98 | } |
| 101 | __flush_tlb_all(); | 99 | __flush_tlb_all(); |
| 100 | |||
| 101 | return save_pgd; | ||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void __init efi_call_phys_epilog(void) | 104 | void __init efi_call_phys_epilog(pgd_t *save_pgd) |
| 105 | { | 105 | { |
| 106 | /* | 106 | /* |
| 107 | * After the lock is released, the original page table is restored. | 107 | * After the lock is released, the original page table is restored. |
| 108 | */ | 108 | */ |
| 109 | int pgd; | 109 | int pgd_idx; |
| 110 | int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); | 110 | int nr_pgds; |
| 111 | 111 | ||
| 112 | if (!efi_enabled(EFI_OLD_MEMMAP)) | 112 | if (!save_pgd) |
| 113 | return; | 113 | return; |
| 114 | 114 | ||
| 115 | for (pgd = 0; pgd < n_pgds; pgd++) | 115 | nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); |
| 116 | set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); | 116 | |
| 117 | for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) | ||
| 118 | set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); | ||
| 119 | |||
| 117 | kfree(save_pgd); | 120 | kfree(save_pgd); |
| 121 | |||
| 118 | __flush_tlb_all(); | 122 | __flush_tlb_all(); |
| 119 | local_irq_restore(efi_flags); | ||
| 120 | early_code_mapping_set_exec(0); | 123 | early_code_mapping_set_exec(0); |
| 121 | } | 124 | } |
| 122 | 125 | ||
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 2eebd28b4c40..6e45a43ffe84 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -17,7 +17,9 @@ | |||
| 17 | */ | 17 | */ |
| 18 | static const char dmi_empty_string[] = " "; | 18 | static const char dmi_empty_string[] = " "; |
| 19 | 19 | ||
| 20 | static u16 __initdata dmi_ver; | 20 | static u32 dmi_ver __initdata; |
| 21 | static u32 dmi_len; | ||
| 22 | static u16 dmi_num; | ||
| 21 | /* | 23 | /* |
| 22 | * Catch too early calls to dmi_check_system(): | 24 | * Catch too early calls to dmi_check_system(): |
| 23 | */ | 25 | */ |
| @@ -78,7 +80,7 @@ static const char * __init dmi_string(const struct dmi_header *dm, u8 s) | |||
| 78 | * We have to be cautious here. We have seen BIOSes with DMI pointers | 80 | * We have to be cautious here. We have seen BIOSes with DMI pointers |
| 79 | * pointing to completely the wrong place for example | 81 | * pointing to completely the wrong place for example |
| 80 | */ | 82 | */ |
| 81 | static void dmi_table(u8 *buf, u32 len, int num, | 83 | static void dmi_table(u8 *buf, |
| 82 | void (*decode)(const struct dmi_header *, void *), | 84 | void (*decode)(const struct dmi_header *, void *), |
| 83 | void *private_data) | 85 | void *private_data) |
| 84 | { | 86 | { |
| @@ -91,8 +93,8 @@ static void dmi_table(u8 *buf, u32 len, int num, | |||
| 91 | * off the end of the table (should never happen but sometimes does | 93 | * off the end of the table (should never happen but sometimes does |
| 92 | * on bogus implementations.) | 94 | * on bogus implementations.) |
| 93 | */ | 95 | */ |
| 94 | while ((!num || i < num) && | 96 | while ((!dmi_num || i < dmi_num) && |
| 95 | (data - buf + sizeof(struct dmi_header)) <= len) { | 97 | (data - buf + sizeof(struct dmi_header)) <= dmi_len) { |
| 96 | const struct dmi_header *dm = (const struct dmi_header *)data; | 98 | const struct dmi_header *dm = (const struct dmi_header *)data; |
| 97 | 99 | ||
| 98 | /* | 100 | /* |
| @@ -101,9 +103,9 @@ static void dmi_table(u8 *buf, u32 len, int num, | |||
| 101 | * table in dmi_decode or dmi_string | 103 | * table in dmi_decode or dmi_string |
| 102 | */ | 104 | */ |
| 103 | data += dm->length; | 105 | data += dm->length; |
| 104 | while ((data - buf < len - 1) && (data[0] || data[1])) | 106 | while ((data - buf < dmi_len - 1) && (data[0] || data[1])) |
| 105 | data++; | 107 | data++; |
| 106 | if (data - buf < len - 1) | 108 | if (data - buf < dmi_len - 1) |
| 107 | decode(dm, private_data); | 109 | decode(dm, private_data); |
| 108 | 110 | ||
| 109 | /* | 111 | /* |
| @@ -118,8 +120,6 @@ static void dmi_table(u8 *buf, u32 len, int num, | |||
| 118 | } | 120 | } |
| 119 | 121 | ||
| 120 | static phys_addr_t dmi_base; | 122 | static phys_addr_t dmi_base; |
| 121 | static u32 dmi_len; | ||
| 122 | static u16 dmi_num; | ||
| 123 | 123 | ||
| 124 | static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, | 124 | static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, |
| 125 | void *)) | 125 | void *)) |
| @@ -130,7 +130,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, | |||
| 130 | if (buf == NULL) | 130 | if (buf == NULL) |
| 131 | return -1; | 131 | return -1; |
| 132 | 132 | ||
| 133 | dmi_table(buf, dmi_len, dmi_num, decode, NULL); | 133 | dmi_table(buf, decode, NULL); |
| 134 | 134 | ||
| 135 | add_device_randomness(buf, dmi_len); | 135 | add_device_randomness(buf, dmi_len); |
| 136 | 136 | ||
| @@ -201,7 +201,7 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, | |||
| 201 | * the UUID are supposed to be little-endian encoded. The specification | 201 | * the UUID are supposed to be little-endian encoded. The specification |
| 202 | * says that this is the defacto standard. | 202 | * says that this is the defacto standard. |
| 203 | */ | 203 | */ |
| 204 | if (dmi_ver >= 0x0206) | 204 | if (dmi_ver >= 0x020600) |
| 205 | sprintf(s, "%pUL", d); | 205 | sprintf(s, "%pUL", d); |
| 206 | else | 206 | else |
| 207 | sprintf(s, "%pUB", d); | 207 | sprintf(s, "%pUB", d); |
| @@ -473,7 +473,7 @@ static void __init dmi_format_ids(char *buf, size_t len) | |||
| 473 | */ | 473 | */ |
| 474 | static int __init dmi_present(const u8 *buf) | 474 | static int __init dmi_present(const u8 *buf) |
| 475 | { | 475 | { |
| 476 | int smbios_ver; | 476 | u32 smbios_ver; |
| 477 | 477 | ||
| 478 | if (memcmp(buf, "_SM_", 4) == 0 && | 478 | if (memcmp(buf, "_SM_", 4) == 0 && |
| 479 | buf[5] < 32 && dmi_checksum(buf, buf[5])) { | 479 | buf[5] < 32 && dmi_checksum(buf, buf[5])) { |
| @@ -506,14 +506,16 @@ static int __init dmi_present(const u8 *buf) | |||
| 506 | if (dmi_walk_early(dmi_decode) == 0) { | 506 | if (dmi_walk_early(dmi_decode) == 0) { |
| 507 | if (smbios_ver) { | 507 | if (smbios_ver) { |
| 508 | dmi_ver = smbios_ver; | 508 | dmi_ver = smbios_ver; |
| 509 | pr_info("SMBIOS %d.%d present.\n", | 509 | pr_info("SMBIOS %d.%d%s present.\n", |
| 510 | dmi_ver >> 8, dmi_ver & 0xFF); | 510 | dmi_ver >> 8, dmi_ver & 0xFF, |
| 511 | (dmi_ver < 0x0300) ? "" : ".x"); | ||
| 511 | } else { | 512 | } else { |
| 512 | dmi_ver = (buf[14] & 0xF0) << 4 | | 513 | dmi_ver = (buf[14] & 0xF0) << 4 | |
| 513 | (buf[14] & 0x0F); | 514 | (buf[14] & 0x0F); |
| 514 | pr_info("Legacy DMI %d.%d present.\n", | 515 | pr_info("Legacy DMI %d.%d present.\n", |
| 515 | dmi_ver >> 8, dmi_ver & 0xFF); | 516 | dmi_ver >> 8, dmi_ver & 0xFF); |
| 516 | } | 517 | } |
| 518 | dmi_ver <<= 8; | ||
| 517 | dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); | 519 | dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); |
| 518 | printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); | 520 | printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); |
| 519 | return 0; | 521 | return 0; |
| @@ -531,14 +533,16 @@ static int __init dmi_smbios3_present(const u8 *buf) | |||
| 531 | { | 533 | { |
| 532 | if (memcmp(buf, "_SM3_", 5) == 0 && | 534 | if (memcmp(buf, "_SM3_", 5) == 0 && |
| 533 | buf[6] < 32 && dmi_checksum(buf, buf[6])) { | 535 | buf[6] < 32 && dmi_checksum(buf, buf[6])) { |
| 534 | dmi_ver = get_unaligned_be16(buf + 7); | 536 | dmi_ver = get_unaligned_be32(buf + 6); |
| 537 | dmi_ver &= 0xFFFFFF; | ||
| 535 | dmi_num = 0; /* No longer specified */ | 538 | dmi_num = 0; /* No longer specified */ |
| 536 | dmi_len = get_unaligned_le32(buf + 12); | 539 | dmi_len = get_unaligned_le32(buf + 12); |
| 537 | dmi_base = get_unaligned_le64(buf + 16); | 540 | dmi_base = get_unaligned_le64(buf + 16); |
| 538 | 541 | ||
| 539 | if (dmi_walk_early(dmi_decode) == 0) { | 542 | if (dmi_walk_early(dmi_decode) == 0) { |
| 540 | pr_info("SMBIOS %d.%d present.\n", | 543 | pr_info("SMBIOS %d.%d.%d present.\n", |
| 541 | dmi_ver >> 8, dmi_ver & 0xFF); | 544 | dmi_ver >> 16, (dmi_ver >> 8) & 0xFF, |
| 545 | dmi_ver & 0xFF); | ||
| 542 | dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); | 546 | dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); |
| 543 | pr_debug("DMI: %s\n", dmi_ids_string); | 547 | pr_debug("DMI: %s\n", dmi_ids_string); |
| 544 | return 0; | 548 | return 0; |
| @@ -893,7 +897,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *), | |||
| 893 | if (buf == NULL) | 897 | if (buf == NULL) |
| 894 | return -1; | 898 | return -1; |
| 895 | 899 | ||
| 896 | dmi_table(buf, dmi_len, dmi_num, decode, private_data); | 900 | dmi_table(buf, decode, private_data); |
| 897 | 901 | ||
| 898 | dmi_unmap(buf); | 902 | dmi_unmap(buf); |
| 899 | return 0; | 903 | return 0; |
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index dcae482a9a17..e29560e6b40b 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
| @@ -175,7 +175,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
| 175 | unsigned long initrd_addr; | 175 | unsigned long initrd_addr; |
| 176 | u64 initrd_size = 0; | 176 | u64 initrd_size = 0; |
| 177 | unsigned long fdt_addr = 0; /* Original DTB */ | 177 | unsigned long fdt_addr = 0; /* Original DTB */ |
| 178 | u64 fdt_size = 0; /* We don't get size from configuration table */ | 178 | unsigned long fdt_size = 0; |
| 179 | char *cmdline_ptr = NULL; | 179 | char *cmdline_ptr = NULL; |
| 180 | int cmdline_size = 0; | 180 | int cmdline_size = 0; |
| 181 | unsigned long new_fdt_addr; | 181 | unsigned long new_fdt_addr; |
| @@ -239,8 +239,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
| 239 | } else { | 239 | } else { |
| 240 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, | 240 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, |
| 241 | "dtb=", | 241 | "dtb=", |
| 242 | ~0UL, (unsigned long *)&fdt_addr, | 242 | ~0UL, &fdt_addr, &fdt_size); |
| 243 | (unsigned long *)&fdt_size); | ||
| 244 | 243 | ||
| 245 | if (status != EFI_SUCCESS) { | 244 | if (status != EFI_SUCCESS) { |
| 246 | pr_efi_err(sys_table, "Failed to load device tree!\n"); | 245 | pr_efi_err(sys_table, "Failed to load device tree!\n"); |
| @@ -252,7 +251,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
| 252 | pr_efi(sys_table, "Using DTB from command line\n"); | 251 | pr_efi(sys_table, "Using DTB from command line\n"); |
| 253 | } else { | 252 | } else { |
| 254 | /* Look for a device tree configuration table entry. */ | 253 | /* Look for a device tree configuration table entry. */ |
| 255 | fdt_addr = (uintptr_t)get_fdt(sys_table); | 254 | fdt_addr = (uintptr_t)get_fdt(sys_table, &fdt_size); |
| 256 | if (fdt_addr) | 255 | if (fdt_addr) |
| 257 | pr_efi(sys_table, "Using DTB from configuration table\n"); | 256 | pr_efi(sys_table, "Using DTB from configuration table\n"); |
| 258 | } | 257 | } |
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 47437b16b186..e334a01cf92f 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h | |||
| @@ -41,7 +41,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | |||
| 41 | unsigned long fdt_addr, | 41 | unsigned long fdt_addr, |
| 42 | unsigned long fdt_size); | 42 | unsigned long fdt_size); |
| 43 | 43 | ||
| 44 | void *get_fdt(efi_system_table_t *sys_table); | 44 | void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size); |
| 45 | 45 | ||
| 46 | void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, | 46 | void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size, |
| 47 | unsigned long desc_size, efi_memory_desc_t *runtime_map, | 47 | unsigned long desc_size, efi_memory_desc_t *runtime_map, |
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 91da56c4fd54..ef5d764e2a27 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c | |||
| @@ -323,7 +323,7 @@ fail: | |||
| 323 | return EFI_LOAD_ERROR; | 323 | return EFI_LOAD_ERROR; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | void *get_fdt(efi_system_table_t *sys_table) | 326 | void *get_fdt(efi_system_table_t *sys_table, unsigned long *fdt_size) |
| 327 | { | 327 | { |
| 328 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; | 328 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; |
| 329 | efi_config_table_t *tables; | 329 | efi_config_table_t *tables; |
| @@ -336,6 +336,11 @@ void *get_fdt(efi_system_table_t *sys_table) | |||
| 336 | for (i = 0; i < sys_table->nr_tables; i++) | 336 | for (i = 0; i < sys_table->nr_tables; i++) |
| 337 | if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) { | 337 | if (efi_guidcmp(tables[i].guid, fdt_guid) == 0) { |
| 338 | fdt = (void *) tables[i].table; | 338 | fdt = (void *) tables[i].table; |
| 339 | if (fdt_check_header(fdt) != 0) { | ||
| 340 | pr_efi_err(sys_table, "Invalid header detected on UEFI supplied FDT, ignoring ...\n"); | ||
| 341 | return NULL; | ||
| 342 | } | ||
| 343 | *fdt_size = fdt_totalsize(fdt); | ||
| 339 | break; | 344 | break; |
| 340 | } | 345 | } |
| 341 | 346 | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index cf7e431cbc73..af5be0368dec 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
| @@ -942,6 +942,7 @@ extern int __init efi_setup_pcdp_console(char *); | |||
| 942 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ | 942 | #define EFI_64BIT 5 /* Is the firmware 64-bit? */ |
| 943 | #define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ | 943 | #define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ |
| 944 | #define EFI_ARCH_1 7 /* First arch-specific bit */ | 944 | #define EFI_ARCH_1 7 /* First arch-specific bit */ |
| 945 | #define EFI_DBG 8 /* Print additional debug info at runtime */ | ||
| 945 | 946 | ||
| 946 | #ifdef CONFIG_EFI | 947 | #ifdef CONFIG_EFI |
| 947 | /* | 948 | /* |
