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, smp_processor_id()) -
108                                      FIRST_RESERVED_GDT_ENTRY)
109         };
110 
111         lgdt(&gdt_desc);
112     }
113 
114     switch_cr3_cr4(virt_to_maddr(efi_l4_pgtable), read_cr4());
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     struct vcpu *curr = current;
122 
123     if ( !state->cr3 )
124         return;
125     switch_cr3_cr4(state->cr3, read_cr4());
126     if ( is_pv_vcpu(curr) && !is_idle_vcpu(curr) )
127     {
128         struct desc_ptr gdt_desc = {
129             .limit = LAST_RESERVED_GDT_BYTE,
130             .base  = GDT_VIRT_START(curr)
131         };
132 
133         lgdt(&gdt_desc);
134     }
135     irq_exit();
136     efi_rs_on_cpu = NR_CPUS;
137     spin_unlock(&efi_rs_lock);
138     vcpu_restore_fpu_nonlazy(curr, true);
139 }
140 
efi_rs_using_pgtables(void)141 bool efi_rs_using_pgtables(void)
142 {
143     return efi_l4_pgtable &&
144            (smp_processor_id() == efi_rs_on_cpu) &&
145            (read_cr3() == virt_to_maddr(efi_l4_pgtable));
146 }
147 
efi_get_time(void)148 unsigned long efi_get_time(void)
149 {
150     EFI_TIME time;
151     EFI_STATUS status;
152     struct efi_rs_state state = efi_rs_enter();
153     unsigned long flags;
154 
155     if ( !state.cr3 )
156         return 0;
157     spin_lock_irqsave(&rtc_lock, flags);
158     status = efi_rs->GetTime(&time, NULL);
159     spin_unlock_irqrestore(&rtc_lock, flags);
160     efi_rs_leave(&state);
161 
162     if ( EFI_ERROR(status) )
163         return 0;
164 
165     return mktime(time.Year, time.Month, time.Day,
166                   time.Hour, time.Minute, time.Second);
167 }
168 
efi_halt_system(void)169 void efi_halt_system(void)
170 {
171     EFI_STATUS status;
172     struct efi_rs_state state = efi_rs_enter();
173 
174     if ( !state.cr3 )
175         return;
176     status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
177     efi_rs_leave(&state);
178 
179     printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status);
180 }
181 
efi_reset_system(bool warm)182 void efi_reset_system(bool warm)
183 {
184     EFI_STATUS status;
185     struct efi_rs_state state = efi_rs_enter();
186 
187     if ( !state.cr3 )
188         return;
189     status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold,
190                                  EFI_SUCCESS, 0, NULL);
191     efi_rs_leave(&state);
192 
193     printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
194 }
195 
196 #endif /* CONFIG_ARM */
197 
wmemchr(const CHAR16 * s,CHAR16 c,UINTN n)198 const CHAR16 *wmemchr(const CHAR16 *s, CHAR16 c, UINTN n)
199 {
200     while ( n && *s != c )
201     {
202         --n;
203         ++s;
204     }
205     return n ? s : NULL;
206 }
207 
208 #endif /* COMPAT */
209 
210 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
efi_get_info(uint32_t idx,union xenpf_efi_info * info)211 int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
212 {
213     unsigned int i, n;
214 
215     if ( !efi_enabled(EFI_BOOT) )
216         return -ENOSYS;
217 
218     switch ( idx )
219     {
220     case XEN_FW_EFI_VERSION:
221         info->version = efi_version;
222         break;
223     case XEN_FW_EFI_RT_VERSION:
224     {
225         if ( !efi_enabled(EFI_RS) )
226             return -EOPNOTSUPP;
227         info->version = efi_rs->Hdr.Revision;
228         break;
229     }
230     case XEN_FW_EFI_CONFIG_TABLE:
231         info->cfg.addr = __pa(efi_ct);
232         info->cfg.nent = efi_num_ct;
233         break;
234     case XEN_FW_EFI_VENDOR:
235         if ( !efi_fw_vendor )
236             return -EOPNOTSUPP;
237         info->vendor.revision = efi_fw_revision;
238         n = info->vendor.bufsz / sizeof(*efi_fw_vendor);
239         if ( !guest_handle_okay(guest_handle_cast(info->vendor.name,
240                                                   CHAR16), n) )
241             return -EFAULT;
242         for ( i = 0; i < n; ++i )
243         {
244             if ( __copy_to_guest_offset(info->vendor.name, i,
245                                         efi_fw_vendor + i, 1) )
246                 return -EFAULT;
247             if ( !efi_fw_vendor[i] )
248                 break;
249         }
250         break;
251     case XEN_FW_EFI_MEM_INFO:
252         for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
253         {
254             EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
255             u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
256 
257             if ( info->mem.addr >= desc->PhysicalStart &&
258                  info->mem.addr < desc->PhysicalStart + len )
259             {
260                 info->mem.type = desc->Type;
261                 info->mem.attr = desc->Attribute;
262                 if ( info->mem.addr + info->mem.size < info->mem.addr ||
263                      info->mem.addr + info->mem.size >
264                      desc->PhysicalStart + len )
265                     info->mem.size = desc->PhysicalStart + len -
266                                      info->mem.addr;
267                 return 0;
268             }
269         }
270         return -ESRCH;
271     case XEN_FW_EFI_PCI_ROM: {
272         const struct efi_pci_rom *ent;
273 
274         for ( ent = efi_pci_roms; ent; ent = ent->next )
275             if ( info->pci_rom.segment == ent->segment &&
276                  info->pci_rom.bus == ent->bus &&
277                  info->pci_rom.devfn == ent->devfn &&
278                  info->pci_rom.vendor == ent->vendor &&
279                  info->pci_rom.devid == ent->devid )
280             {
281                 info->pci_rom.address = __pa(ent->data);
282                 info->pci_rom.size = ent->size;
283                 return 0;
284             }
285         return -ESRCH;
286     }
287 
288     case XEN_FW_EFI_APPLE_PROPERTIES:
289         if ( !efi_apple_properties_len )
290             return -ENODATA;
291         info->apple_properties.address = efi_apple_properties_addr;
292         info->apple_properties.size = efi_apple_properties_len;
293         break;
294 
295     default:
296         return -EINVAL;
297     }
298 
299     return 0;
300 }
301 
gwstrlen(XEN_GUEST_HANDLE_PARAM (CHAR16)str)302 static long gwstrlen(XEN_GUEST_HANDLE_PARAM(CHAR16) str)
303 {
304     unsigned long len;
305 
306     for ( len = 0; ; ++len )
307     {
308         CHAR16 c;
309 
310         if ( copy_from_guest_offset(&c, str, len, 1) )
311             return -EFAULT;
312         if ( !c )
313             break;
314     }
315 
316     return len;
317 }
318 
cast_time(struct xenpf_efi_time * time)319 static inline EFI_TIME *cast_time(struct xenpf_efi_time *time)
320 {
321 #define chk_fld(F, f) \
322     BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \
323                  offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f))
324     chk_fld(Year, year);
325     chk_fld(Month, month);
326     chk_fld(Day, day);
327     chk_fld(Hour, hour);
328     chk_fld(Minute, min);
329     chk_fld(Second, sec);
330     chk_fld(Nanosecond, ns);
331     chk_fld(TimeZone, tz);
332     chk_fld(Daylight, daylight);
333 #undef chk_fld
334     return (void *)time;
335 }
336 
cast_guid(struct xenpf_efi_guid * guid)337 static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
338 {
339 #define chk_fld(n) \
340     BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \
341                  offsetof(EFI_GUID, Data##n) != \
342                  offsetof(struct xenpf_efi_guid, data##n))
343     chk_fld(1);
344     chk_fld(2);
345     chk_fld(3);
346     chk_fld(4);
347 #undef chk_fld
348     return (void *)guid;
349 }
350 
efi_runtime_call(struct xenpf_efi_runtime_call * op)351 int efi_runtime_call(struct xenpf_efi_runtime_call *op)
352 {
353     struct efi_rs_state state;
354     unsigned long flags;
355     EFI_STATUS status = EFI_NOT_STARTED;
356     int rc = 0;
357 
358     if ( !efi_enabled(EFI_BOOT) )
359         return -ENOSYS;
360 
361     if ( !efi_enabled(EFI_RS) )
362         return -EOPNOTSUPP;
363 
364     switch ( op->function )
365     {
366     case XEN_EFI_get_time:
367     {
368         EFI_TIME_CAPABILITIES caps;
369 
370         if ( op->misc )
371             return -EINVAL;
372 
373         state = efi_rs_enter();
374         if ( !state.cr3 )
375             return -EOPNOTSUPP;
376         spin_lock_irqsave(&rtc_lock, flags);
377         status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
378         spin_unlock_irqrestore(&rtc_lock, flags);
379         efi_rs_leave(&state);
380 
381         if ( !EFI_ERROR(status) )
382         {
383             op->u.get_time.resolution = caps.Resolution;
384             op->u.get_time.accuracy = caps.Accuracy;
385             if ( caps.SetsToZero )
386                 op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS;
387         }
388     }
389     break;
390 
391     case XEN_EFI_set_time:
392         if ( op->misc )
393             return -EINVAL;
394 
395         state = efi_rs_enter();
396         if ( !state.cr3 )
397             return -EOPNOTSUPP;
398         spin_lock_irqsave(&rtc_lock, flags);
399         status = efi_rs->SetTime(cast_time(&op->u.set_time));
400         spin_unlock_irqrestore(&rtc_lock, flags);
401         efi_rs_leave(&state);
402         break;
403 
404     case XEN_EFI_get_wakeup_time:
405     {
406         BOOLEAN enabled, pending;
407 
408         if ( op->misc )
409             return -EINVAL;
410 
411         state = efi_rs_enter();
412         if ( !state.cr3 )
413             return -EOPNOTSUPP;
414         spin_lock_irqsave(&rtc_lock, flags);
415         status = efi_rs->GetWakeupTime(&enabled, &pending,
416                                        cast_time(&op->u.get_wakeup_time));
417         spin_unlock_irqrestore(&rtc_lock, flags);
418         efi_rs_leave(&state);
419 
420         if ( !EFI_ERROR(status) )
421         {
422             if ( enabled )
423                 op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED;
424             if ( pending )
425                 op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING;
426         }
427     }
428     break;
429 
430     case XEN_EFI_set_wakeup_time:
431         if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE |
432                           XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) )
433             return -EINVAL;
434 
435         state = efi_rs_enter();
436         if ( !state.cr3 )
437             return -EOPNOTSUPP;
438         spin_lock_irqsave(&rtc_lock, flags);
439         status = efi_rs->SetWakeupTime(!!(op->misc &
440                                           XEN_EFI_SET_WAKEUP_TIME_ENABLE),
441                                        (op->misc &
442                                         XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
443                                        NULL :
444                                        cast_time(&op->u.set_wakeup_time));
445         spin_unlock_irqrestore(&rtc_lock, flags);
446         efi_rs_leave(&state);
447 
448         op->misc = 0;
449         break;
450 
451     case XEN_EFI_get_next_high_monotonic_count:
452         if ( op->misc )
453             return -EINVAL;
454 
455         state = efi_rs_enter();
456         if ( state.cr3 )
457             status = efi_rs->GetNextHighMonotonicCount(&op->misc);
458         else
459             rc = -EOPNOTSUPP;
460         efi_rs_leave(&state);
461         break;
462 
463     case XEN_EFI_get_variable:
464     {
465         CHAR16 *name;
466         long len;
467         unsigned char *data;
468         UINTN size;
469 
470         if ( op->misc )
471             return -EINVAL;
472 
473         len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16));
474         if ( len < 0 )
475             return len;
476         name = xmalloc_array(CHAR16, ++len);
477         if ( !name )
478            return -ENOMEM;
479         if ( __copy_from_guest(name, op->u.get_variable.name, len) ||
480              wmemchr(name, 0, len) != name + len - 1 )
481         {
482             xfree(name);
483             return -EIO;
484         }
485 
486         size = op->u.get_variable.size;
487         if ( size )
488         {
489             data = xmalloc_bytes(size);
490             if ( !data )
491             {
492                 xfree(name);
493                 return -ENOMEM;
494             }
495         }
496         else
497             data = NULL;
498 
499         state = efi_rs_enter();
500         if ( state.cr3 )
501         {
502             status = efi_rs->GetVariable(
503                 name, cast_guid(&op->u.get_variable.vendor_guid),
504                 &op->misc, &size, data);
505             efi_rs_leave(&state);
506 
507             if ( !EFI_ERROR(status) &&
508                  copy_to_guest(op->u.get_variable.data, data, size) )
509                 rc = -EFAULT;
510             op->u.get_variable.size = size;
511         }
512         else
513             rc = -EOPNOTSUPP;
514 
515         xfree(data);
516         xfree(name);
517     }
518     break;
519 
520     case XEN_EFI_set_variable:
521     {
522         CHAR16 *name;
523         long len;
524         unsigned char *data;
525 
526         len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16));
527         if ( len < 0 )
528             return len;
529         name = xmalloc_array(CHAR16, ++len);
530         if ( !name )
531            return -ENOMEM;
532         if ( __copy_from_guest(name, op->u.set_variable.name, len) ||
533              wmemchr(name, 0, len) != name + len - 1 )
534         {
535             xfree(name);
536             return -EIO;
537         }
538 
539         data = xmalloc_bytes(op->u.set_variable.size);
540         if ( !data )
541             rc = -ENOMEM;
542         else if ( copy_from_guest(data, op->u.set_variable.data,
543                                   op->u.set_variable.size) )
544             rc = -EFAULT;
545         else
546         {
547             state = efi_rs_enter();
548             if ( state.cr3 )
549                 status = efi_rs->SetVariable(
550                     name, cast_guid(&op->u.set_variable.vendor_guid),
551                     op->misc, op->u.set_variable.size, data);
552             else
553                 rc = -EOPNOTSUPP;
554             efi_rs_leave(&state);
555         }
556 
557         xfree(data);
558         xfree(name);
559     }
560     break;
561 
562     case XEN_EFI_get_next_variable_name:
563     {
564         union {
565             CHAR16 *str;
566             unsigned char *raw;
567         } name;
568         UINTN size;
569 
570         if ( op->misc )
571             return -EINVAL;
572 
573         size = op->u.get_next_variable_name.size;
574         name.raw = xzalloc_bytes(size);
575         if ( !name.raw )
576             return -ENOMEM;
577         if ( copy_from_guest(name.raw, op->u.get_next_variable_name.name,
578                              size) )
579         {
580             xfree(name.raw);
581             return -EFAULT;
582         }
583 
584         state = efi_rs_enter();
585         if ( state.cr3 )
586         {
587             status = efi_rs->GetNextVariableName(
588                 &size, name.str,
589                 cast_guid(&op->u.get_next_variable_name.vendor_guid));
590             efi_rs_leave(&state);
591 
592             /*
593              * Copy the variable name if necessary. The caller provided size
594              * is used because some firmwares update size when they shouldn't.
595              * */
596             if ( !EFI_ERROR(status) &&
597                  __copy_to_guest(op->u.get_next_variable_name.name,
598                                  name.raw, op->u.get_next_variable_name.size) )
599                 rc = -EFAULT;
600             op->u.get_next_variable_name.size = size;
601         }
602         else
603             rc = -EOPNOTSUPP;
604 
605         xfree(name.raw);
606     }
607     break;
608 
609     case XEN_EFI_query_variable_info:
610         if ( op->misc & ~XEN_EFI_VARINFO_BOOT_SNAPSHOT )
611             return -EINVAL;
612 
613         if ( op->misc & XEN_EFI_VARINFO_BOOT_SNAPSHOT )
614         {
615             if ( (op->u.query_variable_info.attr
616                   & ~EFI_VARIABLE_APPEND_WRITE) !=
617                  (EFI_VARIABLE_NON_VOLATILE |
618                   EFI_VARIABLE_BOOTSERVICE_ACCESS |
619                   EFI_VARIABLE_RUNTIME_ACCESS) )
620                 return -EINVAL;
621 
622             op->u.query_variable_info.max_store_size =
623                 efi_boot_max_var_store_size;
624             op->u.query_variable_info.remain_store_size =
625                 efi_boot_remain_var_store_size;
626             if ( efi_boot_max_var_store_size )
627             {
628                 op->u.query_variable_info.max_size = efi_boot_max_var_size;
629                 status = EFI_SUCCESS;
630             }
631             else
632             {
633                 op->u.query_variable_info.max_size = 0;
634                 status = efi_boot_max_var_size;
635             }
636             break;
637         }
638 
639         if ( !efi_enabled(EFI_RS) || (efi_rs->Hdr.Revision >> 16) < 2 )
640             return -EOPNOTSUPP;
641         state = efi_rs_enter();
642         if ( !state.cr3 )
643             return -EOPNOTSUPP;
644         status = efi_rs->QueryVariableInfo(
645             op->u.query_variable_info.attr,
646             &op->u.query_variable_info.max_store_size,
647             &op->u.query_variable_info.remain_store_size,
648             &op->u.query_variable_info.max_size);
649         efi_rs_leave(&state);
650         break;
651 
652     case XEN_EFI_query_capsule_capabilities:
653     case XEN_EFI_update_capsule:
654         if ( op->misc )
655             return -EINVAL;
656 
657         if ( !efi_enabled(EFI_RS) || (efi_rs->Hdr.Revision >> 16) < 2 )
658             return -EOPNOTSUPP;
659         /* XXX fall through for now */
660     default:
661         return -ENOSYS;
662     }
663 
664 #ifndef COMPAT
665     op->status = status;
666 #else
667     op->status = (status & 0x3fffffff) | ((status >> 32) & 0xc0000000);
668 #endif
669 
670     return rc;
671 }
672 #endif
673