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 | /* |