Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / platform / efi / efi-xen.c
1 /*
2  * Common EFI (Extensible Firmware Interface) support functions
3  * Based on Extensible Firmware Interface Specification version 1.0
4  *
5  * Copyright (C) 1999 VA Linux Systems
6  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
7  * Copyright (C) 1999-2002 Hewlett-Packard Co.
8  *      David Mosberger-Tang <davidm@hpl.hp.com>
9  *      Stephane Eranian <eranian@hpl.hp.com>
10  * Copyright (C) 2005-2008 Intel Co.
11  *      Fenghua Yu <fenghua.yu@intel.com>
12  *      Bibo Mao <bibo.mao@intel.com>
13  *      Chandramouli Narayanan <mouli@linux.intel.com>
14  *      Huang Ying <ying.huang@intel.com>
15  *
16  * Copied from efi_32.c to eliminate the duplicated code between EFI
17  * 32/64 support code. --ying 2007-10-26
18  *
19  * All EFI Runtime Services are not implemented yet as EFI only
20  * supports physical mode addressing on SoftSDV. This is to be fixed
21  * in a future version.  --drummond 1999-07-20
22  *
23  * Implemented EFI runtime services and virtual mode calls.  --davidm
24  *
25  * Goutham Rao: <goutham.rao@intel.com>
26  *      Skip non-WB memory and ignore empty memory ranges.
27  */
28
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31 #include <linux/kernel.h>
32 #include <linux/init.h>
33 #include <linux/efi.h>
34 #include <linux/export.h>
35 #include <linux/platform_device.h>
36 #include <linux/spinlock.h>
37 #include <linux/time.h>
38
39 #include <asm/setup.h>
40 #include <asm/efi.h>
41 #include <asm/time.h>
42 #include <asm/cacheflush.h>
43 #include <asm/tlbflush.h>
44 #include <asm/x86_init.h>
45
46 #include <xen/interface/platform.h>
47
48 #define EFI_DEBUG       1
49
50 int __read_mostly efi_enabled;
51 EXPORT_SYMBOL(efi_enabled);
52
53 #define call op.u.efi_runtime_call
54 #define DECLARE_CALL(what) \
55         struct xen_platform_op op; \
56         op.cmd = XENPF_efi_runtime_call; \
57         call.function = XEN_EFI_##what; \
58         call.misc = 0
59
60 static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
61 {
62         int err;
63         DECLARE_CALL(get_time);
64
65         err = HYPERVISOR_platform_op(&op);
66         if (err)
67                 return EFI_UNSUPPORTED;
68
69         if (tm) {
70                 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
71                 memcpy(tm, &call.u.get_time.time, sizeof(*tm));
72         }
73
74         if (tc) {
75                 tc->resolution = call.u.get_time.resolution;
76                 tc->accuracy = call.u.get_time.accuracy;
77                 tc->sets_to_zero = !!(call.misc &
78                                       XEN_EFI_GET_TIME_SET_CLEARS_NS);
79         }
80
81         return call.status;
82 }
83
84 static efi_status_t xen_efi_set_time(efi_time_t *tm)
85 {
86         DECLARE_CALL(set_time);
87
88         BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
89         memcpy(&call.u.set_time, tm, sizeof(*tm));
90
91         return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
92 }
93
94 static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
95                                             efi_bool_t *pending,
96                                             efi_time_t *tm)
97 {
98         int err;
99         DECLARE_CALL(get_wakeup_time);
100
101         err = HYPERVISOR_platform_op(&op);
102         if (err)
103                 return EFI_UNSUPPORTED;
104
105         if (tm) {
106                 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
107                 memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
108         }
109
110         if (enabled)
111                 *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
112
113         if (pending)
114                 *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
115
116         return call.status;
117 }
118
119 static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
120 {
121         DECLARE_CALL(set_wakeup_time);
122
123         BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
124         if (enabled)
125                 call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
126         if (tm)
127                 memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
128         else
129                 call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
130
131         return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
132 }
133
134 static efi_status_t xen_efi_get_variable(efi_char16_t *name,
135                                          efi_guid_t *vendor,
136                                          u32 *attr,
137                                          unsigned long *data_size,
138                                          void *data)
139 {
140         int err;
141         DECLARE_CALL(get_variable);
142
143         set_xen_guest_handle(call.u.get_variable.name, name);
144         BUILD_BUG_ON(sizeof(*vendor) !=
145                      sizeof(call.u.get_variable.vendor_guid));
146         memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
147         call.u.get_variable.size = *data_size;
148         set_xen_guest_handle(call.u.get_variable.data, data);
149         err = HYPERVISOR_platform_op(&op);
150         if (err)
151                 return EFI_UNSUPPORTED;
152
153         *data_size = call.u.get_variable.size;
154         *attr = call.misc;
155
156         return call.status;
157 }
158
159 static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
160                                               efi_char16_t *name,
161                                               efi_guid_t *vendor)
162 {
163         int err;
164         DECLARE_CALL(get_next_variable_name);
165
166         call.u.get_next_variable_name.size = *name_size;
167         set_xen_guest_handle(call.u.get_next_variable_name.name, name);
168         BUILD_BUG_ON(sizeof(*vendor) !=
169                      sizeof(call.u.get_next_variable_name.vendor_guid));
170         memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
171                sizeof(*vendor));
172         err = HYPERVISOR_platform_op(&op);
173         if (err)
174                 return EFI_UNSUPPORTED;
175
176         *name_size = call.u.get_next_variable_name.size;
177         memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
178                sizeof(*vendor));
179
180         return call.status;
181 }
182
183 static efi_status_t xen_efi_set_variable(efi_char16_t *name,
184                                          efi_guid_t *vendor,
185                                          u32 attr,
186                                          unsigned long data_size,
187                                          void *data)
188 {
189         DECLARE_CALL(set_variable);
190
191         set_xen_guest_handle(call.u.set_variable.name, name);
192         call.misc = attr;
193         BUILD_BUG_ON(sizeof(*vendor) !=
194                      sizeof(call.u.set_variable.vendor_guid));
195         memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
196         call.u.set_variable.size = data_size;
197         set_xen_guest_handle(call.u.set_variable.data, data);
198
199         return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
200 }
201
202 static efi_status_t xen_efi_query_variable_info(u32 attr,
203                                                 u64 *storage_space,
204                                                 u64 *remaining_space,
205                                                 u64 *max_variable_size)
206 {
207         int err;
208         DECLARE_CALL(query_variable_info);
209
210         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
211                 return EFI_UNSUPPORTED;
212
213         err = HYPERVISOR_platform_op(&op);
214         if (err)
215                 return EFI_UNSUPPORTED;
216
217         *storage_space = call.u.query_variable_info.max_store_size;
218         *remaining_space = call.u.query_variable_info.remain_store_size;
219         *max_variable_size = call.u.query_variable_info.max_size;
220
221         return call.status;
222 }
223
224 static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
225 {
226         int err;
227         DECLARE_CALL(get_next_high_monotonic_count);
228
229         err = HYPERVISOR_platform_op(&op);
230         if (err)
231                 return EFI_UNSUPPORTED;
232
233         *count = call.misc;
234
235         return call.status;
236 }
237
238 static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
239                                            unsigned long count,
240                                            unsigned long sg_list)
241 {
242         DECLARE_CALL(update_capsule);
243
244         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
245                 return EFI_UNSUPPORTED;
246
247         set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
248                              capsules);
249         call.u.update_capsule.capsule_count = count;
250         call.u.update_capsule.sg_list = sg_list;
251
252         return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
253 }
254
255 static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
256                                                unsigned long count,
257                                                u64 *max_size,
258                                                int *reset_type)
259 {
260         int err;
261         DECLARE_CALL(query_capsule_capabilities);
262
263         if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
264                 return EFI_UNSUPPORTED;
265
266         set_xen_guest_handle(call.u.query_capsule_capabilities.capsule_header_array,
267                              capsules);
268         call.u.query_capsule_capabilities.capsule_count = count;
269
270         err = HYPERVISOR_platform_op(&op);
271         if (err)
272                 return EFI_UNSUPPORTED;
273
274         *max_size = call.u.query_capsule_capabilities.max_capsule_size;
275         *reset_type = call.u.query_capsule_capabilities.reset_type;
276
277         return call.status;
278 }
279
280 #undef DECLARE_CALL
281 #undef call
282
283 struct efi __read_mostly efi = {
284         .mps                      = EFI_INVALID_TABLE_ADDR,
285         .acpi                     = EFI_INVALID_TABLE_ADDR,
286         .acpi20                   = EFI_INVALID_TABLE_ADDR,
287         .smbios                   = EFI_INVALID_TABLE_ADDR,
288         .sal_systab               = EFI_INVALID_TABLE_ADDR,
289         .boot_info                = EFI_INVALID_TABLE_ADDR,
290         .hcdp                     = EFI_INVALID_TABLE_ADDR,
291         .uga                      = EFI_INVALID_TABLE_ADDR,
292         .uv_systab                = EFI_INVALID_TABLE_ADDR,
293         .get_time                 = xen_efi_get_time,
294         .set_time                 = xen_efi_set_time,
295         .get_wakeup_time          = xen_efi_get_wakeup_time,
296         .set_wakeup_time          = xen_efi_set_wakeup_time,
297         .get_variable             = xen_efi_get_variable,
298         .get_next_variable        = xen_efi_get_next_variable,
299         .set_variable             = xen_efi_set_variable,
300         .get_next_high_mono_count = xen_efi_get_next_high_mono_count,
301         .query_variable_info      = xen_efi_query_variable_info,
302         .update_capsule           = xen_efi_update_capsule,
303         .query_capsule_caps       = xen_efi_query_capsule_caps,
304 };
305 EXPORT_SYMBOL(efi);
306
307 static int __init setup_noefi(char *arg)
308 {
309         efi_enabled = 0;
310         return 0;
311 }
312 early_param("noefi", setup_noefi);
313
314
315 int efi_set_rtc_mmss(unsigned long nowtime)
316 {
317         int real_seconds, real_minutes;
318         efi_status_t    status;
319         efi_time_t      eft;
320         efi_time_cap_t  cap;
321
322         status = efi.get_time(&eft, &cap);
323         if (status != EFI_SUCCESS) {
324                 pr_err("Oops: efitime: can't read time!\n");
325                 return -1;
326         }
327
328         real_seconds = nowtime % 60;
329         real_minutes = nowtime / 60;
330         if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
331                 real_minutes += 30;
332         real_minutes %= 60;
333         eft.minute = real_minutes;
334         eft.second = real_seconds;
335
336         status = efi.set_time(&eft);
337         if (status != EFI_SUCCESS) {
338                 pr_err("Oops: efitime: can't write time!\n");
339                 return -1;
340         }
341         return 0;
342 }
343
344 unsigned long efi_get_time(void)
345 {
346         efi_status_t status;
347         efi_time_t eft;
348         efi_time_cap_t cap;
349
350         status = efi.get_time(&eft, &cap);
351         if (status != EFI_SUCCESS) {
352                 pr_err("Oops: efitime: can't read time!\n");
353                 return mach_get_cmos_time();
354         }
355
356         return mktime(eft.year, eft.month, eft.day, eft.hour,
357                       eft.minute, eft.second);
358 }
359
360 void __init efi_probe(void)
361 {
362         static struct xen_platform_op __initdata op = {
363                 .cmd = XENPF_firmware_info,
364                 .u.firmware_info = {
365                         .type = XEN_FW_EFI_INFO,
366                         .index = XEN_FW_EFI_CONFIG_TABLE
367                 }
368         };
369
370         if (HYPERVISOR_platform_op(&op) == 0)
371                 efi_enabled = 1;
372 }
373
374 void __init efi_reserve_boot_services(void) { }
375
376 static int __init efi_config_init(u64 tables, unsigned int nr_tables)
377 {
378         void *config_tables, *tablep;
379         unsigned int i, sz = sizeof(efi_config_table_t);
380
381         /*
382          * Let's see what config tables the firmware passed to us.
383          */
384         config_tables = early_ioremap(tables, nr_tables * sz);
385         if (config_tables == NULL) {
386                 pr_err("Could not map Configuration table!\n");
387                 return -ENOMEM;
388         }
389
390         tablep = config_tables;
391         pr_info("");
392         for (i = 0; i < nr_tables; i++) {
393                 efi_guid_t guid;
394                 unsigned long table;
395
396                 guid = ((efi_config_table_t *)tablep)->guid;
397                 table = ((efi_config_table_t *)tablep)->table;
398                 if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
399                         efi.mps = table;
400                         pr_cont(" MPS=0x%lx ", table);
401                 } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
402                         efi.acpi20 = table;
403                         pr_cont(" ACPI 2.0=0x%lx ", table);
404                 } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
405                         efi.acpi = table;
406                         pr_cont(" ACPI=0x%lx ", table);
407                 } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
408                         efi.smbios = table;
409                         pr_cont(" SMBIOS=0x%lx ", table);
410                 } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
411                         efi.hcdp = table;
412                         pr_cont(" HCDP=0x%lx ", table);
413                 } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
414                         efi.uga = table;
415                         pr_cont(" UGA=0x%lx ", table);
416                 }
417                 tablep += sz;
418         }
419         pr_cont("\n");
420         early_iounmap(config_tables, nr_tables * sz);
421         return 0;
422 }
423
424 void __init efi_init(void)
425 {
426         efi_char16_t c16[100];
427         char vendor[ARRAY_SIZE(c16)] = "unknown";
428         int ret, i;
429         struct xen_platform_op op;
430         union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
431
432         op.cmd = XENPF_firmware_info;
433         op.u.firmware_info.type = XEN_FW_EFI_INFO;
434
435         /*
436          * Show what we know for posterity
437          */
438         op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
439         info->vendor.bufsz = sizeof(c16);
440         set_xen_guest_handle(info->vendor.name, c16);
441         ret = HYPERVISOR_platform_op(&op);
442         if (!ret) {
443                 for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
444                         vendor[i] = c16[i];
445                 vendor[i] = '\0';
446         } else
447                 pr_err("Could not get the firmware vendor!\n");
448
449         op.u.firmware_info.index = XEN_FW_EFI_VERSION;
450         ret = HYPERVISOR_platform_op(&op);
451         if (!ret)
452                 pr_info("EFI v%u.%.02u by %s\n",
453                         info->version >> 16,
454                         info->version & 0xffff, vendor);
455         else
456                 pr_err("Could not get EFI revision!\n");
457
458         op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
459         ret = HYPERVISOR_platform_op(&op);
460         if (!ret)
461                 efi.runtime_version = info->version;
462         else
463                 pr_warn("Could not get runtime services revision.\n");
464
465         op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
466         if (HYPERVISOR_platform_op(&op))
467                 BUG();
468         if (efi_config_init(info->cfg.addr, info->cfg.nent)) {
469                 efi_enabled = 0;
470                 return;
471         }
472
473         x86_platform.get_wallclock = efi_get_time;
474         x86_platform.set_wallclock = efi_set_rtc_mmss;
475 }
476
477 void __init efi_enter_virtual_mode(void) { }
478
479 static struct platform_device rtc_efi_dev = {
480         .name = "rtc-efi",
481         .id = -1,
482 };
483
484 static int __init rtc_init(void)
485 {
486         if (efi_enabled && platform_device_register(&rtc_efi_dev) < 0)
487                 pr_err("unable to register rtc device...\n");
488
489         /* not necessarily an error */
490         return 0;
491 }
492 arch_initcall(rtc_init);
493
494 /*
495  * Convenience functions to obtain memory types and attributes
496  */
497 u32 efi_mem_type(unsigned long phys_addr)
498 {
499         struct xen_platform_op op;
500         union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
501
502         op.cmd = XENPF_firmware_info;
503         op.u.firmware_info.type = XEN_FW_EFI_INFO;
504         op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
505         info->mem.addr = phys_addr;
506         info->mem.size = 0;
507         return HYPERVISOR_platform_op(&op) ? 0 : info->mem.type;
508 }
509
510 u64 efi_mem_attributes(unsigned long phys_addr)
511 {
512         struct xen_platform_op op;
513         union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
514
515         op.cmd = XENPF_firmware_info;
516         op.u.firmware_info.type = XEN_FW_EFI_INFO;
517         op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
518         info->mem.addr = phys_addr;
519         info->mem.size = 0;
520         return HYPERVISOR_platform_op(&op) ? 0 : info->mem.attr;
521 }