diff options
-rw-r--r-- | arch/arm/include/asm/efi.h | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/efi.h | 3 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 545 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.h | 12 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 101 | ||||
-rw-r--r-- | arch/x86/platform/efi/quirks.c | 14 | ||||
-rw-r--r-- | drivers/firmware/efi/Kconfig | 12 | ||||
-rw-r--r-- | drivers/firmware/efi/cper.c | 19 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 22 | ||||
-rw-r--r-- | drivers/firmware/efi/esrt.c | 8 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 32 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 31 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/runtime-wrappers.c | 202 | ||||
-rw-r--r-- | drivers/video/fbdev/efifb.c | 51 | ||||
-rw-r--r-- | fs/efivarfs/inode.c | 4 | ||||
-rw-r--r-- | include/linux/efi.h | 15 |
17 files changed, 626 insertions, 451 deletions
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index 17f1f1a814ff..38badaae8d9d 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -58,6 +58,9 @@ void efi_virtmap_unload(void); | |||
58 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) | 58 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) |
59 | #define efi_is_64bit() (false) | 59 | #define efi_is_64bit() (false) |
60 | 60 | ||
61 | #define efi_table_attr(table, attr, instance) \ | ||
62 | ((table##_t *)instance)->attr | ||
63 | |||
61 | #define efi_call_proto(protocol, f, instance, ...) \ | 64 | #define efi_call_proto(protocol, f, instance, ...) \ |
62 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) | 65 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) |
63 | 66 | ||
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 192d791f1103..7ed320895d1f 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
@@ -87,6 +87,9 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, | |||
87 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) | 87 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) |
88 | #define efi_is_64bit() (true) | 88 | #define efi_is_64bit() (true) |
89 | 89 | ||
90 | #define efi_table_attr(table, attr, instance) \ | ||
91 | ((table##_t *)instance)->attr | ||
92 | |||
90 | #define efi_call_proto(protocol, f, instance, ...) \ | 93 | #define efi_call_proto(protocol, f, instance, ...) \ |
91 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) | 94 | ((protocol##_t *)instance)->f(instance, ##__VA_ARGS__) |
92 | 95 | ||
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index e98522ea6f09..1458b1700fc7 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -34,74 +34,13 @@ static void setup_boot_services##bits(struct efi_config *c) \ | |||
34 | \ | 34 | \ |
35 | table = (typeof(table))sys_table; \ | 35 | table = (typeof(table))sys_table; \ |
36 | \ | 36 | \ |
37 | c->runtime_services = table->runtime; \ | 37 | c->runtime_services = table->runtime; \ |
38 | c->boot_services = table->boottime; \ | 38 | c->boot_services = table->boottime; \ |
39 | c->text_output = table->con_out; \ | 39 | c->text_output = table->con_out; \ |
40 | } | 40 | } |
41 | BOOT_SERVICES(32); | 41 | BOOT_SERVICES(32); |
42 | BOOT_SERVICES(64); | 42 | BOOT_SERVICES(64); |
43 | 43 | ||
44 | static inline efi_status_t __open_volume32(void *__image, void **__fh) | ||
45 | { | ||
46 | efi_file_io_interface_t *io; | ||
47 | efi_loaded_image_32_t *image = __image; | ||
48 | efi_file_handle_32_t *fh; | ||
49 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
50 | efi_status_t status; | ||
51 | void *handle = (void *)(unsigned long)image->device_handle; | ||
52 | unsigned long func; | ||
53 | |||
54 | status = efi_call_early(handle_protocol, handle, | ||
55 | &fs_proto, (void **)&io); | ||
56 | if (status != EFI_SUCCESS) { | ||
57 | efi_printk(sys_table, "Failed to handle fs_proto\n"); | ||
58 | return status; | ||
59 | } | ||
60 | |||
61 | func = (unsigned long)io->open_volume; | ||
62 | status = efi_early->call(func, io, &fh); | ||
63 | if (status != EFI_SUCCESS) | ||
64 | efi_printk(sys_table, "Failed to open volume\n"); | ||
65 | |||
66 | *__fh = fh; | ||
67 | return status; | ||
68 | } | ||
69 | |||
70 | static inline efi_status_t __open_volume64(void *__image, void **__fh) | ||
71 | { | ||
72 | efi_file_io_interface_t *io; | ||
73 | efi_loaded_image_64_t *image = __image; | ||
74 | efi_file_handle_64_t *fh; | ||
75 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
76 | efi_status_t status; | ||
77 | void *handle = (void *)(unsigned long)image->device_handle; | ||
78 | unsigned long func; | ||
79 | |||
80 | status = efi_call_early(handle_protocol, handle, | ||
81 | &fs_proto, (void **)&io); | ||
82 | if (status != EFI_SUCCESS) { | ||
83 | efi_printk(sys_table, "Failed to handle fs_proto\n"); | ||
84 | return status; | ||
85 | } | ||
86 | |||
87 | func = (unsigned long)io->open_volume; | ||
88 | status = efi_early->call(func, io, &fh); | ||
89 | if (status != EFI_SUCCESS) | ||
90 | efi_printk(sys_table, "Failed to open volume\n"); | ||
91 | |||
92 | *__fh = fh; | ||
93 | return status; | ||
94 | } | ||
95 | |||
96 | efi_status_t | ||
97 | efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) | ||
98 | { | ||
99 | if (efi_early->is64) | ||
100 | return __open_volume64(__image, __fh); | ||
101 | |||
102 | return __open_volume32(__image, __fh); | ||
103 | } | ||
104 | |||
105 | void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) | 44 | void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) |
106 | { | 45 | { |
107 | efi_call_proto(efi_simple_text_output_protocol, output_string, | 46 | efi_call_proto(efi_simple_text_output_protocol, output_string, |
@@ -109,7 +48,7 @@ void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) | |||
109 | } | 48 | } |
110 | 49 | ||
111 | static efi_status_t | 50 | static efi_status_t |
112 | __setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) | 51 | preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) |
113 | { | 52 | { |
114 | struct pci_setup_rom *rom = NULL; | 53 | struct pci_setup_rom *rom = NULL; |
115 | efi_status_t status; | 54 | efi_status_t status; |
@@ -134,16 +73,16 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) | |||
134 | 73 | ||
135 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom); | 74 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom); |
136 | if (status != EFI_SUCCESS) { | 75 | if (status != EFI_SUCCESS) { |
137 | efi_printk(sys_table, "Failed to alloc mem for rom\n"); | 76 | efi_printk(sys_table, "Failed to allocate memory for 'rom'\n"); |
138 | return status; | 77 | return status; |
139 | } | 78 | } |
140 | 79 | ||
141 | memset(rom, 0, sizeof(*rom)); | 80 | memset(rom, 0, sizeof(*rom)); |
142 | 81 | ||
143 | rom->data.type = SETUP_PCI; | 82 | rom->data.type = SETUP_PCI; |
144 | rom->data.len = size - sizeof(struct setup_data); | 83 | rom->data.len = size - sizeof(struct setup_data); |
145 | rom->data.next = 0; | 84 | rom->data.next = 0; |
146 | rom->pcilen = pci->romsize; | 85 | rom->pcilen = pci->romsize; |
147 | *__rom = rom; | 86 | *__rom = rom; |
148 | 87 | ||
149 | status = efi_call_proto(efi_pci_io_protocol, pci.read, pci, | 88 | status = efi_call_proto(efi_pci_io_protocol, pci.read, pci, |
@@ -179,96 +118,6 @@ free_struct: | |||
179 | return status; | 118 | return status; |
180 | } | 119 | } |
181 | 120 | ||
182 | static void | ||
183 | setup_efi_pci32(struct boot_params *params, void **pci_handle, | ||
184 | unsigned long size) | ||
185 | { | ||
186 | efi_pci_io_protocol_t *pci = NULL; | ||
187 | efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; | ||
188 | u32 *handles = (u32 *)(unsigned long)pci_handle; | ||
189 | efi_status_t status; | ||
190 | unsigned long nr_pci; | ||
191 | struct setup_data *data; | ||
192 | int i; | ||
193 | |||
194 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; | ||
195 | |||
196 | while (data && data->next) | ||
197 | data = (struct setup_data *)(unsigned long)data->next; | ||
198 | |||
199 | nr_pci = size / sizeof(u32); | ||
200 | for (i = 0; i < nr_pci; i++) { | ||
201 | struct pci_setup_rom *rom = NULL; | ||
202 | u32 h = handles[i]; | ||
203 | |||
204 | status = efi_call_early(handle_protocol, h, | ||
205 | &pci_proto, (void **)&pci); | ||
206 | |||
207 | if (status != EFI_SUCCESS) | ||
208 | continue; | ||
209 | |||
210 | if (!pci) | ||
211 | continue; | ||
212 | |||
213 | status = __setup_efi_pci(pci, &rom); | ||
214 | if (status != EFI_SUCCESS) | ||
215 | continue; | ||
216 | |||
217 | if (data) | ||
218 | data->next = (unsigned long)rom; | ||
219 | else | ||
220 | params->hdr.setup_data = (unsigned long)rom; | ||
221 | |||
222 | data = (struct setup_data *)rom; | ||
223 | |||
224 | } | ||
225 | } | ||
226 | |||
227 | static void | ||
228 | setup_efi_pci64(struct boot_params *params, void **pci_handle, | ||
229 | unsigned long size) | ||
230 | { | ||
231 | efi_pci_io_protocol_t *pci = NULL; | ||
232 | efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; | ||
233 | u64 *handles = (u64 *)(unsigned long)pci_handle; | ||
234 | efi_status_t status; | ||
235 | unsigned long nr_pci; | ||
236 | struct setup_data *data; | ||
237 | int i; | ||
238 | |||
239 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; | ||
240 | |||
241 | while (data && data->next) | ||
242 | data = (struct setup_data *)(unsigned long)data->next; | ||
243 | |||
244 | nr_pci = size / sizeof(u64); | ||
245 | for (i = 0; i < nr_pci; i++) { | ||
246 | struct pci_setup_rom *rom = NULL; | ||
247 | u64 h = handles[i]; | ||
248 | |||
249 | status = efi_call_early(handle_protocol, h, | ||
250 | &pci_proto, (void **)&pci); | ||
251 | |||
252 | if (status != EFI_SUCCESS) | ||
253 | continue; | ||
254 | |||
255 | if (!pci) | ||
256 | continue; | ||
257 | |||
258 | status = __setup_efi_pci(pci, &rom); | ||
259 | if (status != EFI_SUCCESS) | ||
260 | continue; | ||
261 | |||
262 | if (data) | ||
263 | data->next = (unsigned long)rom; | ||
264 | else | ||
265 | params->hdr.setup_data = (unsigned long)rom; | ||
266 | |||
267 | data = (struct setup_data *)rom; | ||
268 | |||
269 | } | ||
270 | } | ||
271 | |||
272 | /* | 121 | /* |
273 | * There's no way to return an informative status from this function, | 122 | * There's no way to return an informative status from this function, |
274 | * because any analysis (and printing of error messages) needs to be | 123 | * because any analysis (and printing of error messages) needs to be |
@@ -284,6 +133,9 @@ static void setup_efi_pci(struct boot_params *params) | |||
284 | void **pci_handle = NULL; | 133 | void **pci_handle = NULL; |
285 | efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; | 134 | efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; |
286 | unsigned long size = 0; | 135 | unsigned long size = 0; |
136 | unsigned long nr_pci; | ||
137 | struct setup_data *data; | ||
138 | int i; | ||
287 | 139 | ||
288 | status = efi_call_early(locate_handle, | 140 | status = efi_call_early(locate_handle, |
289 | EFI_LOCATE_BY_PROTOCOL, | 141 | EFI_LOCATE_BY_PROTOCOL, |
@@ -295,7 +147,7 @@ static void setup_efi_pci(struct boot_params *params) | |||
295 | size, (void **)&pci_handle); | 147 | size, (void **)&pci_handle); |
296 | 148 | ||
297 | if (status != EFI_SUCCESS) { | 149 | if (status != EFI_SUCCESS) { |
298 | efi_printk(sys_table, "Failed to alloc mem for pci_handle\n"); | 150 | efi_printk(sys_table, "Failed to allocate memory for 'pci_handle'\n"); |
299 | return; | 151 | return; |
300 | } | 152 | } |
301 | 153 | ||
@@ -307,10 +159,34 @@ static void setup_efi_pci(struct boot_params *params) | |||
307 | if (status != EFI_SUCCESS) | 159 | if (status != EFI_SUCCESS) |
308 | goto free_handle; | 160 | goto free_handle; |
309 | 161 | ||
310 | if (efi_early->is64) | 162 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; |
311 | setup_efi_pci64(params, pci_handle, size); | 163 | |
312 | else | 164 | while (data && data->next) |
313 | setup_efi_pci32(params, pci_handle, size); | 165 | data = (struct setup_data *)(unsigned long)data->next; |
166 | |||
167 | nr_pci = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32)); | ||
168 | for (i = 0; i < nr_pci; i++) { | ||
169 | efi_pci_io_protocol_t *pci = NULL; | ||
170 | struct pci_setup_rom *rom; | ||
171 | |||
172 | status = efi_call_early(handle_protocol, | ||
173 | efi_is_64bit() ? ((u64 *)pci_handle)[i] | ||
174 | : ((u32 *)pci_handle)[i], | ||
175 | &pci_proto, (void **)&pci); | ||
176 | if (status != EFI_SUCCESS || !pci) | ||
177 | continue; | ||
178 | |||
179 | status = preserve_pci_rom_image(pci, &rom); | ||
180 | if (status != EFI_SUCCESS) | ||
181 | continue; | ||
182 | |||
183 | if (data) | ||
184 | data->next = (unsigned long)rom; | ||
185 | else | ||
186 | params->hdr.setup_data = (unsigned long)rom; | ||
187 | |||
188 | data = (struct setup_data *)rom; | ||
189 | } | ||
314 | 190 | ||
315 | free_handle: | 191 | free_handle: |
316 | efi_call_early(free_pool, pci_handle); | 192 | efi_call_early(free_pool, pci_handle); |
@@ -341,8 +217,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) | |||
341 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | 217 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, |
342 | size + sizeof(struct setup_data), &new); | 218 | size + sizeof(struct setup_data), &new); |
343 | if (status != EFI_SUCCESS) { | 219 | if (status != EFI_SUCCESS) { |
344 | efi_printk(sys_table, | 220 | efi_printk(sys_table, "Failed to allocate memory for 'properties'\n"); |
345 | "Failed to alloc mem for properties\n"); | ||
346 | return; | 221 | return; |
347 | } | 222 | } |
348 | 223 | ||
@@ -358,9 +233,9 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) | |||
358 | new->next = 0; | 233 | new->next = 0; |
359 | 234 | ||
360 | data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data; | 235 | data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data; |
361 | if (!data) | 236 | if (!data) { |
362 | boot_params->hdr.setup_data = (unsigned long)new; | 237 | boot_params->hdr.setup_data = (unsigned long)new; |
363 | else { | 238 | } else { |
364 | while (data->next) | 239 | while (data->next) |
365 | data = (struct setup_data *)(unsigned long)data->next; | 240 | data = (struct setup_data *)(unsigned long)data->next; |
366 | data->next = (unsigned long)new; | 241 | data->next = (unsigned long)new; |
@@ -380,81 +255,55 @@ static void setup_quirks(struct boot_params *boot_params) | |||
380 | } | 255 | } |
381 | } | 256 | } |
382 | 257 | ||
258 | /* | ||
259 | * See if we have Universal Graphics Adapter (UGA) protocol | ||
260 | */ | ||
383 | static efi_status_t | 261 | static efi_status_t |
384 | setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) | 262 | setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size) |
385 | { | 263 | { |
386 | struct efi_uga_draw_protocol *uga = NULL, *first_uga; | 264 | efi_status_t status; |
387 | efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; | 265 | u32 width, height; |
266 | void **uga_handle = NULL; | ||
267 | efi_uga_draw_protocol_t *uga = NULL, *first_uga; | ||
388 | unsigned long nr_ugas; | 268 | unsigned long nr_ugas; |
389 | u32 *handles = (u32 *)uga_handle; | ||
390 | efi_status_t status = EFI_INVALID_PARAMETER; | ||
391 | int i; | 269 | int i; |
392 | 270 | ||
393 | first_uga = NULL; | 271 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, |
394 | nr_ugas = size / sizeof(u32); | 272 | size, (void **)&uga_handle); |
395 | for (i = 0; i < nr_ugas; i++) { | 273 | if (status != EFI_SUCCESS) |
396 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; | 274 | return status; |
397 | u32 w, h, depth, refresh; | ||
398 | void *pciio; | ||
399 | u32 handle = handles[i]; | ||
400 | |||
401 | status = efi_call_early(handle_protocol, handle, | ||
402 | &uga_proto, (void **)&uga); | ||
403 | if (status != EFI_SUCCESS) | ||
404 | continue; | ||
405 | |||
406 | efi_call_early(handle_protocol, handle, &pciio_proto, &pciio); | ||
407 | |||
408 | status = efi_early->call((unsigned long)uga->get_mode, uga, | ||
409 | &w, &h, &depth, &refresh); | ||
410 | if (status == EFI_SUCCESS && (!first_uga || pciio)) { | ||
411 | *width = w; | ||
412 | *height = h; | ||
413 | |||
414 | /* | ||
415 | * Once we've found a UGA supporting PCIIO, | ||
416 | * don't bother looking any further. | ||
417 | */ | ||
418 | if (pciio) | ||
419 | break; | ||
420 | |||
421 | first_uga = uga; | ||
422 | } | ||
423 | } | ||
424 | 275 | ||
425 | return status; | 276 | status = efi_call_early(locate_handle, |
426 | } | 277 | EFI_LOCATE_BY_PROTOCOL, |
278 | uga_proto, NULL, &size, uga_handle); | ||
279 | if (status != EFI_SUCCESS) | ||
280 | goto free_handle; | ||
427 | 281 | ||
428 | static efi_status_t | 282 | height = 0; |
429 | setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height) | 283 | width = 0; |
430 | { | ||
431 | struct efi_uga_draw_protocol *uga = NULL, *first_uga; | ||
432 | efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; | ||
433 | unsigned long nr_ugas; | ||
434 | u64 *handles = (u64 *)uga_handle; | ||
435 | efi_status_t status = EFI_INVALID_PARAMETER; | ||
436 | int i; | ||
437 | 284 | ||
438 | first_uga = NULL; | 285 | first_uga = NULL; |
439 | nr_ugas = size / sizeof(u64); | 286 | nr_ugas = size / (efi_is_64bit() ? sizeof(u64) : sizeof(u32)); |
440 | for (i = 0; i < nr_ugas; i++) { | 287 | for (i = 0; i < nr_ugas; i++) { |
441 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; | 288 | efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; |
442 | u32 w, h, depth, refresh; | 289 | u32 w, h, depth, refresh; |
443 | void *pciio; | 290 | void *pciio; |
444 | u64 handle = handles[i]; | 291 | unsigned long handle = efi_is_64bit() ? ((u64 *)uga_handle)[i] |
292 | : ((u32 *)uga_handle)[i]; | ||
445 | 293 | ||
446 | status = efi_call_early(handle_protocol, handle, | 294 | status = efi_call_early(handle_protocol, handle, |
447 | &uga_proto, (void **)&uga); | 295 | uga_proto, (void **)&uga); |
448 | if (status != EFI_SUCCESS) | 296 | if (status != EFI_SUCCESS) |
449 | continue; | 297 | continue; |
450 | 298 | ||
299 | pciio = NULL; | ||
451 | efi_call_early(handle_protocol, handle, &pciio_proto, &pciio); | 300 | efi_call_early(handle_protocol, handle, &pciio_proto, &pciio); |
452 | 301 | ||
453 | status = efi_early->call((unsigned long)uga->get_mode, uga, | 302 | status = efi_call_proto(efi_uga_draw_protocol, get_mode, uga, |
454 | &w, &h, &depth, &refresh); | 303 | &w, &h, &depth, &refresh); |
455 | if (status == EFI_SUCCESS && (!first_uga || pciio)) { | 304 | if (status == EFI_SUCCESS && (!first_uga || pciio)) { |
456 | *width = w; | 305 | width = w; |
457 | *height = h; | 306 | height = h; |
458 | 307 | ||
459 | /* | 308 | /* |
460 | * Once we've found a UGA supporting PCIIO, | 309 | * Once we've found a UGA supporting PCIIO, |
@@ -467,59 +316,28 @@ setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height) | |||
467 | } | 316 | } |
468 | } | 317 | } |
469 | 318 | ||
470 | return status; | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * See if we have Universal Graphics Adapter (UGA) protocol | ||
475 | */ | ||
476 | static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, | ||
477 | unsigned long size) | ||
478 | { | ||
479 | efi_status_t status; | ||
480 | u32 width, height; | ||
481 | void **uga_handle = NULL; | ||
482 | |||
483 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
484 | size, (void **)&uga_handle); | ||
485 | if (status != EFI_SUCCESS) | ||
486 | return status; | ||
487 | |||
488 | status = efi_call_early(locate_handle, | ||
489 | EFI_LOCATE_BY_PROTOCOL, | ||
490 | uga_proto, NULL, &size, uga_handle); | ||
491 | if (status != EFI_SUCCESS) | ||
492 | goto free_handle; | ||
493 | |||
494 | height = 0; | ||
495 | width = 0; | ||
496 | |||
497 | if (efi_early->is64) | ||
498 | status = setup_uga64(uga_handle, size, &width, &height); | ||
499 | else | ||
500 | status = setup_uga32(uga_handle, size, &width, &height); | ||
501 | |||
502 | if (!width && !height) | 319 | if (!width && !height) |
503 | goto free_handle; | 320 | goto free_handle; |
504 | 321 | ||
505 | /* EFI framebuffer */ | 322 | /* EFI framebuffer */ |
506 | si->orig_video_isVGA = VIDEO_TYPE_EFI; | 323 | si->orig_video_isVGA = VIDEO_TYPE_EFI; |
507 | 324 | ||
508 | si->lfb_depth = 32; | 325 | si->lfb_depth = 32; |
509 | si->lfb_width = width; | 326 | si->lfb_width = width; |
510 | si->lfb_height = height; | 327 | si->lfb_height = height; |
511 | 328 | ||
512 | si->red_size = 8; | 329 | si->red_size = 8; |
513 | si->red_pos = 16; | 330 | si->red_pos = 16; |
514 | si->green_size = 8; | 331 | si->green_size = 8; |
515 | si->green_pos = 8; | 332 | si->green_pos = 8; |
516 | si->blue_size = 8; | 333 | si->blue_size = 8; |
517 | si->blue_pos = 0; | 334 | si->blue_pos = 0; |
518 | si->rsvd_size = 8; | 335 | si->rsvd_size = 8; |
519 | si->rsvd_pos = 24; | 336 | si->rsvd_pos = 24; |
520 | 337 | ||
521 | free_handle: | 338 | free_handle: |
522 | efi_call_early(free_pool, uga_handle); | 339 | efi_call_early(free_pool, uga_handle); |
340 | |||
523 | return status; | 341 | return status; |
524 | } | 342 | } |
525 | 343 | ||
@@ -586,7 +404,7 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
586 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 404 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
587 | return NULL; | 405 | return NULL; |
588 | 406 | ||
589 | if (efi_early->is64) | 407 | if (efi_is_64bit()) |
590 | setup_boot_services64(efi_early); | 408 | setup_boot_services64(efi_early); |
591 | else | 409 | else |
592 | setup_boot_services32(efi_early); | 410 | setup_boot_services32(efi_early); |
@@ -601,7 +419,7 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
601 | status = efi_low_alloc(sys_table, 0x4000, 1, | 419 | status = efi_low_alloc(sys_table, 0x4000, 1, |
602 | (unsigned long *)&boot_params); | 420 | (unsigned long *)&boot_params); |
603 | if (status != EFI_SUCCESS) { | 421 | if (status != EFI_SUCCESS) { |
604 | efi_printk(sys_table, "Failed to alloc lowmem for boot params\n"); | 422 | efi_printk(sys_table, "Failed to allocate lowmem for boot params\n"); |
605 | return NULL; | 423 | return NULL; |
606 | } | 424 | } |
607 | 425 | ||
@@ -617,9 +435,9 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
617 | * Fill out some of the header fields ourselves because the | 435 | * Fill out some of the header fields ourselves because the |
618 | * EFI firmware loader doesn't load the first sector. | 436 | * EFI firmware loader doesn't load the first sector. |
619 | */ | 437 | */ |
620 | hdr->root_flags = 1; | 438 | hdr->root_flags = 1; |
621 | hdr->vid_mode = 0xffff; | 439 | hdr->vid_mode = 0xffff; |
622 | hdr->boot_flag = 0xAA55; | 440 | hdr->boot_flag = 0xAA55; |
623 | 441 | ||
624 | hdr->type_of_loader = 0x21; | 442 | hdr->type_of_loader = 0x21; |
625 | 443 | ||
@@ -627,6 +445,7 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
627 | cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size); | 445 | cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size); |
628 | if (!cmdline_ptr) | 446 | if (!cmdline_ptr) |
629 | goto fail; | 447 | goto fail; |
448 | |||
630 | hdr->cmd_line_ptr = (unsigned long)cmdline_ptr; | 449 | hdr->cmd_line_ptr = (unsigned long)cmdline_ptr; |
631 | /* Fill in upper bits of command line address, NOP on 32 bit */ | 450 | /* Fill in upper bits of command line address, NOP on 32 bit */ |
632 | boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32; | 451 | boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32; |
@@ -663,10 +482,12 @@ struct boot_params *make_boot_params(struct efi_config *c) | |||
663 | boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; | 482 | boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; |
664 | 483 | ||
665 | return boot_params; | 484 | return boot_params; |
485 | |||
666 | fail2: | 486 | fail2: |
667 | efi_free(sys_table, options_size, hdr->cmd_line_ptr); | 487 | efi_free(sys_table, options_size, hdr->cmd_line_ptr); |
668 | fail: | 488 | fail: |
669 | efi_free(sys_table, 0x4000, (unsigned long)boot_params); | 489 | efi_free(sys_table, 0x4000, (unsigned long)boot_params); |
490 | |||
670 | return NULL; | 491 | return NULL; |
671 | } | 492 | } |
672 | 493 | ||
@@ -678,7 +499,7 @@ static void add_e820ext(struct boot_params *params, | |||
678 | unsigned long size; | 499 | unsigned long size; |
679 | 500 | ||
680 | e820ext->type = SETUP_E820_EXT; | 501 | e820ext->type = SETUP_E820_EXT; |
681 | e820ext->len = nr_entries * sizeof(struct boot_e820_entry); | 502 | e820ext->len = nr_entries * sizeof(struct boot_e820_entry); |
682 | e820ext->next = 0; | 503 | e820ext->next = 0; |
683 | 504 | ||
684 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; | 505 | data = (struct setup_data *)(unsigned long)params->hdr.setup_data; |
@@ -692,8 +513,8 @@ static void add_e820ext(struct boot_params *params, | |||
692 | params->hdr.setup_data = (unsigned long)e820ext; | 513 | params->hdr.setup_data = (unsigned long)e820ext; |
693 | } | 514 | } |
694 | 515 | ||
695 | static efi_status_t setup_e820(struct boot_params *params, | 516 | static efi_status_t |
696 | struct setup_data *e820ext, u32 e820ext_size) | 517 | setup_e820(struct boot_params *params, struct setup_data *e820ext, u32 e820ext_size) |
697 | { | 518 | { |
698 | struct boot_e820_entry *entry = params->e820_table; | 519 | struct boot_e820_entry *entry = params->e820_table; |
699 | struct efi_info *efi = ¶ms->efi_info; | 520 | struct efi_info *efi = ¶ms->efi_info; |
@@ -814,11 +635,10 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, | |||
814 | } | 635 | } |
815 | 636 | ||
816 | struct exit_boot_struct { | 637 | struct exit_boot_struct { |
817 | struct boot_params *boot_params; | 638 | struct boot_params *boot_params; |
818 | struct efi_info *efi; | 639 | struct efi_info *efi; |
819 | struct setup_data *e820ext; | 640 | struct setup_data *e820ext; |
820 | __u32 e820ext_size; | 641 | __u32 e820ext_size; |
821 | bool is64; | ||
822 | }; | 642 | }; |
823 | 643 | ||
824 | static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, | 644 | static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, |
@@ -845,25 +665,25 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, | |||
845 | first = false; | 665 | first = false; |
846 | } | 666 | } |
847 | 667 | ||
848 | signature = p->is64 ? EFI64_LOADER_SIGNATURE : EFI32_LOADER_SIGNATURE; | 668 | signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE |
669 | : EFI32_LOADER_SIGNATURE; | ||
849 | memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32)); | 670 | memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32)); |
850 | 671 | ||
851 | p->efi->efi_systab = (unsigned long)sys_table_arg; | 672 | p->efi->efi_systab = (unsigned long)sys_table_arg; |
852 | p->efi->efi_memdesc_size = *map->desc_size; | 673 | p->efi->efi_memdesc_size = *map->desc_size; |
853 | p->efi->efi_memdesc_version = *map->desc_ver; | 674 | p->efi->efi_memdesc_version = *map->desc_ver; |
854 | p->efi->efi_memmap = (unsigned long)*map->map; | 675 | p->efi->efi_memmap = (unsigned long)*map->map; |
855 | p->efi->efi_memmap_size = *map->map_size; | 676 | p->efi->efi_memmap_size = *map->map_size; |
856 | 677 | ||
857 | #ifdef CONFIG_X86_64 | 678 | #ifdef CONFIG_X86_64 |
858 | p->efi->efi_systab_hi = (unsigned long)sys_table_arg >> 32; | 679 | p->efi->efi_systab_hi = (unsigned long)sys_table_arg >> 32; |
859 | p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32; | 680 | p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32; |
860 | #endif | 681 | #endif |
861 | 682 | ||
862 | return EFI_SUCCESS; | 683 | return EFI_SUCCESS; |
863 | } | 684 | } |
864 | 685 | ||
865 | static efi_status_t exit_boot(struct boot_params *boot_params, | 686 | static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) |
866 | void *handle, bool is64) | ||
867 | { | 687 | { |
868 | unsigned long map_sz, key, desc_size, buff_size; | 688 | unsigned long map_sz, key, desc_size, buff_size; |
869 | efi_memory_desc_t *mem_map; | 689 | efi_memory_desc_t *mem_map; |
@@ -874,17 +694,16 @@ static efi_status_t exit_boot(struct boot_params *boot_params, | |||
874 | struct efi_boot_memmap map; | 694 | struct efi_boot_memmap map; |
875 | struct exit_boot_struct priv; | 695 | struct exit_boot_struct priv; |
876 | 696 | ||
877 | map.map = &mem_map; | 697 | map.map = &mem_map; |
878 | map.map_size = &map_sz; | 698 | map.map_size = &map_sz; |
879 | map.desc_size = &desc_size; | 699 | map.desc_size = &desc_size; |
880 | map.desc_ver = &desc_version; | 700 | map.desc_ver = &desc_version; |
881 | map.key_ptr = &key; | 701 | map.key_ptr = &key; |
882 | map.buff_size = &buff_size; | 702 | map.buff_size = &buff_size; |
883 | priv.boot_params = boot_params; | 703 | priv.boot_params = boot_params; |
884 | priv.efi = &boot_params->efi_info; | 704 | priv.efi = &boot_params->efi_info; |
885 | priv.e820ext = NULL; | 705 | priv.e820ext = NULL; |
886 | priv.e820ext_size = 0; | 706 | priv.e820ext_size = 0; |
887 | priv.is64 = is64; | ||
888 | 707 | ||
889 | /* Might as well exit boot services now */ | 708 | /* Might as well exit boot services now */ |
890 | status = efi_exit_boot_services(sys_table, handle, &map, &priv, | 709 | status = efi_exit_boot_services(sys_table, handle, &map, &priv, |
@@ -892,10 +711,11 @@ static efi_status_t exit_boot(struct boot_params *boot_params, | |||
892 | if (status != EFI_SUCCESS) | 711 | if (status != EFI_SUCCESS) |
893 | return status; | 712 | return status; |
894 | 713 | ||
895 | e820ext = priv.e820ext; | 714 | e820ext = priv.e820ext; |
896 | e820ext_size = priv.e820ext_size; | 715 | e820ext_size = priv.e820ext_size; |
716 | |||
897 | /* Historic? */ | 717 | /* Historic? */ |
898 | boot_params->alt_mem_k = 32 * 1024; | 718 | boot_params->alt_mem_k = 32 * 1024; |
899 | 719 | ||
900 | status = setup_e820(boot_params, e820ext, e820ext_size); | 720 | status = setup_e820(boot_params, e820ext, e820ext_size); |
901 | if (status != EFI_SUCCESS) | 721 | if (status != EFI_SUCCESS) |
@@ -908,8 +728,8 @@ static efi_status_t exit_boot(struct boot_params *boot_params, | |||
908 | * On success we return a pointer to a boot_params structure, and NULL | 728 | * On success we return a pointer to a boot_params structure, and NULL |
909 | * on failure. | 729 | * on failure. |
910 | */ | 730 | */ |
911 | struct boot_params *efi_main(struct efi_config *c, | 731 | struct boot_params * |
912 | struct boot_params *boot_params) | 732 | efi_main(struct efi_config *c, struct boot_params *boot_params) |
913 | { | 733 | { |
914 | struct desc_ptr *gdt = NULL; | 734 | struct desc_ptr *gdt = NULL; |
915 | efi_loaded_image_t *image; | 735 | efi_loaded_image_t *image; |
@@ -918,13 +738,11 @@ struct boot_params *efi_main(struct efi_config *c, | |||
918 | struct desc_struct *desc; | 738 | struct desc_struct *desc; |
919 | void *handle; | 739 | void *handle; |
920 | efi_system_table_t *_table; | 740 | efi_system_table_t *_table; |
921 | bool is64; | ||
922 | 741 | ||
923 | efi_early = c; | 742 | efi_early = c; |
924 | 743 | ||
925 | _table = (efi_system_table_t *)(unsigned long)efi_early->table; | 744 | _table = (efi_system_table_t *)(unsigned long)efi_early->table; |
926 | handle = (void *)(unsigned long)efi_early->image_handle; | 745 | handle = (void *)(unsigned long)efi_early->image_handle; |
927 | is64 = efi_early->is64; | ||
928 | 746 | ||
929 | sys_table = _table; | 747 | sys_table = _table; |
930 | 748 | ||
@@ -932,7 +750,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
932 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 750 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
933 | goto fail; | 751 | goto fail; |
934 | 752 | ||
935 | if (is64) | 753 | if (efi_is_64bit()) |
936 | setup_boot_services64(efi_early); | 754 | setup_boot_services64(efi_early); |
937 | else | 755 | else |
938 | setup_boot_services32(efi_early); | 756 | setup_boot_services32(efi_early); |
@@ -957,7 +775,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
957 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | 775 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, |
958 | sizeof(*gdt), (void **)&gdt); | 776 | sizeof(*gdt), (void **)&gdt); |
959 | if (status != EFI_SUCCESS) { | 777 | if (status != EFI_SUCCESS) { |
960 | efi_printk(sys_table, "Failed to alloc mem for gdt structure\n"); | 778 | efi_printk(sys_table, "Failed to allocate memory for 'gdt' structure\n"); |
961 | goto fail; | 779 | goto fail; |
962 | } | 780 | } |
963 | 781 | ||
@@ -965,7 +783,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
965 | status = efi_low_alloc(sys_table, gdt->size, 8, | 783 | status = efi_low_alloc(sys_table, gdt->size, 8, |
966 | (unsigned long *)&gdt->address); | 784 | (unsigned long *)&gdt->address); |
967 | if (status != EFI_SUCCESS) { | 785 | if (status != EFI_SUCCESS) { |
968 | efi_printk(sys_table, "Failed to alloc mem for gdt\n"); | 786 | efi_printk(sys_table, "Failed to allocate memory for 'gdt'\n"); |
969 | goto fail; | 787 | goto fail; |
970 | } | 788 | } |
971 | 789 | ||
@@ -988,7 +806,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
988 | hdr->code32_start = bzimage_addr; | 806 | hdr->code32_start = bzimage_addr; |
989 | } | 807 | } |
990 | 808 | ||
991 | status = exit_boot(boot_params, handle, is64); | 809 | status = exit_boot(boot_params, handle); |
992 | if (status != EFI_SUCCESS) { | 810 | if (status != EFI_SUCCESS) { |
993 | efi_printk(sys_table, "exit_boot() failed!\n"); | 811 | efi_printk(sys_table, "exit_boot() failed!\n"); |
994 | goto fail; | 812 | goto fail; |
@@ -1002,19 +820,20 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1002 | 820 | ||
1003 | if (IS_ENABLED(CONFIG_X86_64)) { | 821 | if (IS_ENABLED(CONFIG_X86_64)) { |
1004 | /* __KERNEL32_CS */ | 822 | /* __KERNEL32_CS */ |
1005 | desc->limit0 = 0xffff; | 823 | desc->limit0 = 0xffff; |
1006 | desc->base0 = 0x0000; | 824 | desc->base0 = 0x0000; |
1007 | desc->base1 = 0x0000; | 825 | desc->base1 = 0x0000; |
1008 | desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; | 826 | desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; |
1009 | desc->s = DESC_TYPE_CODE_DATA; | 827 | desc->s = DESC_TYPE_CODE_DATA; |
1010 | desc->dpl = 0; | 828 | desc->dpl = 0; |
1011 | desc->p = 1; | 829 | desc->p = 1; |
1012 | desc->limit1 = 0xf; | 830 | desc->limit1 = 0xf; |
1013 | desc->avl = 0; | 831 | desc->avl = 0; |
1014 | desc->l = 0; | 832 | desc->l = 0; |
1015 | desc->d = SEG_OP_SIZE_32BIT; | 833 | desc->d = SEG_OP_SIZE_32BIT; |
1016 | desc->g = SEG_GRANULARITY_4KB; | 834 | desc->g = SEG_GRANULARITY_4KB; |
1017 | desc->base2 = 0x00; | 835 | desc->base2 = 0x00; |
836 | |||
1018 | desc++; | 837 | desc++; |
1019 | } else { | 838 | } else { |
1020 | /* Second entry is unused on 32-bit */ | 839 | /* Second entry is unused on 32-bit */ |
@@ -1022,15 +841,16 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1022 | } | 841 | } |
1023 | 842 | ||
1024 | /* __KERNEL_CS */ | 843 | /* __KERNEL_CS */ |
1025 | desc->limit0 = 0xffff; | 844 | desc->limit0 = 0xffff; |
1026 | desc->base0 = 0x0000; | 845 | desc->base0 = 0x0000; |
1027 | desc->base1 = 0x0000; | 846 | desc->base1 = 0x0000; |
1028 | desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; | 847 | desc->type = SEG_TYPE_CODE | SEG_TYPE_EXEC_READ; |
1029 | desc->s = DESC_TYPE_CODE_DATA; | 848 | desc->s = DESC_TYPE_CODE_DATA; |
1030 | desc->dpl = 0; | 849 | desc->dpl = 0; |
1031 | desc->p = 1; | 850 | desc->p = 1; |
1032 | desc->limit1 = 0xf; | 851 | desc->limit1 = 0xf; |
1033 | desc->avl = 0; | 852 | desc->avl = 0; |
853 | |||
1034 | if (IS_ENABLED(CONFIG_X86_64)) { | 854 | if (IS_ENABLED(CONFIG_X86_64)) { |
1035 | desc->l = 1; | 855 | desc->l = 1; |
1036 | desc->d = 0; | 856 | desc->d = 0; |
@@ -1038,41 +858,41 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1038 | desc->l = 0; | 858 | desc->l = 0; |
1039 | desc->d = SEG_OP_SIZE_32BIT; | 859 | desc->d = SEG_OP_SIZE_32BIT; |
1040 | } | 860 | } |
1041 | desc->g = SEG_GRANULARITY_4KB; | 861 | desc->g = SEG_GRANULARITY_4KB; |
1042 | desc->base2 = 0x00; | 862 | desc->base2 = 0x00; |
1043 | desc++; | 863 | desc++; |
1044 | 864 | ||
1045 | /* __KERNEL_DS */ | 865 | /* __KERNEL_DS */ |
1046 | desc->limit0 = 0xffff; | 866 | desc->limit0 = 0xffff; |
1047 | desc->base0 = 0x0000; | 867 | desc->base0 = 0x0000; |
1048 | desc->base1 = 0x0000; | 868 | desc->base1 = 0x0000; |
1049 | desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE; | 869 | desc->type = SEG_TYPE_DATA | SEG_TYPE_READ_WRITE; |
1050 | desc->s = DESC_TYPE_CODE_DATA; | 870 | desc->s = DESC_TYPE_CODE_DATA; |
1051 | desc->dpl = 0; | 871 | desc->dpl = 0; |
1052 | desc->p = 1; | 872 | desc->p = 1; |
1053 | desc->limit1 = 0xf; | 873 | desc->limit1 = 0xf; |
1054 | desc->avl = 0; | 874 | desc->avl = 0; |
1055 | desc->l = 0; | 875 | desc->l = 0; |
1056 | desc->d = SEG_OP_SIZE_32BIT; | 876 | desc->d = SEG_OP_SIZE_32BIT; |
1057 | desc->g = SEG_GRANULARITY_4KB; | 877 | desc->g = SEG_GRANULARITY_4KB; |
1058 | desc->base2 = 0x00; | 878 | desc->base2 = 0x00; |
1059 | desc++; | 879 | desc++; |
1060 | 880 | ||
1061 | if (IS_ENABLED(CONFIG_X86_64)) { | 881 | if (IS_ENABLED(CONFIG_X86_64)) { |
1062 | /* Task segment value */ | 882 | /* Task segment value */ |
1063 | desc->limit0 = 0x0000; | 883 | desc->limit0 = 0x0000; |
1064 | desc->base0 = 0x0000; | 884 | desc->base0 = 0x0000; |
1065 | desc->base1 = 0x0000; | 885 | desc->base1 = 0x0000; |
1066 | desc->type = SEG_TYPE_TSS; | 886 | desc->type = SEG_TYPE_TSS; |
1067 | desc->s = 0; | 887 | desc->s = 0; |
1068 | desc->dpl = 0; | 888 | desc->dpl = 0; |
1069 | desc->p = 1; | 889 | desc->p = 1; |
1070 | desc->limit1 = 0x0; | 890 | desc->limit1 = 0x0; |
1071 | desc->avl = 0; | 891 | desc->avl = 0; |
1072 | desc->l = 0; | 892 | desc->l = 0; |
1073 | desc->d = 0; | 893 | desc->d = 0; |
1074 | desc->g = SEG_GRANULARITY_4KB; | 894 | desc->g = SEG_GRANULARITY_4KB; |
1075 | desc->base2 = 0x00; | 895 | desc->base2 = 0x00; |
1076 | desc++; | 896 | desc++; |
1077 | } | 897 | } |
1078 | 898 | ||
@@ -1082,5 +902,6 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1082 | return boot_params; | 902 | return boot_params; |
1083 | fail: | 903 | fail: |
1084 | efi_printk(sys_table, "efi_main() failed!\n"); | 904 | efi_printk(sys_table, "efi_main() failed!\n"); |
905 | |||
1085 | return NULL; | 906 | return NULL; |
1086 | } | 907 | } |
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index e799dc5c6448..8297387c4676 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -12,22 +12,22 @@ | |||
12 | 12 | ||
13 | #define DESC_TYPE_CODE_DATA (1 << 0) | 13 | #define DESC_TYPE_CODE_DATA (1 << 0) |
14 | 14 | ||
15 | struct efi_uga_draw_protocol_32 { | 15 | typedef struct { |
16 | u32 get_mode; | 16 | u32 get_mode; |
17 | u32 set_mode; | 17 | u32 set_mode; |
18 | u32 blt; | 18 | u32 blt; |
19 | }; | 19 | } efi_uga_draw_protocol_32_t; |
20 | 20 | ||
21 | struct efi_uga_draw_protocol_64 { | 21 | typedef struct { |
22 | u64 get_mode; | 22 | u64 get_mode; |
23 | u64 set_mode; | 23 | u64 set_mode; |
24 | u64 blt; | 24 | u64 blt; |
25 | }; | 25 | } efi_uga_draw_protocol_64_t; |
26 | 26 | ||
27 | struct efi_uga_draw_protocol { | 27 | typedef struct { |
28 | void *get_mode; | 28 | void *get_mode; |
29 | void *set_mode; | 29 | void *set_mode; |
30 | void *blt; | 30 | void *blt; |
31 | }; | 31 | } efi_uga_draw_protocol_t; |
32 | 32 | ||
33 | #endif /* BOOT_COMPRESSED_EBOOT_H */ | 33 | #endif /* BOOT_COMPRESSED_EBOOT_H */ |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 5f2eb3231607..ee5d08f25ce4 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -636,6 +636,8 @@ void efi_switch_mm(struct mm_struct *mm) | |||
636 | #ifdef CONFIG_EFI_MIXED | 636 | #ifdef CONFIG_EFI_MIXED |
637 | extern efi_status_t efi64_thunk(u32, ...); | 637 | extern efi_status_t efi64_thunk(u32, ...); |
638 | 638 | ||
639 | static DEFINE_SPINLOCK(efi_runtime_lock); | ||
640 | |||
639 | #define runtime_service32(func) \ | 641 | #define runtime_service32(func) \ |
640 | ({ \ | 642 | ({ \ |
641 | u32 table = (u32)(unsigned long)efi.systab; \ | 643 | u32 table = (u32)(unsigned long)efi.systab; \ |
@@ -657,17 +659,14 @@ extern efi_status_t efi64_thunk(u32, ...); | |||
657 | #define efi_thunk(f, ...) \ | 659 | #define efi_thunk(f, ...) \ |
658 | ({ \ | 660 | ({ \ |
659 | efi_status_t __s; \ | 661 | efi_status_t __s; \ |
660 | unsigned long __flags; \ | ||
661 | u32 __func; \ | 662 | u32 __func; \ |
662 | \ | 663 | \ |
663 | local_irq_save(__flags); \ | ||
664 | arch_efi_call_virt_setup(); \ | 664 | arch_efi_call_virt_setup(); \ |
665 | \ | 665 | \ |
666 | __func = runtime_service32(f); \ | 666 | __func = runtime_service32(f); \ |
667 | __s = efi64_thunk(__func, __VA_ARGS__); \ | 667 | __s = efi64_thunk(__func, __VA_ARGS__); \ |
668 | \ | 668 | \ |
669 | arch_efi_call_virt_teardown(); \ | 669 | arch_efi_call_virt_teardown(); \ |
670 | local_irq_restore(__flags); \ | ||
671 | \ | 670 | \ |
672 | __s; \ | 671 | __s; \ |
673 | }) | 672 | }) |
@@ -702,14 +701,17 @@ static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc) | |||
702 | { | 701 | { |
703 | efi_status_t status; | 702 | efi_status_t status; |
704 | u32 phys_tm, phys_tc; | 703 | u32 phys_tm, phys_tc; |
704 | unsigned long flags; | ||
705 | 705 | ||
706 | spin_lock(&rtc_lock); | 706 | spin_lock(&rtc_lock); |
707 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
707 | 708 | ||
708 | phys_tm = virt_to_phys_or_null(tm); | 709 | phys_tm = virt_to_phys_or_null(tm); |
709 | phys_tc = virt_to_phys_or_null(tc); | 710 | phys_tc = virt_to_phys_or_null(tc); |
710 | 711 | ||
711 | status = efi_thunk(get_time, phys_tm, phys_tc); | 712 | status = efi_thunk(get_time, phys_tm, phys_tc); |
712 | 713 | ||
714 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
713 | spin_unlock(&rtc_lock); | 715 | spin_unlock(&rtc_lock); |
714 | 716 | ||
715 | return status; | 717 | return status; |
@@ -719,13 +721,16 @@ static efi_status_t efi_thunk_set_time(efi_time_t *tm) | |||
719 | { | 721 | { |
720 | efi_status_t status; | 722 | efi_status_t status; |
721 | u32 phys_tm; | 723 | u32 phys_tm; |
724 | unsigned long flags; | ||
722 | 725 | ||
723 | spin_lock(&rtc_lock); | 726 | spin_lock(&rtc_lock); |
727 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
724 | 728 | ||
725 | phys_tm = virt_to_phys_or_null(tm); | 729 | phys_tm = virt_to_phys_or_null(tm); |
726 | 730 | ||
727 | status = efi_thunk(set_time, phys_tm); | 731 | status = efi_thunk(set_time, phys_tm); |
728 | 732 | ||
733 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
729 | spin_unlock(&rtc_lock); | 734 | spin_unlock(&rtc_lock); |
730 | 735 | ||
731 | return status; | 736 | return status; |
@@ -737,8 +742,10 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending, | |||
737 | { | 742 | { |
738 | efi_status_t status; | 743 | efi_status_t status; |
739 | u32 phys_enabled, phys_pending, phys_tm; | 744 | u32 phys_enabled, phys_pending, phys_tm; |
745 | unsigned long flags; | ||
740 | 746 | ||
741 | spin_lock(&rtc_lock); | 747 | spin_lock(&rtc_lock); |
748 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
742 | 749 | ||
743 | phys_enabled = virt_to_phys_or_null(enabled); | 750 | phys_enabled = virt_to_phys_or_null(enabled); |
744 | phys_pending = virt_to_phys_or_null(pending); | 751 | phys_pending = virt_to_phys_or_null(pending); |
@@ -747,6 +754,7 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending, | |||
747 | status = efi_thunk(get_wakeup_time, phys_enabled, | 754 | status = efi_thunk(get_wakeup_time, phys_enabled, |
748 | phys_pending, phys_tm); | 755 | phys_pending, phys_tm); |
749 | 756 | ||
757 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
750 | spin_unlock(&rtc_lock); | 758 | spin_unlock(&rtc_lock); |
751 | 759 | ||
752 | return status; | 760 | return status; |
@@ -757,13 +765,16 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | |||
757 | { | 765 | { |
758 | efi_status_t status; | 766 | efi_status_t status; |
759 | u32 phys_tm; | 767 | u32 phys_tm; |
768 | unsigned long flags; | ||
760 | 769 | ||
761 | spin_lock(&rtc_lock); | 770 | spin_lock(&rtc_lock); |
771 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
762 | 772 | ||
763 | phys_tm = virt_to_phys_or_null(tm); | 773 | phys_tm = virt_to_phys_or_null(tm); |
764 | 774 | ||
765 | status = efi_thunk(set_wakeup_time, enabled, phys_tm); | 775 | status = efi_thunk(set_wakeup_time, enabled, phys_tm); |
766 | 776 | ||
777 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
767 | spin_unlock(&rtc_lock); | 778 | spin_unlock(&rtc_lock); |
768 | 779 | ||
769 | return status; | 780 | return status; |
@@ -781,6 +792,9 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor, | |||
781 | efi_status_t status; | 792 | efi_status_t status; |
782 | u32 phys_name, phys_vendor, phys_attr; | 793 | u32 phys_name, phys_vendor, phys_attr; |
783 | u32 phys_data_size, phys_data; | 794 | u32 phys_data_size, phys_data; |
795 | unsigned long flags; | ||
796 | |||
797 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
784 | 798 | ||
785 | phys_data_size = virt_to_phys_or_null(data_size); | 799 | phys_data_size = virt_to_phys_or_null(data_size); |
786 | phys_vendor = virt_to_phys_or_null(vendor); | 800 | phys_vendor = virt_to_phys_or_null(vendor); |
@@ -791,6 +805,8 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor, | |||
791 | status = efi_thunk(get_variable, phys_name, phys_vendor, | 805 | status = efi_thunk(get_variable, phys_name, phys_vendor, |
792 | phys_attr, phys_data_size, phys_data); | 806 | phys_attr, phys_data_size, phys_data); |
793 | 807 | ||
808 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
809 | |||
794 | return status; | 810 | return status; |
795 | } | 811 | } |
796 | 812 | ||
@@ -800,6 +816,34 @@ efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor, | |||
800 | { | 816 | { |
801 | u32 phys_name, phys_vendor, phys_data; | 817 | u32 phys_name, phys_vendor, phys_data; |
802 | efi_status_t status; | 818 | efi_status_t status; |
819 | unsigned long flags; | ||
820 | |||
821 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
822 | |||
823 | phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); | ||
824 | phys_vendor = virt_to_phys_or_null(vendor); | ||
825 | phys_data = virt_to_phys_or_null_size(data, data_size); | ||
826 | |||
827 | /* If data_size is > sizeof(u32) we've got problems */ | ||
828 | status = efi_thunk(set_variable, phys_name, phys_vendor, | ||
829 | attr, data_size, phys_data); | ||
830 | |||
831 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
832 | |||
833 | return status; | ||
834 | } | ||
835 | |||
836 | static efi_status_t | ||
837 | efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, | ||
838 | u32 attr, unsigned long data_size, | ||
839 | void *data) | ||
840 | { | ||
841 | u32 phys_name, phys_vendor, phys_data; | ||
842 | efi_status_t status; | ||
843 | unsigned long flags; | ||
844 | |||
845 | if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) | ||
846 | return EFI_NOT_READY; | ||
803 | 847 | ||
804 | phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); | 848 | phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); |
805 | phys_vendor = virt_to_phys_or_null(vendor); | 849 | phys_vendor = virt_to_phys_or_null(vendor); |
@@ -809,6 +853,8 @@ efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor, | |||
809 | status = efi_thunk(set_variable, phys_name, phys_vendor, | 853 | status = efi_thunk(set_variable, phys_name, phys_vendor, |
810 | attr, data_size, phys_data); | 854 | attr, data_size, phys_data); |
811 | 855 | ||
856 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
857 | |||
812 | return status; | 858 | return status; |
813 | } | 859 | } |
814 | 860 | ||
@@ -819,6 +865,9 @@ efi_thunk_get_next_variable(unsigned long *name_size, | |||
819 | { | 865 | { |
820 | efi_status_t status; | 866 | efi_status_t status; |
821 | u32 phys_name_size, phys_name, phys_vendor; | 867 | u32 phys_name_size, phys_name, phys_vendor; |
868 | unsigned long flags; | ||
869 | |||
870 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
822 | 871 | ||
823 | phys_name_size = virt_to_phys_or_null(name_size); | 872 | phys_name_size = virt_to_phys_or_null(name_size); |
824 | phys_vendor = virt_to_phys_or_null(vendor); | 873 | phys_vendor = virt_to_phys_or_null(vendor); |
@@ -827,6 +876,8 @@ efi_thunk_get_next_variable(unsigned long *name_size, | |||
827 | status = efi_thunk(get_next_variable, phys_name_size, | 876 | status = efi_thunk(get_next_variable, phys_name_size, |
828 | phys_name, phys_vendor); | 877 | phys_name, phys_vendor); |
829 | 878 | ||
879 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
880 | |||
830 | return status; | 881 | return status; |
831 | } | 882 | } |
832 | 883 | ||
@@ -835,10 +886,15 @@ efi_thunk_get_next_high_mono_count(u32 *count) | |||
835 | { | 886 | { |
836 | efi_status_t status; | 887 | efi_status_t status; |
837 | u32 phys_count; | 888 | u32 phys_count; |
889 | unsigned long flags; | ||
890 | |||
891 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
838 | 892 | ||
839 | phys_count = virt_to_phys_or_null(count); | 893 | phys_count = virt_to_phys_or_null(count); |
840 | status = efi_thunk(get_next_high_mono_count, phys_count); | 894 | status = efi_thunk(get_next_high_mono_count, phys_count); |
841 | 895 | ||
896 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
897 | |||
842 | return status; | 898 | return status; |
843 | } | 899 | } |
844 | 900 | ||
@@ -847,10 +903,15 @@ efi_thunk_reset_system(int reset_type, efi_status_t status, | |||
847 | unsigned long data_size, efi_char16_t *data) | 903 | unsigned long data_size, efi_char16_t *data) |
848 | { | 904 | { |
849 | u32 phys_data; | 905 | u32 phys_data; |
906 | unsigned long flags; | ||
907 | |||
908 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
850 | 909 | ||
851 | phys_data = virt_to_phys_or_null_size(data, data_size); | 910 | phys_data = virt_to_phys_or_null_size(data, data_size); |
852 | 911 | ||
853 | efi_thunk(reset_system, reset_type, status, data_size, phys_data); | 912 | efi_thunk(reset_system, reset_type, status, data_size, phys_data); |
913 | |||
914 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
854 | } | 915 | } |
855 | 916 | ||
856 | static efi_status_t | 917 | static efi_status_t |
@@ -872,10 +933,13 @@ efi_thunk_query_variable_info(u32 attr, u64 *storage_space, | |||
872 | { | 933 | { |
873 | efi_status_t status; | 934 | efi_status_t status; |
874 | u32 phys_storage, phys_remaining, phys_max; | 935 | u32 phys_storage, phys_remaining, phys_max; |
936 | unsigned long flags; | ||
875 | 937 | ||
876 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | 938 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) |
877 | return EFI_UNSUPPORTED; | 939 | return EFI_UNSUPPORTED; |
878 | 940 | ||
941 | spin_lock_irqsave(&efi_runtime_lock, flags); | ||
942 | |||
879 | phys_storage = virt_to_phys_or_null(storage_space); | 943 | phys_storage = virt_to_phys_or_null(storage_space); |
880 | phys_remaining = virt_to_phys_or_null(remaining_space); | 944 | phys_remaining = virt_to_phys_or_null(remaining_space); |
881 | phys_max = virt_to_phys_or_null(max_variable_size); | 945 | phys_max = virt_to_phys_or_null(max_variable_size); |
@@ -883,6 +947,35 @@ efi_thunk_query_variable_info(u32 attr, u64 *storage_space, | |||
883 | status = efi_thunk(query_variable_info, attr, phys_storage, | 947 | status = efi_thunk(query_variable_info, attr, phys_storage, |
884 | phys_remaining, phys_max); | 948 | phys_remaining, phys_max); |
885 | 949 | ||
950 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
951 | |||
952 | return status; | ||
953 | } | ||
954 | |||
955 | static efi_status_t | ||
956 | efi_thunk_query_variable_info_nonblocking(u32 attr, u64 *storage_space, | ||
957 | u64 *remaining_space, | ||
958 | u64 *max_variable_size) | ||
959 | { | ||
960 | efi_status_t status; | ||
961 | u32 phys_storage, phys_remaining, phys_max; | ||
962 | unsigned long flags; | ||
963 | |||
964 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
965 | return EFI_UNSUPPORTED; | ||
966 | |||
967 | if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) | ||
968 | return EFI_NOT_READY; | ||
969 | |||
970 | phys_storage = virt_to_phys_or_null(storage_space); | ||
971 | phys_remaining = virt_to_phys_or_null(remaining_space); | ||
972 | phys_max = virt_to_phys_or_null(max_variable_size); | ||
973 | |||
974 | status = efi_thunk(query_variable_info, attr, phys_storage, | ||
975 | phys_remaining, phys_max); | ||
976 | |||
977 | spin_unlock_irqrestore(&efi_runtime_lock, flags); | ||
978 | |||
886 | return status; | 979 | return status; |
887 | } | 980 | } |
888 | 981 | ||
@@ -908,9 +1001,11 @@ void efi_thunk_runtime_setup(void) | |||
908 | efi.get_variable = efi_thunk_get_variable; | 1001 | efi.get_variable = efi_thunk_get_variable; |
909 | efi.get_next_variable = efi_thunk_get_next_variable; | 1002 | efi.get_next_variable = efi_thunk_get_next_variable; |
910 | efi.set_variable = efi_thunk_set_variable; | 1003 | efi.set_variable = efi_thunk_set_variable; |
1004 | efi.set_variable_nonblocking = efi_thunk_set_variable_nonblocking; | ||
911 | efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count; | 1005 | efi.get_next_high_mono_count = efi_thunk_get_next_high_mono_count; |
912 | efi.reset_system = efi_thunk_reset_system; | 1006 | efi.reset_system = efi_thunk_reset_system; |
913 | efi.query_variable_info = efi_thunk_query_variable_info; | 1007 | efi.query_variable_info = efi_thunk_query_variable_info; |
1008 | efi.query_variable_info_nonblocking = efi_thunk_query_variable_info_nonblocking; | ||
914 | efi.update_capsule = efi_thunk_update_capsule; | 1009 | efi.update_capsule = efi_thunk_update_capsule; |
915 | efi.query_capsule_caps = efi_thunk_query_capsule_caps; | 1010 | efi.query_capsule_caps = efi_thunk_query_capsule_caps; |
916 | } | 1011 | } |
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 36c1f8b9f7e0..844d31cb8a0c 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -105,12 +105,11 @@ early_param("efi_no_storage_paranoia", setup_storage_paranoia); | |||
105 | */ | 105 | */ |
106 | void efi_delete_dummy_variable(void) | 106 | void efi_delete_dummy_variable(void) |
107 | { | 107 | { |
108 | efi.set_variable((efi_char16_t *)efi_dummy_name, | 108 | efi.set_variable_nonblocking((efi_char16_t *)efi_dummy_name, |
109 | &EFI_DUMMY_GUID, | 109 | &EFI_DUMMY_GUID, |
110 | EFI_VARIABLE_NON_VOLATILE | | 110 | EFI_VARIABLE_NON_VOLATILE | |
111 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | 111 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
112 | EFI_VARIABLE_RUNTIME_ACCESS, | 112 | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); |
113 | 0, NULL); | ||
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* |
@@ -249,7 +248,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) | |||
249 | int num_entries; | 248 | int num_entries; |
250 | void *new; | 249 | void *new; |
251 | 250 | ||
252 | if (efi_mem_desc_lookup(addr, &md)) { | 251 | if (efi_mem_desc_lookup(addr, &md) || |
252 | md.type != EFI_BOOT_SERVICES_DATA) { | ||
253 | pr_err("Failed to lookup EFI memory descriptor for %pa\n", &addr); | 253 | pr_err("Failed to lookup EFI memory descriptor for %pa\n", &addr); |
254 | return; | 254 | return; |
255 | } | 255 | } |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 781a4a337557..d8e159feb573 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -87,6 +87,18 @@ config EFI_RUNTIME_WRAPPERS | |||
87 | config EFI_ARMSTUB | 87 | config EFI_ARMSTUB |
88 | bool | 88 | bool |
89 | 89 | ||
90 | config EFI_ARMSTUB_DTB_LOADER | ||
91 | bool "Enable the DTB loader" | ||
92 | depends on EFI_ARMSTUB | ||
93 | help | ||
94 | Select this config option to add support for the dtb= command | ||
95 | line parameter, allowing a device tree blob to be loaded into | ||
96 | memory from the EFI System Partition by the stub. | ||
97 | |||
98 | The device tree is typically provided by the platform or by | ||
99 | the bootloader, so this option is mostly for development | ||
100 | purposes only. | ||
101 | |||
90 | config EFI_BOOTLOADER_CONTROL | 102 | config EFI_BOOTLOADER_CONTROL |
91 | tristate "EFI Bootloader Control" | 103 | tristate "EFI Bootloader Control" |
92 | depends on EFI_VARS | 104 | depends on EFI_VARS |
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 3bf0dca378a6..a7902fccdcfa 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c | |||
@@ -48,8 +48,21 @@ u64 cper_next_record_id(void) | |||
48 | { | 48 | { |
49 | static atomic64_t seq; | 49 | static atomic64_t seq; |
50 | 50 | ||
51 | if (!atomic64_read(&seq)) | 51 | if (!atomic64_read(&seq)) { |
52 | atomic64_set(&seq, ((u64)get_seconds()) << 32); | 52 | time64_t time = ktime_get_real_seconds(); |
53 | |||
54 | /* | ||
55 | * This code is unlikely to still be needed in year 2106, | ||
56 | * but just in case, let's use a few more bits for timestamps | ||
57 | * after y2038 to be sure they keep increasing monotonically | ||
58 | * for the next few hundred years... | ||
59 | */ | ||
60 | if (time < 0x80000000) | ||
61 | atomic64_set(&seq, (ktime_get_real_seconds()) << 32); | ||
62 | else | ||
63 | atomic64_set(&seq, 0x8000000000000000ull | | ||
64 | ktime_get_real_seconds() << 24); | ||
65 | } | ||
53 | 66 | ||
54 | return atomic64_inc_return(&seq); | 67 | return atomic64_inc_return(&seq); |
55 | } | 68 | } |
@@ -459,7 +472,7 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata | |||
459 | else | 472 | else |
460 | goto err_section_too_small; | 473 | goto err_section_too_small; |
461 | #if defined(CONFIG_ARM64) || defined(CONFIG_ARM) | 474 | #if defined(CONFIG_ARM64) || defined(CONFIG_ARM) |
462 | } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_ARM)) { | 475 | } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { |
463 | struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata); | 476 | struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata); |
464 | 477 | ||
465 | printk("%ssection_type: ARM processor error\n", newpfx); | 478 | printk("%ssection_type: ARM processor error\n", newpfx); |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 232f4915223b..d8a33a781a57 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -84,6 +84,8 @@ struct mm_struct efi_mm = { | |||
84 | .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), | 84 | .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), |
85 | }; | 85 | }; |
86 | 86 | ||
87 | struct workqueue_struct *efi_rts_wq; | ||
88 | |||
87 | static bool disable_runtime; | 89 | static bool disable_runtime; |
88 | static int __init setup_noefi(char *arg) | 90 | static int __init setup_noefi(char *arg) |
89 | { | 91 | { |
@@ -337,6 +339,18 @@ static int __init efisubsys_init(void) | |||
337 | if (!efi_enabled(EFI_BOOT)) | 339 | if (!efi_enabled(EFI_BOOT)) |
338 | return 0; | 340 | return 0; |
339 | 341 | ||
342 | /* | ||
343 | * Since we process only one efi_runtime_service() at a time, an | ||
344 | * ordered workqueue (which creates only one execution context) | ||
345 | * should suffice all our needs. | ||
346 | */ | ||
347 | efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0); | ||
348 | if (!efi_rts_wq) { | ||
349 | pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n"); | ||
350 | clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); | ||
351 | return 0; | ||
352 | } | ||
353 | |||
340 | /* We register the efi directory at /sys/firmware/efi */ | 354 | /* We register the efi directory at /sys/firmware/efi */ |
341 | efi_kobj = kobject_create_and_add("efi", firmware_kobj); | 355 | efi_kobj = kobject_create_and_add("efi", firmware_kobj); |
342 | if (!efi_kobj) { | 356 | if (!efi_kobj) { |
@@ -388,7 +402,7 @@ subsys_initcall(efisubsys_init); | |||
388 | * and if so, populate the supplied memory descriptor with the appropriate | 402 | * and if so, populate the supplied memory descriptor with the appropriate |
389 | * data. | 403 | * data. |
390 | */ | 404 | */ |
391 | int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) | 405 | int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) |
392 | { | 406 | { |
393 | efi_memory_desc_t *md; | 407 | efi_memory_desc_t *md; |
394 | 408 | ||
@@ -406,12 +420,6 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) | |||
406 | u64 size; | 420 | u64 size; |
407 | u64 end; | 421 | u64 end; |
408 | 422 | ||
409 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
410 | md->type != EFI_BOOT_SERVICES_DATA && | ||
411 | md->type != EFI_RUNTIME_SERVICES_DATA) { | ||
412 | continue; | ||
413 | } | ||
414 | |||
415 | size = md->num_pages << EFI_PAGE_SHIFT; | 423 | size = md->num_pages << EFI_PAGE_SHIFT; |
416 | end = md->phys_addr + size; | 424 | end = md->phys_addr + size; |
417 | if (phys_addr >= md->phys_addr && phys_addr < end) { | 425 | if (phys_addr >= md->phys_addr && phys_addr < end) { |
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 1ab80e06e7c5..5d06bd247d07 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c | |||
@@ -250,7 +250,10 @@ void __init efi_esrt_init(void) | |||
250 | return; | 250 | return; |
251 | 251 | ||
252 | rc = efi_mem_desc_lookup(efi.esrt, &md); | 252 | rc = efi_mem_desc_lookup(efi.esrt, &md); |
253 | if (rc < 0) { | 253 | if (rc < 0 || |
254 | (!(md.attribute & EFI_MEMORY_RUNTIME) && | ||
255 | md.type != EFI_BOOT_SERVICES_DATA && | ||
256 | md.type != EFI_RUNTIME_SERVICES_DATA)) { | ||
254 | pr_warn("ESRT header is not in the memory map.\n"); | 257 | pr_warn("ESRT header is not in the memory map.\n"); |
255 | return; | 258 | return; |
256 | } | 259 | } |
@@ -326,7 +329,8 @@ void __init efi_esrt_init(void) | |||
326 | 329 | ||
327 | end = esrt_data + size; | 330 | end = esrt_data + size; |
328 | pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end); | 331 | pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end); |
329 | efi_mem_reserve(esrt_data, esrt_data_size); | 332 | if (md.type == EFI_BOOT_SERVICES_DATA) |
333 | efi_mem_reserve(esrt_data, esrt_data_size); | ||
330 | 334 | ||
331 | pr_debug("esrt-init: loaded.\n"); | 335 | pr_debug("esrt-init: loaded.\n"); |
332 | } | 336 | } |
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 01a9d78ee415..6920033de6d4 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -40,31 +40,6 @@ | |||
40 | 40 | ||
41 | static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; | 41 | static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; |
42 | 42 | ||
43 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | ||
44 | void *__image, void **__fh) | ||
45 | { | ||
46 | efi_file_io_interface_t *io; | ||
47 | efi_loaded_image_t *image = __image; | ||
48 | efi_file_handle_t *fh; | ||
49 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
50 | efi_status_t status; | ||
51 | void *handle = (void *)(unsigned long)image->device_handle; | ||
52 | |||
53 | status = sys_table_arg->boottime->handle_protocol(handle, | ||
54 | &fs_proto, (void **)&io); | ||
55 | if (status != EFI_SUCCESS) { | ||
56 | efi_printk(sys_table_arg, "Failed to handle fs_proto\n"); | ||
57 | return status; | ||
58 | } | ||
59 | |||
60 | status = io->open_volume(io, &fh); | ||
61 | if (status != EFI_SUCCESS) | ||
62 | efi_printk(sys_table_arg, "Failed to open volume\n"); | ||
63 | |||
64 | *__fh = fh; | ||
65 | return status; | ||
66 | } | ||
67 | |||
68 | void efi_char16_printk(efi_system_table_t *sys_table_arg, | 43 | void efi_char16_printk(efi_system_table_t *sys_table_arg, |
69 | efi_char16_t *str) | 44 | efi_char16_t *str) |
70 | { | 45 | { |
@@ -202,9 +177,10 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
202 | * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure | 177 | * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure |
203 | * boot is enabled if we can't determine its state. | 178 | * boot is enabled if we can't determine its state. |
204 | */ | 179 | */ |
205 | if (secure_boot != efi_secureboot_mode_disabled && | 180 | if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) || |
206 | strstr(cmdline_ptr, "dtb=")) { | 181 | secure_boot != efi_secureboot_mode_disabled) { |
207 | pr_efi(sys_table, "Ignoring DTB from command line.\n"); | 182 | if (strstr(cmdline_ptr, "dtb=")) |
183 | pr_efi(sys_table, "Ignoring DTB from command line.\n"); | ||
208 | } else { | 184 | } else { |
209 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, | 185 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, |
210 | "dtb=", | 186 | "dtb=", |
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 50a9cab5a834..e94975f4655b 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c | |||
@@ -413,6 +413,34 @@ static efi_status_t efi_file_close(void *handle) | |||
413 | return efi_call_proto(efi_file_handle, close, handle); | 413 | return efi_call_proto(efi_file_handle, close, handle); |
414 | } | 414 | } |
415 | 415 | ||
416 | static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | ||
417 | efi_loaded_image_t *image, | ||
418 | efi_file_handle_t **__fh) | ||
419 | { | ||
420 | efi_file_io_interface_t *io; | ||
421 | efi_file_handle_t *fh; | ||
422 | efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; | ||
423 | efi_status_t status; | ||
424 | void *handle = (void *)(unsigned long)efi_table_attr(efi_loaded_image, | ||
425 | device_handle, | ||
426 | image); | ||
427 | |||
428 | status = efi_call_early(handle_protocol, handle, | ||
429 | &fs_proto, (void **)&io); | ||
430 | if (status != EFI_SUCCESS) { | ||
431 | efi_printk(sys_table_arg, "Failed to handle fs_proto\n"); | ||
432 | return status; | ||
433 | } | ||
434 | |||
435 | status = efi_call_proto(efi_file_io_interface, open_volume, io, &fh); | ||
436 | if (status != EFI_SUCCESS) | ||
437 | efi_printk(sys_table_arg, "Failed to open volume\n"); | ||
438 | else | ||
439 | *__fh = fh; | ||
440 | |||
441 | return status; | ||
442 | } | ||
443 | |||
416 | /* | 444 | /* |
417 | * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= | 445 | * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= |
418 | * option, e.g. efi=nochunk. | 446 | * option, e.g. efi=nochunk. |
@@ -563,8 +591,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | |||
563 | 591 | ||
564 | /* Only open the volume once. */ | 592 | /* Only open the volume once. */ |
565 | if (!i) { | 593 | if (!i) { |
566 | status = efi_open_volume(sys_table_arg, image, | 594 | status = efi_open_volume(sys_table_arg, image, &fh); |
567 | (void **)&fh); | ||
568 | if (status != EFI_SUCCESS) | 595 | if (status != EFI_SUCCESS) |
569 | goto free_files; | 596 | goto free_files; |
570 | } | 597 | } |
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index f59564b72ddc..32799cf039ef 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h | |||
@@ -36,9 +36,6 @@ extern int __pure is_quiet(void); | |||
36 | 36 | ||
37 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | 37 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); |
38 | 38 | ||
39 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, | ||
40 | void **__fh); | ||
41 | |||
42 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); | 39 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); |
43 | 40 | ||
44 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | 41 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, |
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index ae54870b2788..aa66cbf23512 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c | |||
@@ -1,6 +1,15 @@ | |||
1 | /* | 1 | /* |
2 | * runtime-wrappers.c - Runtime Services function call wrappers | 2 | * runtime-wrappers.c - Runtime Services function call wrappers |
3 | * | 3 | * |
4 | * Implementation summary: | ||
5 | * ----------------------- | ||
6 | * 1. When user/kernel thread requests to execute efi_runtime_service(), | ||
7 | * enqueue work to efi_rts_wq. | ||
8 | * 2. Caller thread waits for completion until the work is finished | ||
9 | * because it's dependent on the return status and execution of | ||
10 | * efi_runtime_service(). | ||
11 | * For instance, get_variable() and get_next_variable(). | ||
12 | * | ||
4 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> | 13 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> |
5 | * | 14 | * |
6 | * Split off from arch/x86/platform/efi/efi.c | 15 | * Split off from arch/x86/platform/efi/efi.c |
@@ -22,6 +31,9 @@ | |||
22 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
23 | #include <linux/semaphore.h> | 32 | #include <linux/semaphore.h> |
24 | #include <linux/stringify.h> | 33 | #include <linux/stringify.h> |
34 | #include <linux/workqueue.h> | ||
35 | #include <linux/completion.h> | ||
36 | |||
25 | #include <asm/efi.h> | 37 | #include <asm/efi.h> |
26 | 38 | ||
27 | /* | 39 | /* |
@@ -33,6 +45,76 @@ | |||
33 | #define __efi_call_virt(f, args...) \ | 45 | #define __efi_call_virt(f, args...) \ |
34 | __efi_call_virt_pointer(efi.systab->runtime, f, args) | 46 | __efi_call_virt_pointer(efi.systab->runtime, f, args) |
35 | 47 | ||
48 | /* efi_runtime_service() function identifiers */ | ||
49 | enum efi_rts_ids { | ||
50 | GET_TIME, | ||
51 | SET_TIME, | ||
52 | GET_WAKEUP_TIME, | ||
53 | SET_WAKEUP_TIME, | ||
54 | GET_VARIABLE, | ||
55 | GET_NEXT_VARIABLE, | ||
56 | SET_VARIABLE, | ||
57 | QUERY_VARIABLE_INFO, | ||
58 | GET_NEXT_HIGH_MONO_COUNT, | ||
59 | UPDATE_CAPSULE, | ||
60 | QUERY_CAPSULE_CAPS, | ||
61 | }; | ||
62 | |||
63 | /* | ||
64 | * efi_runtime_work: Details of EFI Runtime Service work | ||
65 | * @arg<1-5>: EFI Runtime Service function arguments | ||
66 | * @status: Status of executing EFI Runtime Service | ||
67 | * @efi_rts_id: EFI Runtime Service function identifier | ||
68 | * @efi_rts_comp: Struct used for handling completions | ||
69 | */ | ||
70 | struct efi_runtime_work { | ||
71 | void *arg1; | ||
72 | void *arg2; | ||
73 | void *arg3; | ||
74 | void *arg4; | ||
75 | void *arg5; | ||
76 | efi_status_t status; | ||
77 | struct work_struct work; | ||
78 | enum efi_rts_ids efi_rts_id; | ||
79 | struct completion efi_rts_comp; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * efi_queue_work: Queue efi_runtime_service() and wait until it's done | ||
84 | * @rts: efi_runtime_service() function identifier | ||
85 | * @rts_arg<1-5>: efi_runtime_service() function arguments | ||
86 | * | ||
87 | * Accesses to efi_runtime_services() are serialized by a binary | ||
88 | * semaphore (efi_runtime_lock) and caller waits until the work is | ||
89 | * finished, hence _only_ one work is queued at a time and the caller | ||
90 | * thread waits for completion. | ||
91 | */ | ||
92 | #define efi_queue_work(_rts, _arg1, _arg2, _arg3, _arg4, _arg5) \ | ||
93 | ({ \ | ||
94 | struct efi_runtime_work efi_rts_work; \ | ||
95 | efi_rts_work.status = EFI_ABORTED; \ | ||
96 | \ | ||
97 | init_completion(&efi_rts_work.efi_rts_comp); \ | ||
98 | INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts); \ | ||
99 | efi_rts_work.arg1 = _arg1; \ | ||
100 | efi_rts_work.arg2 = _arg2; \ | ||
101 | efi_rts_work.arg3 = _arg3; \ | ||
102 | efi_rts_work.arg4 = _arg4; \ | ||
103 | efi_rts_work.arg5 = _arg5; \ | ||
104 | efi_rts_work.efi_rts_id = _rts; \ | ||
105 | \ | ||
106 | /* \ | ||
107 | * queue_work() returns 0 if work was already on queue, \ | ||
108 | * _ideally_ this should never happen. \ | ||
109 | */ \ | ||
110 | if (queue_work(efi_rts_wq, &efi_rts_work.work)) \ | ||
111 | wait_for_completion(&efi_rts_work.efi_rts_comp); \ | ||
112 | else \ | ||
113 | pr_err("Failed to queue work to efi_rts_wq.\n"); \ | ||
114 | \ | ||
115 | efi_rts_work.status; \ | ||
116 | }) | ||
117 | |||
36 | void efi_call_virt_check_flags(unsigned long flags, const char *call) | 118 | void efi_call_virt_check_flags(unsigned long flags, const char *call) |
37 | { | 119 | { |
38 | unsigned long cur_flags, mismatch; | 120 | unsigned long cur_flags, mismatch; |
@@ -90,13 +172,98 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call) | |||
90 | */ | 172 | */ |
91 | static DEFINE_SEMAPHORE(efi_runtime_lock); | 173 | static DEFINE_SEMAPHORE(efi_runtime_lock); |
92 | 174 | ||
175 | /* | ||
176 | * Calls the appropriate efi_runtime_service() with the appropriate | ||
177 | * arguments. | ||
178 | * | ||
179 | * Semantics followed by efi_call_rts() to understand efi_runtime_work: | ||
180 | * 1. If argument was a pointer, recast it from void pointer to original | ||
181 | * pointer type. | ||
182 | * 2. If argument was a value, recast it from void pointer to original | ||
183 | * pointer type and dereference it. | ||
184 | */ | ||
185 | static void efi_call_rts(struct work_struct *work) | ||
186 | { | ||
187 | struct efi_runtime_work *efi_rts_work; | ||
188 | void *arg1, *arg2, *arg3, *arg4, *arg5; | ||
189 | efi_status_t status = EFI_NOT_FOUND; | ||
190 | |||
191 | efi_rts_work = container_of(work, struct efi_runtime_work, work); | ||
192 | arg1 = efi_rts_work->arg1; | ||
193 | arg2 = efi_rts_work->arg2; | ||
194 | arg3 = efi_rts_work->arg3; | ||
195 | arg4 = efi_rts_work->arg4; | ||
196 | arg5 = efi_rts_work->arg5; | ||
197 | |||
198 | switch (efi_rts_work->efi_rts_id) { | ||
199 | case GET_TIME: | ||
200 | status = efi_call_virt(get_time, (efi_time_t *)arg1, | ||
201 | (efi_time_cap_t *)arg2); | ||
202 | break; | ||
203 | case SET_TIME: | ||
204 | status = efi_call_virt(set_time, (efi_time_t *)arg1); | ||
205 | break; | ||
206 | case GET_WAKEUP_TIME: | ||
207 | status = efi_call_virt(get_wakeup_time, (efi_bool_t *)arg1, | ||
208 | (efi_bool_t *)arg2, (efi_time_t *)arg3); | ||
209 | break; | ||
210 | case SET_WAKEUP_TIME: | ||
211 | status = efi_call_virt(set_wakeup_time, *(efi_bool_t *)arg1, | ||
212 | (efi_time_t *)arg2); | ||
213 | break; | ||
214 | case GET_VARIABLE: | ||
215 | status = efi_call_virt(get_variable, (efi_char16_t *)arg1, | ||
216 | (efi_guid_t *)arg2, (u32 *)arg3, | ||
217 | (unsigned long *)arg4, (void *)arg5); | ||
218 | break; | ||
219 | case GET_NEXT_VARIABLE: | ||
220 | status = efi_call_virt(get_next_variable, (unsigned long *)arg1, | ||
221 | (efi_char16_t *)arg2, | ||
222 | (efi_guid_t *)arg3); | ||
223 | break; | ||
224 | case SET_VARIABLE: | ||
225 | status = efi_call_virt(set_variable, (efi_char16_t *)arg1, | ||
226 | (efi_guid_t *)arg2, *(u32 *)arg3, | ||
227 | *(unsigned long *)arg4, (void *)arg5); | ||
228 | break; | ||
229 | case QUERY_VARIABLE_INFO: | ||
230 | status = efi_call_virt(query_variable_info, *(u32 *)arg1, | ||
231 | (u64 *)arg2, (u64 *)arg3, (u64 *)arg4); | ||
232 | break; | ||
233 | case GET_NEXT_HIGH_MONO_COUNT: | ||
234 | status = efi_call_virt(get_next_high_mono_count, (u32 *)arg1); | ||
235 | break; | ||
236 | case UPDATE_CAPSULE: | ||
237 | status = efi_call_virt(update_capsule, | ||
238 | (efi_capsule_header_t **)arg1, | ||
239 | *(unsigned long *)arg2, | ||
240 | *(unsigned long *)arg3); | ||
241 | break; | ||
242 | case QUERY_CAPSULE_CAPS: | ||
243 | status = efi_call_virt(query_capsule_caps, | ||
244 | (efi_capsule_header_t **)arg1, | ||
245 | *(unsigned long *)arg2, (u64 *)arg3, | ||
246 | (int *)arg4); | ||
247 | break; | ||
248 | default: | ||
249 | /* | ||
250 | * Ideally, we should never reach here because a caller of this | ||
251 | * function should have put the right efi_runtime_service() | ||
252 | * function identifier into efi_rts_work->efi_rts_id | ||
253 | */ | ||
254 | pr_err("Requested executing invalid EFI Runtime Service.\n"); | ||
255 | } | ||
256 | efi_rts_work->status = status; | ||
257 | complete(&efi_rts_work->efi_rts_comp); | ||
258 | } | ||
259 | |||
93 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | 260 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) |
94 | { | 261 | { |
95 | efi_status_t status; | 262 | efi_status_t status; |
96 | 263 | ||
97 | if (down_interruptible(&efi_runtime_lock)) | 264 | if (down_interruptible(&efi_runtime_lock)) |
98 | return EFI_ABORTED; | 265 | return EFI_ABORTED; |
99 | status = efi_call_virt(get_time, tm, tc); | 266 | status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL); |
100 | up(&efi_runtime_lock); | 267 | up(&efi_runtime_lock); |
101 | return status; | 268 | return status; |
102 | } | 269 | } |
@@ -107,7 +274,7 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm) | |||
107 | 274 | ||
108 | if (down_interruptible(&efi_runtime_lock)) | 275 | if (down_interruptible(&efi_runtime_lock)) |
109 | return EFI_ABORTED; | 276 | return EFI_ABORTED; |
110 | status = efi_call_virt(set_time, tm); | 277 | status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL); |
111 | up(&efi_runtime_lock); | 278 | up(&efi_runtime_lock); |
112 | return status; | 279 | return status; |
113 | } | 280 | } |
@@ -120,7 +287,8 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, | |||
120 | 287 | ||
121 | if (down_interruptible(&efi_runtime_lock)) | 288 | if (down_interruptible(&efi_runtime_lock)) |
122 | return EFI_ABORTED; | 289 | return EFI_ABORTED; |
123 | status = efi_call_virt(get_wakeup_time, enabled, pending, tm); | 290 | status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL, |
291 | NULL); | ||
124 | up(&efi_runtime_lock); | 292 | up(&efi_runtime_lock); |
125 | return status; | 293 | return status; |
126 | } | 294 | } |
@@ -131,7 +299,8 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | |||
131 | 299 | ||
132 | if (down_interruptible(&efi_runtime_lock)) | 300 | if (down_interruptible(&efi_runtime_lock)) |
133 | return EFI_ABORTED; | 301 | return EFI_ABORTED; |
134 | status = efi_call_virt(set_wakeup_time, enabled, tm); | 302 | status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL, |
303 | NULL); | ||
135 | up(&efi_runtime_lock); | 304 | up(&efi_runtime_lock); |
136 | return status; | 305 | return status; |
137 | } | 306 | } |
@@ -146,8 +315,8 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name, | |||
146 | 315 | ||
147 | if (down_interruptible(&efi_runtime_lock)) | 316 | if (down_interruptible(&efi_runtime_lock)) |
148 | return EFI_ABORTED; | 317 | return EFI_ABORTED; |
149 | status = efi_call_virt(get_variable, name, vendor, attr, data_size, | 318 | status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size, |
150 | data); | 319 | data); |
151 | up(&efi_runtime_lock); | 320 | up(&efi_runtime_lock); |
152 | return status; | 321 | return status; |
153 | } | 322 | } |
@@ -160,7 +329,8 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, | |||
160 | 329 | ||
161 | if (down_interruptible(&efi_runtime_lock)) | 330 | if (down_interruptible(&efi_runtime_lock)) |
162 | return EFI_ABORTED; | 331 | return EFI_ABORTED; |
163 | status = efi_call_virt(get_next_variable, name_size, name, vendor); | 332 | status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor, |
333 | NULL, NULL); | ||
164 | up(&efi_runtime_lock); | 334 | up(&efi_runtime_lock); |
165 | return status; | 335 | return status; |
166 | } | 336 | } |
@@ -175,8 +345,8 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, | |||
175 | 345 | ||
176 | if (down_interruptible(&efi_runtime_lock)) | 346 | if (down_interruptible(&efi_runtime_lock)) |
177 | return EFI_ABORTED; | 347 | return EFI_ABORTED; |
178 | status = efi_call_virt(set_variable, name, vendor, attr, data_size, | 348 | status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size, |
179 | data); | 349 | data); |
180 | up(&efi_runtime_lock); | 350 | up(&efi_runtime_lock); |
181 | return status; | 351 | return status; |
182 | } | 352 | } |
@@ -210,8 +380,8 @@ static efi_status_t virt_efi_query_variable_info(u32 attr, | |||
210 | 380 | ||
211 | if (down_interruptible(&efi_runtime_lock)) | 381 | if (down_interruptible(&efi_runtime_lock)) |
212 | return EFI_ABORTED; | 382 | return EFI_ABORTED; |
213 | status = efi_call_virt(query_variable_info, attr, storage_space, | 383 | status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space, |
214 | remaining_space, max_variable_size); | 384 | remaining_space, max_variable_size, NULL); |
215 | up(&efi_runtime_lock); | 385 | up(&efi_runtime_lock); |
216 | return status; | 386 | return status; |
217 | } | 387 | } |
@@ -242,7 +412,8 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) | |||
242 | 412 | ||
243 | if (down_interruptible(&efi_runtime_lock)) | 413 | if (down_interruptible(&efi_runtime_lock)) |
244 | return EFI_ABORTED; | 414 | return EFI_ABORTED; |
245 | status = efi_call_virt(get_next_high_mono_count, count); | 415 | status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL, |
416 | NULL, NULL); | ||
246 | up(&efi_runtime_lock); | 417 | up(&efi_runtime_lock); |
247 | return status; | 418 | return status; |
248 | } | 419 | } |
@@ -272,7 +443,8 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, | |||
272 | 443 | ||
273 | if (down_interruptible(&efi_runtime_lock)) | 444 | if (down_interruptible(&efi_runtime_lock)) |
274 | return EFI_ABORTED; | 445 | return EFI_ABORTED; |
275 | status = efi_call_virt(update_capsule, capsules, count, sg_list); | 446 | status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list, |
447 | NULL, NULL); | ||
276 | up(&efi_runtime_lock); | 448 | up(&efi_runtime_lock); |
277 | return status; | 449 | return status; |
278 | } | 450 | } |
@@ -289,8 +461,8 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, | |||
289 | 461 | ||
290 | if (down_interruptible(&efi_runtime_lock)) | 462 | if (down_interruptible(&efi_runtime_lock)) |
291 | return EFI_ABORTED; | 463 | return EFI_ABORTED; |
292 | status = efi_call_virt(query_capsule_caps, capsules, count, max_size, | 464 | status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count, |
293 | reset_type); | 465 | max_size, reset_type, NULL); |
294 | up(&efi_runtime_lock); | 466 | up(&efi_runtime_lock); |
295 | return status; | 467 | return status; |
296 | } | 468 | } |
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 46a4484e3da7..c6f78d27947b 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <drm/drm_connector.h> /* For DRM_MODE_PANEL_ORIENTATION_* */ | 20 | #include <drm/drm_connector.h> /* For DRM_MODE_PANEL_ORIENTATION_* */ |
21 | 21 | ||
22 | static bool request_mem_succeeded = false; | 22 | static bool request_mem_succeeded = false; |
23 | static bool nowc = false; | 23 | static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC; |
24 | 24 | ||
25 | static struct fb_var_screeninfo efifb_defined = { | 25 | static struct fb_var_screeninfo efifb_defined = { |
26 | .activate = FB_ACTIVATE_NOW, | 26 | .activate = FB_ACTIVATE_NOW, |
@@ -68,8 +68,12 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
68 | 68 | ||
69 | static void efifb_destroy(struct fb_info *info) | 69 | static void efifb_destroy(struct fb_info *info) |
70 | { | 70 | { |
71 | if (info->screen_base) | 71 | if (info->screen_base) { |
72 | iounmap(info->screen_base); | 72 | if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) |
73 | iounmap(info->screen_base); | ||
74 | else | ||
75 | memunmap(info->screen_base); | ||
76 | } | ||
73 | if (request_mem_succeeded) | 77 | if (request_mem_succeeded) |
74 | release_mem_region(info->apertures->ranges[0].base, | 78 | release_mem_region(info->apertures->ranges[0].base, |
75 | info->apertures->ranges[0].size); | 79 | info->apertures->ranges[0].size); |
@@ -104,7 +108,7 @@ static int efifb_setup(char *options) | |||
104 | else if (!strncmp(this_opt, "width:", 6)) | 108 | else if (!strncmp(this_opt, "width:", 6)) |
105 | screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); | 109 | screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); |
106 | else if (!strcmp(this_opt, "nowc")) | 110 | else if (!strcmp(this_opt, "nowc")) |
107 | nowc = true; | 111 | mem_flags &= ~EFI_MEMORY_WC; |
108 | } | 112 | } |
109 | } | 113 | } |
110 | 114 | ||
@@ -164,6 +168,7 @@ static int efifb_probe(struct platform_device *dev) | |||
164 | unsigned int size_remap; | 168 | unsigned int size_remap; |
165 | unsigned int size_total; | 169 | unsigned int size_total; |
166 | char *option = NULL; | 170 | char *option = NULL; |
171 | efi_memory_desc_t md; | ||
167 | 172 | ||
168 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled) | 173 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled) |
169 | return -ENODEV; | 174 | return -ENODEV; |
@@ -272,12 +277,35 @@ static int efifb_probe(struct platform_device *dev) | |||
272 | info->apertures->ranges[0].base = efifb_fix.smem_start; | 277 | info->apertures->ranges[0].base = efifb_fix.smem_start; |
273 | info->apertures->ranges[0].size = size_remap; | 278 | info->apertures->ranges[0].size = size_remap; |
274 | 279 | ||
275 | if (nowc) | 280 | if (!efi_mem_desc_lookup(efifb_fix.smem_start, &md)) { |
276 | info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); | 281 | if ((efifb_fix.smem_start + efifb_fix.smem_len) > |
277 | else | 282 | (md.phys_addr + (md.num_pages << EFI_PAGE_SHIFT))) { |
278 | info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); | 283 | pr_err("efifb: video memory @ 0x%lx spans multiple EFI memory regions\n", |
284 | efifb_fix.smem_start); | ||
285 | err = -EIO; | ||
286 | goto err_release_fb; | ||
287 | } | ||
288 | /* | ||
289 | * If the UEFI memory map covers the efifb region, we may only | ||
290 | * remap it using the attributes the memory map prescribes. | ||
291 | */ | ||
292 | mem_flags |= EFI_MEMORY_WT | EFI_MEMORY_WB; | ||
293 | mem_flags &= md.attribute; | ||
294 | } | ||
295 | if (mem_flags & EFI_MEMORY_WC) | ||
296 | info->screen_base = ioremap_wc(efifb_fix.smem_start, | ||
297 | efifb_fix.smem_len); | ||
298 | else if (mem_flags & EFI_MEMORY_UC) | ||
299 | info->screen_base = ioremap(efifb_fix.smem_start, | ||
300 | efifb_fix.smem_len); | ||
301 | else if (mem_flags & EFI_MEMORY_WT) | ||
302 | info->screen_base = memremap(efifb_fix.smem_start, | ||
303 | efifb_fix.smem_len, MEMREMAP_WT); | ||
304 | else if (mem_flags & EFI_MEMORY_WB) | ||
305 | info->screen_base = memremap(efifb_fix.smem_start, | ||
306 | efifb_fix.smem_len, MEMREMAP_WB); | ||
279 | if (!info->screen_base) { | 307 | if (!info->screen_base) { |
280 | pr_err("efifb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", | 308 | pr_err("efifb: abort, cannot remap video memory 0x%x @ 0x%lx\n", |
281 | efifb_fix.smem_len, efifb_fix.smem_start); | 309 | efifb_fix.smem_len, efifb_fix.smem_start); |
282 | err = -EIO; | 310 | err = -EIO; |
283 | goto err_release_fb; | 311 | goto err_release_fb; |
@@ -371,7 +399,10 @@ err_fb_dealoc: | |||
371 | err_groups: | 399 | err_groups: |
372 | sysfs_remove_groups(&dev->dev.kobj, efifb_groups); | 400 | sysfs_remove_groups(&dev->dev.kobj, efifb_groups); |
373 | err_unmap: | 401 | err_unmap: |
374 | iounmap(info->screen_base); | 402 | if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) |
403 | iounmap(info->screen_base); | ||
404 | else | ||
405 | memunmap(info->screen_base); | ||
375 | err_release_fb: | 406 | err_release_fb: |
376 | framebuffer_release(info); | 407 | framebuffer_release(info); |
377 | err_release_mem: | 408 | err_release_mem: |
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 71fccccf317e..8c6ab6c95727 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c | |||
@@ -86,7 +86,9 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, | |||
86 | /* length of the variable name itself: remove GUID and separator */ | 86 | /* length of the variable name itself: remove GUID and separator */ |
87 | namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1; | 87 | namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1; |
88 | 88 | ||
89 | uuid_le_to_bin(dentry->d_name.name + namelen + 1, &var->var.VendorGuid); | 89 | err = guid_parse(dentry->d_name.name + namelen + 1, &var->var.VendorGuid); |
90 | if (err) | ||
91 | goto out; | ||
90 | 92 | ||
91 | if (efivar_variable_is_removable(var->var.VendorGuid, | 93 | if (efivar_variable_is_removable(var->var.VendorGuid, |
92 | dentry->d_name.name, namelen)) | 94 | dentry->d_name.name, namelen)) |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 56add823f190..401e4b254e30 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -894,6 +894,16 @@ typedef struct _efi_file_handle { | |||
894 | void *flush; | 894 | void *flush; |
895 | } efi_file_handle_t; | 895 | } efi_file_handle_t; |
896 | 896 | ||
897 | typedef struct { | ||
898 | u64 revision; | ||
899 | u32 open_volume; | ||
900 | } efi_file_io_interface_32_t; | ||
901 | |||
902 | typedef struct { | ||
903 | u64 revision; | ||
904 | u64 open_volume; | ||
905 | } efi_file_io_interface_64_t; | ||
906 | |||
897 | typedef struct _efi_file_io_interface { | 907 | typedef struct _efi_file_io_interface { |
898 | u64 revision; | 908 | u64 revision; |
899 | int (*open_volume)(struct _efi_file_io_interface *, | 909 | int (*open_volume)(struct _efi_file_io_interface *, |
@@ -988,14 +998,12 @@ extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); | |||
988 | extern void efi_gettimeofday (struct timespec64 *ts); | 998 | extern void efi_gettimeofday (struct timespec64 *ts); |
989 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ | 999 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ |
990 | #ifdef CONFIG_X86 | 1000 | #ifdef CONFIG_X86 |
991 | extern void efi_late_init(void); | ||
992 | extern void efi_free_boot_services(void); | 1001 | extern void efi_free_boot_services(void); |
993 | extern efi_status_t efi_query_variable_store(u32 attributes, | 1002 | extern efi_status_t efi_query_variable_store(u32 attributes, |
994 | unsigned long size, | 1003 | unsigned long size, |
995 | bool nonblocking); | 1004 | bool nonblocking); |
996 | extern void efi_find_mirror(void); | 1005 | extern void efi_find_mirror(void); |
997 | #else | 1006 | #else |
998 | static inline void efi_late_init(void) {} | ||
999 | static inline void efi_free_boot_services(void) {} | 1007 | static inline void efi_free_boot_services(void) {} |
1000 | 1008 | ||
1001 | static inline efi_status_t efi_query_variable_store(u32 attributes, | 1009 | static inline efi_status_t efi_query_variable_store(u32 attributes, |
@@ -1651,4 +1659,7 @@ struct linux_efi_tpm_eventlog { | |||
1651 | 1659 | ||
1652 | extern int efi_tpm_eventlog_init(void); | 1660 | extern int efi_tpm_eventlog_init(void); |
1653 | 1661 | ||
1662 | /* Workqueue to queue EFI Runtime Services */ | ||
1663 | extern struct workqueue_struct *efi_rts_wq; | ||
1664 | |||
1654 | #endif /* _LINUX_EFI_H */ | 1665 | #endif /* _LINUX_EFI_H */ |