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