1 #include "efi.h"
2 #include "runtime.h"
3 #include <xen/cache.h>
4 #include <xen/errno.h>
5 #include <xen/guest_access.h>
6 #include <xen/irq.h>
7 #include <xen/time.h>
8
9 DEFINE_XEN_GUEST_HANDLE(CHAR16);
10
11 struct efi_rs_state {
12 #ifdef CONFIG_X86
13 /*
14 * The way stacks get set up leads to them always being on an 8-byte
15 * boundary not evenly divisible by 16 (see asm-x86/current.h). The EFI ABI,
16 * just like the CPU one, however requires stacks to be 16-byte aligned
17 * before every function call. Since the compiler assumes this (unless
18 * passing it -mpreferred-stack-boundary=3), it wouldn't generate code to
19 * align the stack to 16 bytes even if putting a 16-byte aligned object
20 * there. Hence we need to force larger than 16-byte alignment, even if we
21 * don't strictly need that.
22 */
23 unsigned long __aligned(32) cr3;
24 #endif
25 };
26
27 struct efi_rs_state efi_rs_enter(void);
28 void efi_rs_leave(struct efi_rs_state *);
29
30 #ifndef COMPAT
31
32 #ifndef CONFIG_ARM
33 # include <asm/i387.h>
34 # include <asm/xstate.h>
35 # include <public/platform.h>
36 #endif
37
38 unsigned int __read_mostly efi_num_ct;
39 const EFI_CONFIGURATION_TABLE *__read_mostly efi_ct;
40
41 unsigned int __read_mostly efi_version;
42 unsigned int __read_mostly efi_fw_revision;
43 const CHAR16 *__read_mostly efi_fw_vendor;
44
45 const EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
46 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
47 static DEFINE_SPINLOCK(efi_rs_lock);
48 static unsigned int efi_rs_on_cpu = NR_CPUS;
49 #endif
50
51 UINTN __read_mostly efi_memmap_size;
52 UINTN __read_mostly efi_mdesc_size;
53 void *__read_mostly efi_memmap;
54
55 UINT64 __read_mostly efi_boot_max_var_store_size;
56 UINT64 __read_mostly efi_boot_remain_var_store_size;
57 UINT64 __read_mostly efi_boot_max_var_size;
58
59 UINT64 __read_mostly efi_apple_properties_addr;
60 UINTN __read_mostly efi_apple_properties_len;
61
62 /* Bit field representing available EFI features/properties. */
63 unsigned int efi_flags;
64
65 struct efi __read_mostly efi = {
66 .acpi = EFI_INVALID_TABLE_ADDR,
67 .acpi20 = EFI_INVALID_TABLE_ADDR,
68 .mps = EFI_INVALID_TABLE_ADDR,
69 .smbios = EFI_INVALID_TABLE_ADDR,
70 .smbios3 = EFI_INVALID_TABLE_ADDR,
71 };
72
73 const struct efi_pci_rom *__read_mostly efi_pci_roms;
74
efi_enabled(unsigned int feature)75 bool efi_enabled(unsigned int feature)
76 {
77 return test_bit(feature, &efi_flags);
78 }
79
80 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
81
efi_rs_enter(void)82 struct efi_rs_state efi_rs_enter(void)
83 {
84 static const u16 fcw = FCW_DEFAULT;
85 static const u32 mxcsr = MXCSR_DEFAULT;
86 struct efi_rs_state state = { .cr3 = 0 };
87
88 if ( !efi_l4_pgtable )
89 return state;
90
91 state.cr3 = read_cr3();
92 save_fpu_enable();
93 asm volatile ( "fnclex; fldcw %0" :: "m" (fcw) );
94 asm volatile ( "ldmxcsr %0" :: "m" (mxcsr) );
95
96 spin_lock(&efi_rs_lock);
97
98 efi_rs_on_cpu = smp_processor_id();
99
100 /* prevent fixup_page_fault() from doing anything */
101 irq_enter();
102
103 if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
104 {
105 struct desc_ptr gdt_desc = {
106 .limit = LAST_RESERVED_GDT_BYTE,
107 .base = (unsigned long)(per_cpu(gdt_table, smp_processor_id()) -
108 FIRST_RESERVED_GDT_ENTRY)
109 };
110
111 asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
112 }
113
114 write_cr3(virt_to_maddr(efi_l4_pgtable));
115
116 return state;
117 }
118
efi_rs_leave(struct efi_rs_state * state)119 void efi_rs_leave(struct efi_rs_state *state)
120 {
121 if ( !state->cr3 )
122 return;
123 write_cr3(state->cr3);
124 if ( is_pv_vcpu(current) && !is_idle_vcpu(current) )
125 {
126 struct desc_ptr gdt_desc = {
127 .limit = LAST_RESERVED_GDT_BYTE,
128 .base = GDT_VIRT_START(current)
129 };
130
131 asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
132 }
133 irq_exit();
134 efi_rs_on_cpu = NR_CPUS;
135 spin_unlock(&efi_rs_lock);
136 stts();
137 }
138
efi_rs_using_pgtables(void)139 bool efi_rs_using_pgtables(void)
140 {
141 return efi_l4_pgtable &&
142 (smp_processor_id() == efi_rs_on_cpu) &&
143 (read_cr3() == virt_to_maddr(efi_l4_pgtable));
144 }
145
efi_get_time(void)146 unsigned long efi_get_time(void)
147 {
148 EFI_TIME time;
149 EFI_STATUS status;
150 struct efi_rs_state state = efi_rs_enter();
151 unsigned long flags;
152
153 if ( !state.cr3 )
154 return 0;
155 spin_lock_irqsave(&rtc_lock, flags);
156 status = efi_rs->GetTime(&time, NULL);
157 spin_unlock_irqrestore(&rtc_lock, flags);
158 efi_rs_leave(&state);
159
160 if ( EFI_ERROR(status) )
161 return 0;
162
163 return mktime(time.Year, time.Month, time.Day,
164 time.Hour, time.Minute, time.Second);
165 }
166
efi_halt_system(void)167 void efi_halt_system(void)
168 {
169 EFI_STATUS status;
170 struct efi_rs_state state = efi_rs_enter();
171
172 if ( !state.cr3 )
173 return;
174 status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
175 efi_rs_leave(&state);
176
177 printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status);
178 }
179
efi_reset_system(bool warm)180 void efi_reset_system(bool warm)
181 {
182 EFI_STATUS status;
183 struct efi_rs_state state = efi_rs_enter();
184
185 if ( !state.cr3 )
186 return;
187 status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold,
188 EFI_SUCCESS, 0, NULL);
189 efi_rs_leave(&state);
190
191 printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
192 }
193
194 #endif /* CONFIG_ARM */
195 #endif
196
197 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
efi_get_info(uint32_t idx,union xenpf_efi_info * info)198 int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
199 {
200 unsigned int i, n;
201
202 if ( !efi_enabled(EFI_BOOT) )
203 return -ENOSYS;
204
205 switch ( idx )
206 {
207 case XEN_FW_EFI_VERSION:
208 info->version = efi_version;
209 break;
210 case XEN_FW_EFI_RT_VERSION:
211 {
212 struct efi_rs_state state = efi_rs_enter();
213
214 if ( !state.cr3 )
215 return -EOPNOTSUPP;
216 info->version = efi_rs->Hdr.Revision;
217 efi_rs_leave(&state);
218 break;
219 }
220 case XEN_FW_EFI_CONFIG_TABLE:
221 info->cfg.addr = __pa(efi_ct);
222 info->cfg.nent = efi_num_ct;
223 break;
224 case XEN_FW_EFI_VENDOR:
225 if ( !efi_fw_vendor )
226 return -EOPNOTSUPP;
227 info->vendor.revision = efi_fw_revision;
228 n = info->vendor.bufsz / sizeof(*efi_fw_vendor);
229 if ( !guest_handle_okay(guest_handle_cast(info->vendor.name,
230 CHAR16), n) )
231 return -EFAULT;
232 for ( i = 0; i < n; ++i )
233 {
234 if ( __copy_to_guest_offset(info->vendor.name, i,
235 efi_fw_vendor + i, 1) )
236 return -EFAULT;
237 if ( !efi_fw_vendor[i] )
238 break;
239 }
240 break;
241 case XEN_FW_EFI_MEM_INFO:
242 for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
243 {
244 EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
245 u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
246
247 if ( info->mem.addr >= desc->PhysicalStart &&
248 info->mem.addr < desc->PhysicalStart + len )
249 {
250 info->mem.type = desc->Type;
251 info->mem.attr = desc->Attribute;
252 if ( info->mem.addr + info->mem.size < info->mem.addr ||
253 info->mem.addr + info->mem.size >
254 desc->PhysicalStart + len )
255 info->mem.size = desc->PhysicalStart + len -
256 info->mem.addr;
257 return 0;
258 }
259 }
260 return -ESRCH;
261 case XEN_FW_EFI_PCI_ROM: {
262 const struct efi_pci_rom *ent;
263
264 for ( ent = efi_pci_roms; ent; ent = ent->next )
265 if ( info->pci_rom.segment == ent->segment &&
266 info->pci_rom.bus == ent->bus &&
267 info->pci_rom.devfn == ent->devfn &&
268 info->pci_rom.vendor == ent->vendor &&
269 info->pci_rom.devid == ent->devid )
270 {
271 info->pci_rom.address = __pa(ent->data);
272 info->pci_rom.size = ent->size;
273 return 0;
274 }
275 return -ESRCH;
276 }
277
278 case XEN_FW_EFI_APPLE_PROPERTIES:
279 if ( !efi_apple_properties_len )
280 return -ENODATA;
281 info->apple_properties.address = efi_apple_properties_addr;
282 info->apple_properties.size = efi_apple_properties_len;
283 break;
284
285 default:
286 return -EINVAL;
287 }
288
289 return 0;
290 }
291
gwstrlen(XEN_GUEST_HANDLE_PARAM (CHAR16)str)292 static long gwstrlen(XEN_GUEST_HANDLE_PARAM(CHAR16) str)
293 {
294 unsigned long len;
295
296 for ( len = 0; ; ++len )
297 {
298 CHAR16 c;
299
300 if ( copy_from_guest_offset(&c, str, len, 1) )
301 return -EFAULT;
302 if ( !c )
303 break;
304 }
305
306 return len;
307 }
308
cast_time(struct xenpf_efi_time * time)309 static inline EFI_TIME *cast_time(struct xenpf_efi_time *time)
310 {
311 #define chk_fld(F, f) \
312 BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \
313 offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f))
314 chk_fld(Year, year);
315 chk_fld(Month, month);
316 chk_fld(Day, day);
317 chk_fld(Hour, hour);
318 chk_fld(Minute, min);
319 chk_fld(Second, sec);
320 chk_fld(Nanosecond, ns);
321 chk_fld(TimeZone, tz);
322 chk_fld(Daylight, daylight);
323 #undef chk_fld
324 return (void *)time;
325 }
326
cast_guid(struct xenpf_efi_guid * guid)327 static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
328 {
329 #define chk_fld(n) \
330 BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \
331 offsetof(EFI_GUID, Data##n) != \
332 offsetof(struct xenpf_efi_guid, data##n))
333 chk_fld(1);
334 chk_fld(2);
335 chk_fld(3);
336 chk_fld(4);
337 #undef chk_fld
338 return (void *)guid;
339 }
340
efi_runtime_call(struct xenpf_efi_runtime_call * op)341 int efi_runtime_call(struct xenpf_efi_runtime_call *op)
342 {
343 struct efi_rs_state state;
344 unsigned long flags;
345 EFI_STATUS status = EFI_NOT_STARTED;
346 int rc = 0;
347
348 if ( !efi_enabled(EFI_BOOT) )
349 return -ENOSYS;
350
351 if ( !efi_enabled(EFI_RS) )
352 return -EOPNOTSUPP;
353
354 switch ( op->function )
355 {
356 case XEN_EFI_get_time:
357 {
358 EFI_TIME_CAPABILITIES caps;
359
360 if ( op->misc )
361 return -EINVAL;
362
363 state = efi_rs_enter();
364 if ( !state.cr3 )
365 return -EOPNOTSUPP;
366 spin_lock_irqsave(&rtc_lock, flags);
367 status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
368 spin_unlock_irqrestore(&rtc_lock, flags);
369 efi_rs_leave(&state);
370
371 if ( !EFI_ERROR(status) )
372 {
373 op->u.get_time.resolution = caps.Resolution;
374 op->u.get_time.accuracy = caps.Accuracy;
375 if ( caps.SetsToZero )
376 op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS;
377 }
378 }
379 break;
380
381 case XEN_EFI_set_time:
382 if ( op->misc )
383 return -EINVAL;
384
385 state = efi_rs_enter();
386 if ( !state.cr3 )
387 return -EOPNOTSUPP;
388 spin_lock_irqsave(&rtc_lock, flags);
389 status = efi_rs->SetTime(cast_time(&op->u.set_time));
390 spin_unlock_irqrestore(&rtc_lock, flags);
391 efi_rs_leave(&state);
392 break;
393
394 case XEN_EFI_get_wakeup_time:
395 {
396 BOOLEAN enabled, pending;
397
398 if ( op->misc )
399 return -EINVAL;
400
401 state = efi_rs_enter();
402 if ( !state.cr3 )
403 return -EOPNOTSUPP;
404 spin_lock_irqsave(&rtc_lock, flags);
405 status = efi_rs->GetWakeupTime(&enabled, &pending,
406 cast_time(&op->u.get_wakeup_time));
407 spin_unlock_irqrestore(&rtc_lock, flags);
408 efi_rs_leave(&state);
409
410 if ( !EFI_ERROR(status) )
411 {
412 if ( enabled )
413 op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED;
414 if ( pending )
415 op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING;
416 }
417 }
418 break;
419
420 case XEN_EFI_set_wakeup_time:
421 if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE |
422 XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) )
423 return -EINVAL;
424
425 state = efi_rs_enter();
426 if ( !state.cr3 )
427 return -EOPNOTSUPP;
428 spin_lock_irqsave(&rtc_lock, flags);
429 status = efi_rs->SetWakeupTime(!!(op->misc &
430 XEN_EFI_SET_WAKEUP_TIME_ENABLE),
431 (op->misc &
432 XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
433 NULL :
434 cast_time(&op->u.set_wakeup_time));
435 spin_unlock_irqrestore(&rtc_lock, flags);
436 efi_rs_leave(&state);
437
438 op->misc = 0;
439 break;
440
441 case XEN_EFI_get_next_high_monotonic_count:
442 if ( op->misc )
443 return -EINVAL;
444
445 state = efi_rs_enter();
446 if ( state.cr3 )
447 status = efi_rs->GetNextHighMonotonicCount(&op->misc);
448 else
449 rc = -EOPNOTSUPP;
450 efi_rs_leave(&state);
451 break;
452
453 case XEN_EFI_get_variable:
454 {
455 CHAR16 *name;
456 long len;
457 unsigned char *data;
458 UINTN size;
459
460 if ( op->misc )
461 return -EINVAL;
462
463 len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16));
464 if ( len < 0 )
465 return len;
466 name = xmalloc_array(CHAR16, ++len);
467 if ( !name )
468 return -ENOMEM;
469 __copy_from_guest(name, op->u.get_variable.name, len);
470
471 size = op->u.get_variable.size;
472 if ( size )
473 {
474 data = xmalloc_bytes(size);
475 if ( !data )
476 {
477 xfree(name);
478 return -ENOMEM;
479 }
480 }
481 else
482 data = NULL;
483
484 state = efi_rs_enter();
485 if ( state.cr3 )
486 {
487 status = efi_rs->GetVariable(
488 name, cast_guid(&op->u.get_variable.vendor_guid),
489 &op->misc, &size, data);
490 efi_rs_leave(&state);
491
492 if ( !EFI_ERROR(status) &&
493 copy_to_guest(op->u.get_variable.data, data, size) )
494 rc = -EFAULT;
495 op->u.get_variable.size = size;
496 }
497 else
498 rc = -EOPNOTSUPP;
499
500 xfree(data);
501 xfree(name);
502 }
503 break;
504
505 case XEN_EFI_set_variable:
506 {
507 CHAR16 *name;
508 long len;
509 unsigned char *data;
510
511 len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16));
512 if ( len < 0 )
513 return len;
514 name = xmalloc_array(CHAR16, ++len);
515 if ( !name )
516 return -ENOMEM;
517 __copy_from_guest(name, op->u.set_variable.name, len);
518
519 data = xmalloc_bytes(op->u.set_variable.size);
520 if ( !data )
521 rc = -ENOMEM;
522 else if ( copy_from_guest(data, op->u.set_variable.data,
523 op->u.set_variable.size) )
524 rc = -EFAULT;
525 else
526 {
527 state = efi_rs_enter();
528 if ( state.cr3 )
529 status = efi_rs->SetVariable(
530 name, cast_guid(&op->u.set_variable.vendor_guid),
531 op->misc, op->u.set_variable.size, data);
532 else
533 rc = -EOPNOTSUPP;
534 efi_rs_leave(&state);
535 }
536
537 xfree(data);
538 xfree(name);
539 }
540 break;
541
542 case XEN_EFI_get_next_variable_name:
543 {
544 union {
545 CHAR16 *str;
546 unsigned char *raw;
547 } name;
548 UINTN size;
549
550 if ( op->misc )
551 return -EINVAL;
552
553 size = op->u.get_next_variable_name.size;
554 name.raw = xmalloc_bytes(size);
555 if ( !name.raw )
556 return -ENOMEM;
557 if ( copy_from_guest(name.raw, op->u.get_next_variable_name.name,
558 size) )
559 {
560 xfree(name.raw);
561 return -EFAULT;
562 }
563
564 state = efi_rs_enter();
565 if ( state.cr3 )
566 {
567 status = efi_rs->GetNextVariableName(
568 &size, name.str,
569 cast_guid(&op->u.get_next_variable_name.vendor_guid));
570 efi_rs_leave(&state);
571
572 /*
573 * Copy the variable name if necessary. The caller provided size
574 * is used because some firmwares update size when they shouldn't.
575 * */
576 if ( !EFI_ERROR(status) &&
577 __copy_to_guest(op->u.get_next_variable_name.name,
578 name.raw, op->u.get_next_variable_name.size) )
579 rc = -EFAULT;
580 op->u.get_next_variable_name.size = size;
581 }
582 else
583 rc = -EOPNOTSUPP;
584
585 xfree(name.raw);
586 }
587 break;
588
589 case XEN_EFI_query_variable_info:
590 if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
591 return -EINVAL;
592
593 if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
594 {
595 if ( (op->u.query_variable_info.attr
596 & ~EFI_VARIABLE_APPEND_WRITE) !=
597 (EFI_VARIABLE_NON_VOLATILE |
598 EFI_VARIABLE_BOOTSERVICE_ACCESS |
599 EFI_VARIABLE_RUNTIME_ACCESS) )
600 return -EINVAL;
601
602 op->u.query_variable_info.max_store_size =
603 efi_boot_max_var_store_size;
604 op->u.query_variable_info.remain_store_size =
605 efi_boot_remain_var_store_size;
606 if ( efi_boot_max_var_store_size )
607 {
608 op->u.query_variable_info.max_size = efi_boot_max_var_size;
609 status = EFI_SUCCESS;
610 }
611 else
612 {
613 op->u.query_variable_info.max_size = 0;
614 status = efi_boot_max_var_size;
615 }
616 break;
617 }
618
619 state = efi_rs_enter();
620 if ( !state.cr3 || (efi_rs->Hdr.Revision >> 16) < 2 )
621 {
622 efi_rs_leave(&state);
623 return -EOPNOTSUPP;
624 }
625 status = efi_rs->QueryVariableInfo(
626 op->u.query_variable_info.attr,
627 &op->u.query_variable_info.max_store_size,
628 &op->u.query_variable_info.remain_store_size,
629 &op->u.query_variable_info.max_size);
630 efi_rs_leave(&state);
631 break;
632
633 case XEN_EFI_query_capsule_capabilities:
634 case XEN_EFI_update_capsule:
635 if ( op->misc )
636 return -EINVAL;
637
638 state = efi_rs_enter();
639 if ( !state.cr3 || (efi_rs->Hdr.Revision >> 16) < 2 )
640 {
641 efi_rs_leave(&state);
642 return -EOPNOTSUPP;
643 }
644 efi_rs_leave(&state);
645 /* XXX fall through for now */
646 default:
647 return -ENOSYS;
648 }
649
650 #ifndef COMPAT
651 op->status = status;
652 #else
653 op->status = (status & 0x3fffffff) | ((status >> 32) & 0xc0000000);
654 #endif
655
656 return rc;
657 }
658 #endif
659