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