aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-12 13:03:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-12 13:03:44 -0500
commit3940cf0b3d3c6c5817bb86f61a02277cd33f953a (patch)
tree119b7a593a3422ac4d6e2e1fa762a8f817f71a35
parent9ad1aeecdbbf002637f0466e8935a3248d1843ad (diff)
parent018edcfac4c3b140366ad51b0907f3becb5bb624 (diff)
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar: "The main changes in this development cycle were: - Implement EFI dev path parser and other changes to fully support thunderbolt devices on Apple Macbooks (Lukas Wunner) - Add RNG seeding via the EFI stub, on ARM/arm64 (Ard Biesheuvel) - Expose EFI framebuffer configuration to user-space, to improve tooling (Peter Jones) - Misc fixes and cleanups (Ivan Hu, Wei Yongjun, Yisheng Xie, Dan Carpenter, Roy Franz)" * 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: efi/libstub: Make efi_random_alloc() allocate below 4 GB on 32-bit thunderbolt: Compile on x86 only thunderbolt, efi: Fix Kconfig dependencies harder thunderbolt, efi: Fix Kconfig dependencies thunderbolt: Use Device ROM retrieved from EFI x86/efi: Retrieve and assign Apple device properties efi: Allow bitness-agnostic protocol calls efi: Add device path parser efi/arm*/libstub: Invoke EFI_RNG_PROTOCOL to seed the UEFI RNG table efi/libstub: Add random.c to ARM build efi: Add support for seeding the RNG from a UEFI config table MAINTAINERS: Add ARM and arm64 EFI specific files to EFI subsystem efi/libstub: Fix allocation size calculations efi/efivar_ssdt_load: Don't return success on allocation failure efifb: Show framebuffer layout as device attributes efi/efi_test: Use memdup_user() as a cleanup efi/efi_test: Fix uninitialized variable 'rv' efi/efi_test: Fix uninitialized variable 'datasize' efi/arm*: Fix efi_init() error handling efi: Remove unused include of <linux/version.h>
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--MAINTAINERS6
-rw-r--r--arch/arm/include/asm/efi.h3
-rw-r--r--arch/arm64/include/asm/efi.h3
-rw-r--r--arch/x86/boot/compressed/eboot.c65
-rw-r--r--arch/x86/include/asm/efi.h16
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h1
-rw-r--r--drivers/firmware/efi/Kconfig18
-rw-r--r--drivers/firmware/efi/Makefile2
-rw-r--r--drivers/firmware/efi/apple-properties.c248
-rw-r--r--drivers/firmware/efi/arm-init.c4
-rw-r--r--drivers/firmware/efi/dev-path-parser.c203
-rw-r--r--drivers/firmware/efi/efi.c76
-rw-r--r--drivers/firmware/efi/libstub/Makefile4
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c2
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c33
-rw-r--r--drivers/firmware/efi/libstub/efistub.h11
-rw-r--r--drivers/firmware/efi/libstub/random.c67
-rw-r--r--drivers/firmware/efi/test/efi_test.c15
-rw-r--r--drivers/thunderbolt/Kconfig2
-rw-r--r--drivers/thunderbolt/eeprom.c43
-rw-r--r--drivers/thunderbolt/switch.c2
-rw-r--r--drivers/video/fbdev/efifb.c59
-rw-r--r--include/linux/efi.h46
24 files changed, 872 insertions, 62 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 37babf91f2cb..86a31dfc036e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1062,6 +1062,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1062 1062
1063 dscc4.setup= [NET] 1063 dscc4.setup= [NET]
1064 1064
1065 dump_apple_properties [X86]
1066 Dump name and content of EFI device properties on
1067 x86 Macs. Useful for driver authors to determine
1068 what data is available or for reverse-engineering.
1069
1065 dyndbg[="val"] [KNL,DYNAMIC_DEBUG] 1070 dyndbg[="val"] [KNL,DYNAMIC_DEBUG]
1066 module.dyndbg[="val"] 1071 module.dyndbg[="val"]
1067 Enable debug messages at boot time. See 1072 Enable debug messages at boot time. See
diff --git a/MAINTAINERS b/MAINTAINERS
index e2463baf33e5..cfbb164acd20 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4645,12 +4645,14 @@ L: linux-efi@vger.kernel.org
4645T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git 4645T: git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
4646S: Maintained 4646S: Maintained
4647F: Documentation/efi-stub.txt 4647F: Documentation/efi-stub.txt
4648F: arch/ia64/kernel/efi.c 4648F: arch/*/kernel/efi.c
4649F: arch/x86/boot/compressed/eboot.[ch] 4649F: arch/x86/boot/compressed/eboot.[ch]
4650F: arch/x86/include/asm/efi.h 4650F: arch/*/include/asm/efi.h
4651F: arch/x86/platform/efi/ 4651F: arch/x86/platform/efi/
4652F: drivers/firmware/efi/ 4652F: drivers/firmware/efi/
4653F: include/linux/efi*.h 4653F: include/linux/efi*.h
4654F: arch/arm/boot/compressed/efi-header.S
4655F: arch/arm64/kernel/efi-entry.S
4654 4656
4655EFI VARIABLE FILESYSTEM 4657EFI VARIABLE FILESYSTEM
4656M: Matthew Garrett <matthew.garrett@nebula.com> 4658M: Matthew Garrett <matthew.garrett@nebula.com>
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 766bf9b78160..0b06f5341b45 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -57,6 +57,9 @@ void efi_virtmap_unload(void);
57#define __efi_call_early(f, ...) f(__VA_ARGS__) 57#define __efi_call_early(f, ...) f(__VA_ARGS__)
58#define efi_is_64bit() (false) 58#define efi_is_64bit() (false)
59 59
60#define efi_call_proto(protocol, f, instance, ...) \
61 ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
62
60struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg); 63struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
61void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si); 64void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
62 65
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index a9e54aad15ef..771b3f0bc757 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -51,6 +51,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
51#define __efi_call_early(f, ...) f(__VA_ARGS__) 51#define __efi_call_early(f, ...) f(__VA_ARGS__)
52#define efi_is_64bit() (true) 52#define efi_is_64bit() (true)
53 53
54#define efi_call_proto(protocol, f, instance, ...) \
55 ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
56
54#define alloc_screen_info(x...) &screen_info 57#define alloc_screen_info(x...) &screen_info
55#define free_screen_info(x...) 58#define free_screen_info(x...)
56 59
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index cc69e37548db..ff01c8fc76f7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -537,6 +537,69 @@ free_handle:
537 efi_call_early(free_pool, pci_handle); 537 efi_call_early(free_pool, pci_handle);
538} 538}
539 539
540static void retrieve_apple_device_properties(struct boot_params *boot_params)
541{
542 efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
543 struct setup_data *data, *new;
544 efi_status_t status;
545 u32 size = 0;
546 void *p;
547
548 status = efi_call_early(locate_protocol, &guid, NULL, &p);
549 if (status != EFI_SUCCESS)
550 return;
551
552 if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
553 efi_printk(sys_table, "Unsupported properties proto version\n");
554 return;
555 }
556
557 efi_call_proto(apple_properties_protocol, get_all, p, NULL, &size);
558 if (!size)
559 return;
560
561 do {
562 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
563 size + sizeof(struct setup_data), &new);
564 if (status != EFI_SUCCESS) {
565 efi_printk(sys_table,
566 "Failed to alloc mem for properties\n");
567 return;
568 }
569
570 status = efi_call_proto(apple_properties_protocol, get_all, p,
571 new->data, &size);
572
573 if (status == EFI_BUFFER_TOO_SMALL)
574 efi_call_early(free_pool, new);
575 } while (status == EFI_BUFFER_TOO_SMALL);
576
577 new->type = SETUP_APPLE_PROPERTIES;
578 new->len = size;
579 new->next = 0;
580
581 data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
582 if (!data)
583 boot_params->hdr.setup_data = (unsigned long)new;
584 else {
585 while (data->next)
586 data = (struct setup_data *)(unsigned long)data->next;
587 data->next = (unsigned long)new;
588 }
589}
590
591static void setup_quirks(struct boot_params *boot_params)
592{
593 efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
594 efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
595 efi_table_attr(efi_system_table, fw_vendor, sys_table);
596
597 if (!memcmp(fw_vendor, apple, sizeof(apple))) {
598 if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
599 retrieve_apple_device_properties(boot_params);
600 }
601}
602
540static efi_status_t 603static efi_status_t
541setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) 604setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
542{ 605{
@@ -1098,6 +1161,8 @@ struct boot_params *efi_main(struct efi_config *c,
1098 1161
1099 setup_efi_pci(boot_params); 1162 setup_efi_pci(boot_params);
1100 1163
1164 setup_quirks(boot_params);
1165
1101 status = efi_call_early(allocate_pool, EFI_LOADER_DATA, 1166 status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
1102 sizeof(*gdt), (void **)&gdt); 1167 sizeof(*gdt), (void **)&gdt);
1103 if (status != EFI_SUCCESS) { 1168 if (status != EFI_SUCCESS) {
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 389d700b961e..e99675b9c861 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -210,12 +210,18 @@ static inline bool efi_is_64bit(void)
210 return __efi_early()->is64; 210 return __efi_early()->is64;
211} 211}
212 212
213#define efi_table_attr(table, attr, instance) \
214 (efi_is_64bit() ? \
215 ((table##_64_t *)(unsigned long)instance)->attr : \
216 ((table##_32_t *)(unsigned long)instance)->attr)
217
218#define efi_call_proto(protocol, f, instance, ...) \
219 __efi_early()->call(efi_table_attr(protocol, f, instance), \
220 instance, ##__VA_ARGS__)
221
213#define efi_call_early(f, ...) \ 222#define efi_call_early(f, ...) \
214 __efi_early()->call(efi_is_64bit() ? \ 223 __efi_early()->call(efi_table_attr(efi_boot_services, f, \
215 ((efi_boot_services_64_t *)(unsigned long) \ 224 __efi_early()->boot_services), __VA_ARGS__)
216 __efi_early()->boot_services)->f : \
217 ((efi_boot_services_32_t *)(unsigned long) \
218 __efi_early()->boot_services)->f, __VA_ARGS__)
219 225
220#define __efi_call_early(f, ...) \ 226#define __efi_call_early(f, ...) \
221 __efi_early()->call((unsigned long)f, __VA_ARGS__); 227 __efi_early()->call((unsigned long)f, __VA_ARGS__);
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c18ce67495fa..b10bf319ed20 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -7,6 +7,7 @@
7#define SETUP_DTB 2 7#define SETUP_DTB 2
8#define SETUP_PCI 3 8#define SETUP_PCI 3
9#define SETUP_EFI 4 9#define SETUP_EFI 4
10#define SETUP_APPLE_PROPERTIES 5
10 11
11/* ram_size flags */ 12/* ram_size flags */
12#define RAMDISK_IMAGE_START_MASK 0x07FF 13#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index c981be17d3c0..2e78b0b96d74 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -129,7 +129,25 @@ config EFI_TEST
129 Say Y here to enable the runtime services support via /dev/efi_test. 129 Say Y here to enable the runtime services support via /dev/efi_test.
130 If unsure, say N. 130 If unsure, say N.
131 131
132config APPLE_PROPERTIES
133 bool "Apple Device Properties"
134 depends on EFI_STUB && X86
135 select EFI_DEV_PATH_PARSER
136 select UCS2_STRING
137 help
138 Retrieve properties from EFI on Apple Macs and assign them to
139 devices, allowing for improved support of Apple hardware.
140 Properties that would otherwise be missing include the
141 Thunderbolt Device ROM and GPU configuration data.
142
143 If unsure, say Y if you have a Mac. Otherwise N.
144
132endmenu 145endmenu
133 146
134config UEFI_CPER 147config UEFI_CPER
135 bool 148 bool
149
150config EFI_DEV_PATH_PARSER
151 bool
152 depends on ACPI
153 default n
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index c8a439f6d715..ad67342313ed 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -21,6 +21,8 @@ obj-$(CONFIG_EFI_STUB) += libstub/
21obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o 21obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
22obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o 22obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
23obj-$(CONFIG_EFI_TEST) += test/ 23obj-$(CONFIG_EFI_TEST) += test/
24obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
25obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
24 26
25arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o 27arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o
26obj-$(CONFIG_ARM) += $(arm-obj-y) 28obj-$(CONFIG_ARM) += $(arm-obj-y)
diff --git a/drivers/firmware/efi/apple-properties.c b/drivers/firmware/efi/apple-properties.c
new file mode 100644
index 000000000000..c473f4c5ca34
--- /dev/null
+++ b/drivers/firmware/efi/apple-properties.c
@@ -0,0 +1,248 @@
1/*
2 * apple-properties.c - EFI device properties on Macs
3 * Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License (version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define pr_fmt(fmt) "apple-properties: " fmt
19
20#include <linux/bootmem.h>
21#include <linux/dmi.h>
22#include <linux/efi.h>
23#include <linux/property.h>
24#include <linux/slab.h>
25#include <linux/ucs2_string.h>
26#include <asm/setup.h>
27
28static bool dump_properties __initdata;
29
30static int __init dump_properties_enable(char *arg)
31{
32 dump_properties = true;
33 return 0;
34}
35
36__setup("dump_apple_properties", dump_properties_enable);
37
38struct dev_header {
39 u32 len;
40 u32 prop_count;
41 struct efi_dev_path path[0];
42 /*
43 * followed by key/value pairs, each key and value preceded by u32 len,
44 * len includes itself, value may be empty (in which case its len is 4)
45 */
46};
47
48struct properties_header {
49 u32 len;
50 u32 version;
51 u32 dev_count;
52 struct dev_header dev_header[0];
53};
54
55static u8 one __initdata = 1;
56
57static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
58 struct device *dev, void *ptr,
59 struct property_entry entry[])
60{
61 int i;
62
63 for (i = 0; i < dev_header->prop_count; i++) {
64 int remaining = dev_header->len - (ptr - (void *)dev_header);
65 u32 key_len, val_len;
66 char *key;
67
68 if (sizeof(key_len) > remaining)
69 break;
70
71 key_len = *(typeof(key_len) *)ptr;
72 if (key_len + sizeof(val_len) > remaining ||
73 key_len < sizeof(key_len) + sizeof(efi_char16_t) ||
74 *(efi_char16_t *)(ptr + sizeof(key_len)) == 0) {
75 dev_err(dev, "invalid property name len at %#zx\n",
76 ptr - (void *)dev_header);
77 break;
78 }
79
80 val_len = *(typeof(val_len) *)(ptr + key_len);
81 if (key_len + val_len > remaining ||
82 val_len < sizeof(val_len)) {
83 dev_err(dev, "invalid property val len at %#zx\n",
84 ptr - (void *)dev_header + key_len);
85 break;
86 }
87
88 /* 4 bytes to accommodate UTF-8 code points + null byte */
89 key = kzalloc((key_len - sizeof(key_len)) * 4 + 1, GFP_KERNEL);
90 if (!key) {
91 dev_err(dev, "cannot allocate property name\n");
92 break;
93 }
94 ucs2_as_utf8(key, ptr + sizeof(key_len),
95 key_len - sizeof(key_len));
96
97 entry[i].name = key;
98 entry[i].is_array = true;
99 entry[i].length = val_len - sizeof(val_len);
100 entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len);
101 if (!entry[i].length) {
102 /* driver core doesn't accept empty properties */
103 entry[i].length = 1;
104 entry[i].pointer.raw_data = &one;
105 }
106
107 if (dump_properties) {
108 dev_info(dev, "property: %s\n", entry[i].name);
109 print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET,
110 16, 1, entry[i].pointer.raw_data,
111 entry[i].length, true);
112 }
113
114 ptr += key_len + val_len;
115 }
116
117 if (i != dev_header->prop_count) {
118 dev_err(dev, "got %d device properties, expected %u\n", i,
119 dev_header->prop_count);
120 print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
121 16, 1, dev_header, dev_header->len, true);
122 return;
123 }
124
125 dev_info(dev, "assigning %d device properties\n", i);
126}
127
128static int __init unmarshal_devices(struct properties_header *properties)
129{
130 size_t offset = offsetof(struct properties_header, dev_header[0]);
131
132 while (offset + sizeof(struct dev_header) < properties->len) {
133 struct dev_header *dev_header = (void *)properties + offset;
134 struct property_entry *entry = NULL;
135 struct device *dev;
136 size_t len;
137 int ret, i;
138 void *ptr;
139
140 if (offset + dev_header->len > properties->len ||
141 dev_header->len <= sizeof(*dev_header)) {
142 pr_err("invalid len in dev_header at %#zx\n", offset);
143 return -EINVAL;
144 }
145
146 ptr = dev_header->path;
147 len = dev_header->len - sizeof(*dev_header);
148
149 dev = efi_get_device_by_path((struct efi_dev_path **)&ptr, &len);
150 if (IS_ERR(dev)) {
151 pr_err("device path parse error %ld at %#zx:\n",
152 PTR_ERR(dev), ptr - (void *)dev_header);
153 print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
154 16, 1, dev_header, dev_header->len, true);
155 dev = NULL;
156 goto skip_device;
157 }
158
159 entry = kcalloc(dev_header->prop_count + 1, sizeof(*entry),
160 GFP_KERNEL);
161 if (!entry) {
162 dev_err(dev, "cannot allocate properties\n");
163 goto skip_device;
164 }
165
166 unmarshal_key_value_pairs(dev_header, dev, ptr, entry);
167 if (!entry[0].name)
168 goto skip_device;
169
170 ret = device_add_properties(dev, entry); /* makes deep copy */
171 if (ret)
172 dev_err(dev, "error %d assigning properties\n", ret);
173
174 for (i = 0; entry[i].name; i++)
175 kfree(entry[i].name);
176
177skip_device:
178 kfree(entry);
179 put_device(dev);
180 offset += dev_header->len;
181 }
182
183 return 0;
184}
185
186static int __init map_properties(void)
187{
188 struct properties_header *properties;
189 struct setup_data *data;
190 u32 data_len;
191 u64 pa_data;
192 int ret;
193
194 if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.") &&
195 !dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc."))
196 return 0;
197
198 pa_data = boot_params.hdr.setup_data;
199 while (pa_data) {
200 data = ioremap(pa_data, sizeof(*data));
201 if (!data) {
202 pr_err("cannot map setup_data header\n");
203 return -ENOMEM;
204 }
205
206 if (data->type != SETUP_APPLE_PROPERTIES) {
207 pa_data = data->next;
208 iounmap(data);
209 continue;
210 }
211
212 data_len = data->len;
213 iounmap(data);
214
215 data = ioremap(pa_data, sizeof(*data) + data_len);
216 if (!data) {
217 pr_err("cannot map setup_data payload\n");
218 return -ENOMEM;
219 }
220
221 properties = (struct properties_header *)data->data;
222 if (properties->version != 1) {
223 pr_err("unsupported version:\n");
224 print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
225 16, 1, properties, data_len, true);
226 ret = -ENOTSUPP;
227 } else if (properties->len != data_len) {
228 pr_err("length mismatch, expected %u\n", data_len);
229 print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
230 16, 1, properties, data_len, true);
231 ret = -EINVAL;
232 } else
233 ret = unmarshal_devices(properties);
234
235 /*
236 * Can only free the setup_data payload but not its header
237 * to avoid breaking the chain of ->next pointers.
238 */
239 data->len = 0;
240 iounmap(data);
241 free_bootmem_late(pa_data + sizeof(*data), data_len);
242
243 return ret;
244 }
245 return 0;
246}
247
248fs_initcall(map_properties);
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 8efe13075c92..f853ad2c4ca0 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -244,8 +244,10 @@ void __init efi_init(void)
244 "Unexpected EFI_MEMORY_DESCRIPTOR version %ld", 244 "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
245 efi.memmap.desc_version); 245 efi.memmap.desc_version);
246 246
247 if (uefi_init() < 0) 247 if (uefi_init() < 0) {
248 efi_memmap_unmap();
248 return; 249 return;
250 }
249 251
250 reserve_regions(); 252 reserve_regions();
251 efi_memattr_init(); 253 efi_memattr_init();
diff --git a/drivers/firmware/efi/dev-path-parser.c b/drivers/firmware/efi/dev-path-parser.c
new file mode 100644
index 000000000000..85d1834ee9b7
--- /dev/null
+++ b/drivers/firmware/efi/dev-path-parser.c
@@ -0,0 +1,203 @@
1/*
2 * dev-path-parser.c - EFI Device Path parser
3 * Copyright (C) 2016 Lukas Wunner <lukas@wunner.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License (version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/acpi.h>
19#include <linux/efi.h>
20#include <linux/pci.h>
21
22struct acpi_hid_uid {
23 struct acpi_device_id hid[2];
24 char uid[11]; /* UINT_MAX + null byte */
25};
26
27static int __init match_acpi_dev(struct device *dev, void *data)
28{
29 struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
30 struct acpi_device *adev = to_acpi_device(dev);
31
32 if (acpi_match_device_ids(adev, hid_uid.hid))
33 return 0;
34
35 if (adev->pnp.unique_id)
36 return !strcmp(adev->pnp.unique_id, hid_uid.uid);
37 else
38 return !strcmp("0", hid_uid.uid);
39}
40
41static long __init parse_acpi_path(struct efi_dev_path *node,
42 struct device *parent, struct device **child)
43{
44 struct acpi_hid_uid hid_uid = {};
45 struct device *phys_dev;
46
47 if (node->length != 12)
48 return -EINVAL;
49
50 sprintf(hid_uid.hid[0].id, "%c%c%c%04X",
51 'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
52 'A' + ((node->acpi.hid >> 5) & 0x1f) - 1,
53 'A' + ((node->acpi.hid >> 0) & 0x1f) - 1,
54 node->acpi.hid >> 16);
55 sprintf(hid_uid.uid, "%u", node->acpi.uid);
56
57 *child = bus_find_device(&acpi_bus_type, NULL, &hid_uid,
58 match_acpi_dev);
59 if (!*child)
60 return -ENODEV;
61
62 phys_dev = acpi_get_first_physical_node(to_acpi_device(*child));
63 if (phys_dev) {
64 get_device(phys_dev);
65 put_device(*child);
66 *child = phys_dev;
67 }
68
69 return 0;
70}
71
72static int __init match_pci_dev(struct device *dev, void *data)
73{
74 unsigned int devfn = *(unsigned int *)data;
75
76 return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
77}
78
79static long __init parse_pci_path(struct efi_dev_path *node,
80 struct device *parent, struct device **child)
81{
82 unsigned int devfn;
83
84 if (node->length != 6)
85 return -EINVAL;
86 if (!parent)
87 return -EINVAL;
88
89 devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
90
91 *child = device_find_child(parent, &devfn, match_pci_dev);
92 if (!*child)
93 return -ENODEV;
94
95 return 0;
96}
97
98/*
99 * Insert parsers for further node types here.
100 *
101 * Each parser takes a pointer to the @node and to the @parent (will be NULL
102 * for the first device path node). If a device corresponding to @node was
103 * found below @parent, its reference count should be incremented and the
104 * device returned in @child.
105 *
106 * The return value should be 0 on success or a negative int on failure.
107 * The special return values 0x01 (EFI_DEV_END_INSTANCE) and 0xFF
108 * (EFI_DEV_END_ENTIRE) signal the end of the device path, only
109 * parse_end_path() is supposed to return this.
110 *
111 * Be sure to validate the node length and contents before commencing the
112 * search for a device.
113 */
114
115static long __init parse_end_path(struct efi_dev_path *node,
116 struct device *parent, struct device **child)
117{
118 if (node->length != 4)
119 return -EINVAL;
120 if (node->sub_type != EFI_DEV_END_INSTANCE &&
121 node->sub_type != EFI_DEV_END_ENTIRE)
122 return -EINVAL;
123 if (!parent)
124 return -ENODEV;
125
126 *child = get_device(parent);
127 return node->sub_type;
128}
129
130/**
131 * efi_get_device_by_path - find device by EFI Device Path
132 * @node: EFI Device Path
133 * @len: maximum length of EFI Device Path in bytes
134 *
135 * Parse a series of EFI Device Path nodes at @node and find the corresponding
136 * device. If the device was found, its reference count is incremented and a
137 * pointer to it is returned. The caller needs to drop the reference with
138 * put_device() after use. The @node pointer is updated to point to the
139 * location immediately after the "End of Hardware Device Path" node.
140 *
141 * If another Device Path instance follows, @len is decremented by the number
142 * of bytes consumed. Otherwise @len is set to %0.
143 *
144 * If a Device Path node is malformed or its corresponding device is not found,
145 * @node is updated to point to this offending node and an ERR_PTR is returned.
146 *
147 * If @len is initially %0, the function returns %NULL. Thus, to iterate over
148 * all instances in a path, the following idiom may be used:
149 *
150 * while (!IS_ERR_OR_NULL(dev = efi_get_device_by_path(&node, &len))) {
151 * // do something with dev
152 * put_device(dev);
153 * }
154 * if (IS_ERR(dev))
155 * // report error
156 *
157 * Devices can only be found if they're already instantiated. Most buses
158 * instantiate devices in the "subsys" initcall level, hence the earliest
159 * initcall level in which this function should be called is "fs".
160 *
161 * Returns the device on success or
162 * %ERR_PTR(-ENODEV) if no device was found,
163 * %ERR_PTR(-EINVAL) if a node is malformed or exceeds @len,
164 * %ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented.
165 */
166struct device * __init efi_get_device_by_path(struct efi_dev_path **node,
167 size_t *len)
168{
169 struct device *parent = NULL, *child;
170 long ret = 0;
171
172 if (!*len)
173 return NULL;
174
175 while (!ret) {
176 if (*len < 4 || *len < (*node)->length)
177 ret = -EINVAL;
178 else if ((*node)->type == EFI_DEV_ACPI &&
179 (*node)->sub_type == EFI_DEV_BASIC_ACPI)
180 ret = parse_acpi_path(*node, parent, &child);
181 else if ((*node)->type == EFI_DEV_HW &&
182 (*node)->sub_type == EFI_DEV_PCI)
183 ret = parse_pci_path(*node, parent, &child);
184 else if (((*node)->type == EFI_DEV_END_PATH ||
185 (*node)->type == EFI_DEV_END_PATH2))
186 ret = parse_end_path(*node, parent, &child);
187 else
188 ret = -ENOTSUPP;
189
190 put_device(parent);
191 if (ret < 0)
192 return ERR_PTR(ret);
193
194 parent = child;
195 *node = (void *)*node + (*node)->length;
196 *len -= (*node)->length;
197 }
198
199 if (ret == EFI_DEV_END_ENTIRE)
200 *len = 0;
201
202 return child;
203}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1ac199cd75e7..92914801e388 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -23,7 +23,10 @@
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_fdt.h> 24#include <linux/of_fdt.h>
25#include <linux/io.h> 25#include <linux/io.h>
26#include <linux/kexec.h>
26#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/random.h>
29#include <linux/reboot.h>
27#include <linux/slab.h> 30#include <linux/slab.h>
28#include <linux/acpi.h> 31#include <linux/acpi.h>
29#include <linux/ucs2_string.h> 32#include <linux/ucs2_string.h>
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
48 .esrt = EFI_INVALID_TABLE_ADDR, 51 .esrt = EFI_INVALID_TABLE_ADDR,
49 .properties_table = EFI_INVALID_TABLE_ADDR, 52 .properties_table = EFI_INVALID_TABLE_ADDR,
50 .mem_attr_table = EFI_INVALID_TABLE_ADDR, 53 .mem_attr_table = EFI_INVALID_TABLE_ADDR,
54 .rng_seed = EFI_INVALID_TABLE_ADDR,
51}; 55};
52EXPORT_SYMBOL(efi); 56EXPORT_SYMBOL(efi);
53 57
@@ -259,8 +263,10 @@ static __init int efivar_ssdt_load(void)
259 } 263 }
260 264
261 data = kmalloc(size, GFP_KERNEL); 265 data = kmalloc(size, GFP_KERNEL);
262 if (!data) 266 if (!data) {
267 ret = -ENOMEM;
263 goto free_entry; 268 goto free_entry;
269 }
264 270
265 ret = efivar_entry_get(entry, NULL, &size, data); 271 ret = efivar_entry_get(entry, NULL, &size, data);
266 if (ret) { 272 if (ret) {
@@ -438,6 +444,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
438 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, 444 {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
439 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, 445 {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
440 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, 446 {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
447 {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
441 {NULL_GUID, NULL, NULL}, 448 {NULL_GUID, NULL, NULL},
442}; 449};
443 450
@@ -499,6 +506,29 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
499 pr_cont("\n"); 506 pr_cont("\n");
500 set_bit(EFI_CONFIG_TABLES, &efi.flags); 507 set_bit(EFI_CONFIG_TABLES, &efi.flags);
501 508
509 if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
510 struct linux_efi_random_seed *seed;
511 u32 size = 0;
512
513 seed = early_memremap(efi.rng_seed, sizeof(*seed));
514 if (seed != NULL) {
515 size = seed->size;
516 early_memunmap(seed, sizeof(*seed));
517 } else {
518 pr_err("Could not map UEFI random seed!\n");
519 }
520 if (size > 0) {
521 seed = early_memremap(efi.rng_seed,
522 sizeof(*seed) + size);
523 if (seed != NULL) {
524 add_device_randomness(seed->bits, seed->size);
525 early_memunmap(seed, sizeof(*seed) + size);
526 } else {
527 pr_err("Could not map UEFI random seed!\n");
528 }
529 }
530 }
531
502 /* Parse the EFI Properties table if it exists */ 532 /* Parse the EFI Properties table if it exists */
503 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { 533 if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
504 efi_properties_table_t *tbl; 534 efi_properties_table_t *tbl;
@@ -822,3 +852,47 @@ int efi_status_to_err(efi_status_t status)
822 852
823 return err; 853 return err;
824} 854}
855
856#ifdef CONFIG_KEXEC
857static int update_efi_random_seed(struct notifier_block *nb,
858 unsigned long code, void *unused)
859{
860 struct linux_efi_random_seed *seed;
861 u32 size = 0;
862
863 if (!kexec_in_progress)
864 return NOTIFY_DONE;
865
866 seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
867 if (seed != NULL) {
868 size = min(seed->size, 32U);
869 memunmap(seed);
870 } else {
871 pr_err("Could not map UEFI random seed!\n");
872 }
873 if (size > 0) {
874 seed = memremap(efi.rng_seed, sizeof(*seed) + size,
875 MEMREMAP_WB);
876 if (seed != NULL) {
877 seed->size = size;
878 get_random_bytes(seed->bits, seed->size);
879 memunmap(seed);
880 } else {
881 pr_err("Could not map UEFI random seed!\n");
882 }
883 }
884 return NOTIFY_DONE;
885}
886
887static struct notifier_block efi_random_seed_nb = {
888 .notifier_call = update_efi_random_seed,
889};
890
891static int register_update_efi_random_seed(void)
892{
893 if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
894 return 0;
895 return register_reboot_notifier(&efi_random_seed_nb);
896}
897late_initcall(register_update_efi_random_seed);
898#endif
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 5e23e2d305e7..6621b13c370f 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
36$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE 36$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
37 $(call if_changed_rule,cc_o_c) 37 $(call if_changed_rule,cc_o_c)
38 38
39lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o \ 39lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \
40 $(patsubst %.c,lib-%.o,$(arm-deps)) 40 $(patsubst %.c,lib-%.o,$(arm-deps))
41 41
42lib-$(CONFIG_ARM) += arm32-stub.o 42lib-$(CONFIG_ARM) += arm32-stub.o
43lib-$(CONFIG_ARM64) += arm64-stub.o random.o 43lib-$(CONFIG_ARM64) += arm64-stub.o
44CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) 44CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
45 45
46# 46#
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 993aa56755f6..b4f7d78f9e8b 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
340 if (status != EFI_SUCCESS) 340 if (status != EFI_SUCCESS)
341 pr_efi_err(sys_table, "Failed initrd from command line!\n"); 341 pr_efi_err(sys_table, "Failed initrd from command line!\n");
342 342
343 efi_random_get_seed(sys_table);
344
343 new_fdt_addr = fdt_addr; 345 new_fdt_addr = fdt_addr;
344 status = allocate_new_fdt_and_exit_boot(sys_table, handle, 346 status = allocate_new_fdt_and_exit_boot(sys_table, handle,
345 &new_fdt_addr, dram_base + MAX_FDT_OFFSET, 347 &new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index aded10662020..757badc1debb 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -32,15 +32,6 @@
32 32
33static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; 33static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
34 34
35/*
36 * Allow the platform to override the allocation granularity: this allows
37 * systems that have the capability to run with a larger page size to deal
38 * with the allocations for initrd and fdt more efficiently.
39 */
40#ifndef EFI_ALLOC_ALIGN
41#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
42#endif
43
44#define EFI_MMAP_NR_SLACK_SLOTS 8 35#define EFI_MMAP_NR_SLACK_SLOTS 8
45 36
46struct file_info { 37struct file_info {
@@ -186,14 +177,16 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
186 goto fail; 177 goto fail;
187 178
188 /* 179 /*
189 * Enforce minimum alignment that EFI requires when requesting 180 * Enforce minimum alignment that EFI or Linux requires when
190 * a specific address. We are doing page-based allocations, 181 * requesting a specific address. We are doing page-based (or
191 * so we must be aligned to a page. 182 * larger) allocations, and both the address and size must meet
183 * alignment constraints.
192 */ 184 */
193 if (align < EFI_ALLOC_ALIGN) 185 if (align < EFI_ALLOC_ALIGN)
194 align = EFI_ALLOC_ALIGN; 186 align = EFI_ALLOC_ALIGN;
195 187
196 nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; 188 size = round_up(size, EFI_ALLOC_ALIGN);
189 nr_pages = size / EFI_PAGE_SIZE;
197again: 190again:
198 for (i = 0; i < map_size / desc_size; i++) { 191 for (i = 0; i < map_size / desc_size; i++) {
199 efi_memory_desc_t *desc; 192 efi_memory_desc_t *desc;
@@ -208,7 +201,7 @@ again:
208 continue; 201 continue;
209 202
210 start = desc->phys_addr; 203 start = desc->phys_addr;
211 end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); 204 end = start + desc->num_pages * EFI_PAGE_SIZE;
212 205
213 if (end > max) 206 if (end > max)
214 end = max; 207 end = max;
@@ -278,14 +271,16 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
278 goto fail; 271 goto fail;
279 272
280 /* 273 /*
281 * Enforce minimum alignment that EFI requires when requesting 274 * Enforce minimum alignment that EFI or Linux requires when
282 * a specific address. We are doing page-based allocations, 275 * requesting a specific address. We are doing page-based (or
283 * so we must be aligned to a page. 276 * larger) allocations, and both the address and size must meet
277 * alignment constraints.
284 */ 278 */
285 if (align < EFI_ALLOC_ALIGN) 279 if (align < EFI_ALLOC_ALIGN)
286 align = EFI_ALLOC_ALIGN; 280 align = EFI_ALLOC_ALIGN;
287 281
288 nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; 282 size = round_up(size, EFI_ALLOC_ALIGN);
283 nr_pages = size / EFI_PAGE_SIZE;
289 for (i = 0; i < map_size / desc_size; i++) { 284 for (i = 0; i < map_size / desc_size; i++) {
290 efi_memory_desc_t *desc; 285 efi_memory_desc_t *desc;
291 unsigned long m = (unsigned long)map; 286 unsigned long m = (unsigned long)map;
@@ -300,7 +295,7 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
300 continue; 295 continue;
301 296
302 start = desc->phys_addr; 297 start = desc->phys_addr;
303 end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); 298 end = start + desc->num_pages * EFI_PAGE_SIZE;
304 299
305 /* 300 /*
306 * Don't allocate at 0x0. It will confuse code that 301 * Don't allocate at 0x0. It will confuse code that
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index ee49cd23ee63..b98824e3800a 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -15,6 +15,15 @@
15 */ 15 */
16#undef __init 16#undef __init
17 17
18/*
19 * Allow the platform to override the allocation granularity: this allows
20 * systems that have the capability to run with a larger page size to deal
21 * with the allocations for initrd and fdt more efficiently.
22 */
23#ifndef EFI_ALLOC_ALIGN
24#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
25#endif
26
18void efi_char16_printk(efi_system_table_t *, efi_char16_t *); 27void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
19 28
20efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, 29efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
@@ -62,4 +71,6 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
62 71
63efi_status_t check_platform_features(efi_system_table_t *sys_table_arg); 72efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
64 73
74efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
75
65#endif 76#endif
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 0c9f58c5ba50..7e72954d5860 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -8,6 +8,7 @@
8 */ 8 */
9 9
10#include <linux/efi.h> 10#include <linux/efi.h>
11#include <linux/log2.h>
11#include <asm/efi.h> 12#include <asm/efi.h>
12 13
13#include "efistub.h" 14#include "efistub.h"
@@ -41,21 +42,23 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
41 */ 42 */
42static unsigned long get_entry_num_slots(efi_memory_desc_t *md, 43static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
43 unsigned long size, 44 unsigned long size,
44 unsigned long align) 45 unsigned long align_shift)
45{ 46{
46 u64 start, end; 47 unsigned long align = 1UL << align_shift;
48 u64 first_slot, last_slot, region_end;
47 49
48 if (md->type != EFI_CONVENTIONAL_MEMORY) 50 if (md->type != EFI_CONVENTIONAL_MEMORY)
49 return 0; 51 return 0;
50 52
51 start = round_up(md->phys_addr, align); 53 region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1);
52 end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
53 align);
54 54
55 if (start > end) 55 first_slot = round_up(md->phys_addr, align);
56 last_slot = round_down(region_end - size + 1, align);
57
58 if (first_slot > last_slot)
56 return 0; 59 return 0;
57 60
58 return (end - start + 1) / align; 61 return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1;
59} 62}
60 63
61/* 64/*
@@ -98,7 +101,7 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
98 efi_memory_desc_t *md = (void *)memory_map + map_offset; 101 efi_memory_desc_t *md = (void *)memory_map + map_offset;
99 unsigned long slots; 102 unsigned long slots;
100 103
101 slots = get_entry_num_slots(md, size, align); 104 slots = get_entry_num_slots(md, size, ilog2(align));
102 MD_NUM_SLOTS(md) = slots; 105 MD_NUM_SLOTS(md) = slots;
103 total_slots += slots; 106 total_slots += slots;
104 } 107 }
@@ -141,3 +144,51 @@ efi_status_t efi_random_alloc(efi_system_table_t *sys_table_arg,
141 144
142 return status; 145 return status;
143} 146}
147
148#define RANDOM_SEED_SIZE 32
149
150efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
151{
152 efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
153 efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
154 efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
155 struct efi_rng_protocol *rng;
156 struct linux_efi_random_seed *seed;
157 efi_status_t status;
158
159 status = efi_call_early(locate_protocol, &rng_proto, NULL,
160 (void **)&rng);
161 if (status != EFI_SUCCESS)
162 return status;
163
164 status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
165 sizeof(*seed) + RANDOM_SEED_SIZE,
166 (void **)&seed);
167 if (status != EFI_SUCCESS)
168 return status;
169
170 status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
171 seed->bits);
172 if (status == EFI_UNSUPPORTED)
173 /*
174 * Use whatever algorithm we have available if the raw algorithm
175 * is not implemented.
176 */
177 status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
178 seed->bits);
179
180 if (status != EFI_SUCCESS)
181 goto err_freepool;
182
183 seed->size = RANDOM_SEED_SIZE;
184 status = efi_call_early(install_configuration_table, &rng_table_guid,
185 seed);
186 if (status != EFI_SUCCESS)
187 goto err_freepool;
188
189 return EFI_SUCCESS;
190
191err_freepool:
192 efi_call_early(free_pool, seed);
193 return status;
194}
diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c
index f61bb52be318..8cd578f62059 100644
--- a/drivers/firmware/efi/test/efi_test.c
+++ b/drivers/firmware/efi/test/efi_test.c
@@ -8,7 +8,6 @@
8 * 8 *
9 */ 9 */
10 10
11#include <linux/version.h>
12#include <linux/miscdevice.h> 11#include <linux/miscdevice.h>
13#include <linux/module.h> 12#include <linux/module.h>
14#include <linux/init.h> 13#include <linux/init.h>
@@ -156,7 +155,7 @@ static long efi_runtime_get_variable(unsigned long arg)
156{ 155{
157 struct efi_getvariable __user *getvariable_user; 156 struct efi_getvariable __user *getvariable_user;
158 struct efi_getvariable getvariable; 157 struct efi_getvariable getvariable;
159 unsigned long datasize, prev_datasize, *dz; 158 unsigned long datasize = 0, prev_datasize, *dz;
160 efi_guid_t vendor_guid, *vd = NULL; 159 efi_guid_t vendor_guid, *vd = NULL;
161 efi_status_t status; 160 efi_status_t status;
162 efi_char16_t *name = NULL; 161 efi_char16_t *name = NULL;
@@ -266,14 +265,10 @@ static long efi_runtime_set_variable(unsigned long arg)
266 return rv; 265 return rv;
267 } 266 }
268 267
269 data = kmalloc(setvariable.data_size, GFP_KERNEL); 268 data = memdup_user(setvariable.data, setvariable.data_size);
270 if (!data) { 269 if (IS_ERR(data)) {
271 kfree(name); 270 kfree(name);
272 return -ENOMEM; 271 return PTR_ERR(data);
273 }
274 if (copy_from_user(data, setvariable.data, setvariable.data_size)) {
275 rv = -EFAULT;
276 goto out;
277 } 272 }
278 273
279 status = efi.set_variable(name, &vendor_guid, 274 status = efi.set_variable(name, &vendor_guid,
@@ -429,7 +424,7 @@ static long efi_runtime_get_nextvariablename(unsigned long arg)
429 efi_guid_t *vd = NULL; 424 efi_guid_t *vd = NULL;
430 efi_guid_t vendor_guid; 425 efi_guid_t vendor_guid;
431 efi_char16_t *name = NULL; 426 efi_char16_t *name = NULL;
432 int rv; 427 int rv = 0;
433 428
434 getnextvariablename_user = (struct efi_getnextvariablename __user *)arg; 429 getnextvariablename_user = (struct efi_getnextvariablename __user *)arg;
435 430
diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
index c121acc15bfe..d35db16aa43f 100644
--- a/drivers/thunderbolt/Kconfig
+++ b/drivers/thunderbolt/Kconfig
@@ -1,6 +1,8 @@
1menuconfig THUNDERBOLT 1menuconfig THUNDERBOLT
2 tristate "Thunderbolt support for Apple devices" 2 tristate "Thunderbolt support for Apple devices"
3 depends on PCI 3 depends on PCI
4 depends on X86 || COMPILE_TEST
5 select APPLE_PROPERTIES if EFI_STUB && X86
4 select CRC32 6 select CRC32
5 help 7 help
6 Cactus Ridge Thunderbolt Controller driver 8 Cactus Ridge Thunderbolt Controller driver
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 2b9602c2c355..6392990c984d 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -5,6 +5,7 @@
5 */ 5 */
6 6
7#include <linux/crc32.h> 7#include <linux/crc32.h>
8#include <linux/property.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
9#include "tb.h" 10#include "tb.h"
10 11
@@ -360,6 +361,40 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
360} 361}
361 362
362/** 363/**
364 * tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
365 */
366static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
367{
368 struct device *dev = &sw->tb->nhi->pdev->dev;
369 int len, res;
370
371 len = device_property_read_u8_array(dev, "ThunderboltDROM", NULL, 0);
372 if (len < 0 || len < sizeof(struct tb_drom_header))
373 return -EINVAL;
374
375 sw->drom = kmalloc(len, GFP_KERNEL);
376 if (!sw->drom)
377 return -ENOMEM;
378
379 res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom,
380 len);
381 if (res)
382 goto err;
383
384 *size = ((struct tb_drom_header *)sw->drom)->data_len +
385 TB_DROM_DATA_START;
386 if (*size > len)
387 goto err;
388
389 return 0;
390
391err:
392 kfree(sw->drom);
393 sw->drom = NULL;
394 return -EINVAL;
395}
396
397/**
363 * tb_drom_read - copy drom to sw->drom and parse it 398 * tb_drom_read - copy drom to sw->drom and parse it
364 */ 399 */
365int tb_drom_read(struct tb_switch *sw) 400int tb_drom_read(struct tb_switch *sw)
@@ -374,6 +409,13 @@ int tb_drom_read(struct tb_switch *sw)
374 409
375 if (tb_route(sw) == 0) { 410 if (tb_route(sw) == 0) {
376 /* 411 /*
412 * Apple's NHI EFI driver supplies a DROM for the root switch
413 * in a device property. Use it if available.
414 */
415 if (tb_drom_copy_efi(sw, &size) == 0)
416 goto parse;
417
418 /*
377 * The root switch contains only a dummy drom (header only, 419 * The root switch contains only a dummy drom (header only,
378 * no entries). Hardcode the configuration here. 420 * no entries). Hardcode the configuration here.
379 */ 421 */
@@ -418,6 +460,7 @@ int tb_drom_read(struct tb_switch *sw)
418 if (res) 460 if (res)
419 goto err; 461 goto err;
420 462
463parse:
421 header = (void *) sw->drom; 464 header = (void *) sw->drom;
422 465
423 if (header->data_len + TB_DROM_DATA_START != size) { 466 if (header->data_len + TB_DROM_DATA_START != size) {
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 9840fdecb73b..c6f30b1695a9 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -460,7 +460,7 @@ int tb_switch_resume(struct tb_switch *sw)
460 tb_sw_warn(sw, "uid read failed\n"); 460 tb_sw_warn(sw, "uid read failed\n");
461 return err; 461 return err;
462 } 462 }
463 if (sw->uid != uid) { 463 if (sw != sw->tb->root_switch && sw->uid != uid) {
464 tb_sw_info(sw, 464 tb_sw_info(sw,
465 "changed while suspended (uid %#llx -> %#llx)\n", 465 "changed while suspended (uid %#llx -> %#llx)\n",
466 sw->uid, uid); 466 sw->uid, uid);
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 37a37c4d04cb..8c4dc1e1f94f 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -118,6 +118,31 @@ static inline bool fb_base_is_valid(void)
118 return false; 118 return false;
119} 119}
120 120
121#define efifb_attr_decl(name, fmt) \
122static ssize_t name##_show(struct device *dev, \
123 struct device_attribute *attr, \
124 char *buf) \
125{ \
126 return sprintf(buf, fmt "\n", (screen_info.lfb_##name)); \
127} \
128static DEVICE_ATTR_RO(name)
129
130efifb_attr_decl(base, "0x%x");
131efifb_attr_decl(linelength, "%u");
132efifb_attr_decl(height, "%u");
133efifb_attr_decl(width, "%u");
134efifb_attr_decl(depth, "%u");
135
136static struct attribute *efifb_attrs[] = {
137 &dev_attr_base.attr,
138 &dev_attr_linelength.attr,
139 &dev_attr_width.attr,
140 &dev_attr_height.attr,
141 &dev_attr_depth.attr,
142 NULL
143};
144ATTRIBUTE_GROUPS(efifb);
145
121static int efifb_probe(struct platform_device *dev) 146static int efifb_probe(struct platform_device *dev)
122{ 147{
123 struct fb_info *info; 148 struct fb_info *info;
@@ -205,14 +230,13 @@ static int efifb_probe(struct platform_device *dev)
205 } else { 230 } else {
206 /* We cannot make this fatal. Sometimes this comes from magic 231 /* We cannot make this fatal. Sometimes this comes from magic
207 spaces our resource handlers simply don't know about */ 232 spaces our resource handlers simply don't know about */
208 printk(KERN_WARNING 233 pr_warn("efifb: cannot reserve video memory at 0x%lx\n",
209 "efifb: cannot reserve video memory at 0x%lx\n",
210 efifb_fix.smem_start); 234 efifb_fix.smem_start);
211 } 235 }
212 236
213 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 237 info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
214 if (!info) { 238 if (!info) {
215 printk(KERN_ERR "efifb: cannot allocate framebuffer\n"); 239 pr_err("efifb: cannot allocate framebuffer\n");
216 err = -ENOMEM; 240 err = -ENOMEM;
217 goto err_release_mem; 241 goto err_release_mem;
218 } 242 }
@@ -230,16 +254,15 @@ static int efifb_probe(struct platform_device *dev)
230 254
231 info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); 255 info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
232 if (!info->screen_base) { 256 if (!info->screen_base) {
233 printk(KERN_ERR "efifb: abort, cannot ioremap video memory " 257 pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
234 "0x%x @ 0x%lx\n",
235 efifb_fix.smem_len, efifb_fix.smem_start); 258 efifb_fix.smem_len, efifb_fix.smem_start);
236 err = -EIO; 259 err = -EIO;
237 goto err_release_fb; 260 goto err_release_fb;
238 } 261 }
239 262
240 printk(KERN_INFO "efifb: framebuffer at 0x%lx, using %dk, total %dk\n", 263 pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
241 efifb_fix.smem_start, size_remap/1024, size_total/1024); 264 efifb_fix.smem_start, size_remap/1024, size_total/1024);
242 printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", 265 pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
243 efifb_defined.xres, efifb_defined.yres, 266 efifb_defined.xres, efifb_defined.yres,
244 efifb_defined.bits_per_pixel, efifb_fix.line_length, 267 efifb_defined.bits_per_pixel, efifb_fix.line_length,
245 screen_info.pages); 268 screen_info.pages);
@@ -247,7 +270,7 @@ static int efifb_probe(struct platform_device *dev)
247 efifb_defined.xres_virtual = efifb_defined.xres; 270 efifb_defined.xres_virtual = efifb_defined.xres;
248 efifb_defined.yres_virtual = efifb_fix.smem_len / 271 efifb_defined.yres_virtual = efifb_fix.smem_len /
249 efifb_fix.line_length; 272 efifb_fix.line_length;
250 printk(KERN_INFO "efifb: scrolling: redraw\n"); 273 pr_info("efifb: scrolling: redraw\n");
251 efifb_defined.yres_virtual = efifb_defined.yres; 274 efifb_defined.yres_virtual = efifb_defined.yres;
252 275
253 /* some dummy values for timing to make fbset happy */ 276 /* some dummy values for timing to make fbset happy */
@@ -265,7 +288,7 @@ static int efifb_probe(struct platform_device *dev)
265 efifb_defined.transp.offset = screen_info.rsvd_pos; 288 efifb_defined.transp.offset = screen_info.rsvd_pos;
266 efifb_defined.transp.length = screen_info.rsvd_size; 289 efifb_defined.transp.length = screen_info.rsvd_size;
267 290
268 printk(KERN_INFO "efifb: %s: " 291 pr_info("efifb: %s: "
269 "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", 292 "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
270 "Truecolor", 293 "Truecolor",
271 screen_info.rsvd_size, 294 screen_info.rsvd_size,
@@ -285,12 +308,19 @@ static int efifb_probe(struct platform_device *dev)
285 info->fix = efifb_fix; 308 info->fix = efifb_fix;
286 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; 309 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
287 310
288 if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { 311 err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
289 printk(KERN_ERR "efifb: cannot allocate colormap\n"); 312 if (err) {
313 pr_err("efifb: cannot add sysfs attrs\n");
290 goto err_unmap; 314 goto err_unmap;
291 } 315 }
292 if ((err = register_framebuffer(info)) < 0) { 316 err = fb_alloc_cmap(&info->cmap, 256, 0);
293 printk(KERN_ERR "efifb: cannot register framebuffer\n"); 317 if (err < 0) {
318 pr_err("efifb: cannot allocate colormap\n");
319 goto err_groups;
320 }
321 err = register_framebuffer(info);
322 if (err < 0) {
323 pr_err("efifb: cannot register framebuffer\n");
294 goto err_fb_dealoc; 324 goto err_fb_dealoc;
295 } 325 }
296 fb_info(info, "%s frame buffer device\n", info->fix.id); 326 fb_info(info, "%s frame buffer device\n", info->fix.id);
@@ -298,6 +328,8 @@ static int efifb_probe(struct platform_device *dev)
298 328
299err_fb_dealoc: 329err_fb_dealoc:
300 fb_dealloc_cmap(&info->cmap); 330 fb_dealloc_cmap(&info->cmap);
331err_groups:
332 sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
301err_unmap: 333err_unmap:
302 iounmap(info->screen_base); 334 iounmap(info->screen_base);
303err_release_fb: 335err_release_fb:
@@ -313,6 +345,7 @@ static int efifb_remove(struct platform_device *pdev)
313 struct fb_info *info = platform_get_drvdata(pdev); 345 struct fb_info *info = platform_get_drvdata(pdev);
314 346
315 unregister_framebuffer(info); 347 unregister_framebuffer(info);
348 sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
316 framebuffer_release(info); 349 framebuffer_release(info);
317 350
318 return 0; 351 return 0;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 2d089487d2da..a07a476178cd 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -443,6 +443,22 @@ typedef struct {
443#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 443#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000
444#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 444#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000
445 445
446typedef struct {
447 u32 version;
448 u32 get;
449 u32 set;
450 u32 del;
451 u32 get_all;
452} apple_properties_protocol_32_t;
453
454typedef struct {
455 u64 version;
456 u64 get;
457 u64 set;
458 u64 del;
459 u64 get_all;
460} apple_properties_protocol_64_t;
461
446/* 462/*
447 * Types and defines for EFI ResetSystem 463 * Types and defines for EFI ResetSystem
448 */ 464 */
@@ -589,8 +605,10 @@ void efi_native_runtime_setup(void);
589#define DEVICE_TREE_GUID EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0) 605#define DEVICE_TREE_GUID EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
590#define EFI_PROPERTIES_TABLE_GUID EFI_GUID(0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5) 606#define EFI_PROPERTIES_TABLE_GUID EFI_GUID(0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
591#define EFI_RNG_PROTOCOL_GUID EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44) 607#define EFI_RNG_PROTOCOL_GUID EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
608#define EFI_RNG_ALGORITHM_RAW EFI_GUID(0xe43176d7, 0xb6e8, 0x4827, 0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
592#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) 609#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
593#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) 610#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
611#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
594 612
595/* 613/*
596 * This GUID is used to pass to the kernel proper the struct screen_info 614 * This GUID is used to pass to the kernel proper the struct screen_info
@@ -599,6 +617,7 @@ void efi_native_runtime_setup(void);
599 */ 617 */
600#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) 618#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
601#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) 619#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
620#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
602 621
603typedef struct { 622typedef struct {
604 efi_guid_t guid; 623 efi_guid_t guid;
@@ -872,6 +891,7 @@ extern struct efi {
872 unsigned long esrt; /* ESRT table */ 891 unsigned long esrt; /* ESRT table */
873 unsigned long properties_table; /* properties table */ 892 unsigned long properties_table; /* properties table */
874 unsigned long mem_attr_table; /* memory attributes table */ 893 unsigned long mem_attr_table; /* memory attributes table */
894 unsigned long rng_seed; /* UEFI firmware random seed */
875 efi_get_time_t *get_time; 895 efi_get_time_t *get_time;
876 efi_set_time_t *set_time; 896 efi_set_time_t *set_time;
877 efi_get_wakeup_time_t *get_wakeup_time; 897 efi_get_wakeup_time_t *get_wakeup_time;
@@ -1145,6 +1165,26 @@ struct efi_generic_dev_path {
1145 u16 length; 1165 u16 length;
1146} __attribute ((packed)); 1166} __attribute ((packed));
1147 1167
1168struct efi_dev_path {
1169 u8 type; /* can be replaced with unnamed */
1170 u8 sub_type; /* struct efi_generic_dev_path; */
1171 u16 length; /* once we've moved to -std=c11 */
1172 union {
1173 struct {
1174 u32 hid;
1175 u32 uid;
1176 } acpi;
1177 struct {
1178 u8 fn;
1179 u8 dev;
1180 } pci;
1181 };
1182} __attribute ((packed));
1183
1184#if IS_ENABLED(CONFIG_EFI_DEV_PATH_PARSER)
1185struct device *efi_get_device_by_path(struct efi_dev_path **node, size_t *len);
1186#endif
1187
1148static inline void memrange_efi_to_native(u64 *addr, u64 *npages) 1188static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
1149{ 1189{
1150 *npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr); 1190 *npages = PFN_UP(*addr + (*npages<<EFI_PAGE_SHIFT)) - PFN_DOWN(*addr);
@@ -1493,4 +1533,10 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table,
1493 struct efi_boot_memmap *map, 1533 struct efi_boot_memmap *map,
1494 void *priv, 1534 void *priv,
1495 efi_exit_boot_map_processing priv_func); 1535 efi_exit_boot_map_processing priv_func);
1536
1537struct linux_efi_random_seed {
1538 u32 size;
1539 u8 bits[];
1540};
1541
1496#endif /* _LINUX_EFI_H */ 1542#endif /* _LINUX_EFI_H */