2 * Common EFI (Extensible Firmware Interface) support functions
3 * Based on Extensible Firmware Interface Specification version 1.0
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>
16 * Copied from efi_32.c to eliminate the duplicated code between EFI
17 * 32/64 support code. --ying 2007-10-26
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
23 * Implemented EFI runtime services and virtual mode calls. --davidm
25 * Goutham Rao: <goutham.rao@intel.com>
26 * Skip non-WB memory and ignore empty memory ranges.
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
39 #include <asm/setup.h>
42 #include <asm/cacheflush.h>
43 #include <asm/tlbflush.h>
44 #include <asm/x86_init.h>
46 #include <xen/interface/platform.h>
50 int __read_mostly efi_enabled;
51 EXPORT_SYMBOL(efi_enabled);
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; \
60 static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
63 DECLARE_CALL(get_time);
65 err = HYPERVISOR_platform_op(&op);
67 return EFI_UNSUPPORTED;
70 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
71 memcpy(tm, &call.u.get_time.time, sizeof(*tm));
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);
84 static efi_status_t xen_efi_set_time(efi_time_t *tm)
86 DECLARE_CALL(set_time);
88 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
89 memcpy(&call.u.set_time, tm, sizeof(*tm));
91 return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
94 static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
99 DECLARE_CALL(get_wakeup_time);
101 err = HYPERVISOR_platform_op(&op);
103 return EFI_UNSUPPORTED;
106 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
107 memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
111 *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
114 *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
119 static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
121 DECLARE_CALL(set_wakeup_time);
123 BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
125 call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
127 memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
129 call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
131 return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
134 static efi_status_t xen_efi_get_variable(efi_char16_t *name,
137 unsigned long *data_size,
141 DECLARE_CALL(get_variable);
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);
151 return EFI_UNSUPPORTED;
153 *data_size = call.u.get_variable.size;
159 static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
164 DECLARE_CALL(get_next_variable_name);
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,
172 err = HYPERVISOR_platform_op(&op);
174 return EFI_UNSUPPORTED;
176 *name_size = call.u.get_next_variable_name.size;
177 memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
183 static efi_status_t xen_efi_set_variable(efi_char16_t *name,
186 unsigned long data_size,
189 DECLARE_CALL(set_variable);
191 set_xen_guest_handle(call.u.set_variable.name, name);
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);
199 return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
202 static efi_status_t xen_efi_query_variable_info(u32 attr,
204 u64 *remaining_space,
205 u64 *max_variable_size)
208 DECLARE_CALL(query_variable_info);
210 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
211 return EFI_UNSUPPORTED;
213 err = HYPERVISOR_platform_op(&op);
215 return EFI_UNSUPPORTED;
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;
224 static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
227 DECLARE_CALL(get_next_high_monotonic_count);
229 err = HYPERVISOR_platform_op(&op);
231 return EFI_UNSUPPORTED;
238 static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
240 unsigned long sg_list)
242 DECLARE_CALL(update_capsule);
244 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
245 return EFI_UNSUPPORTED;
247 set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
249 call.u.update_capsule.capsule_count = count;
250 call.u.update_capsule.sg_list = sg_list;
252 return HYPERVISOR_platform_op(&op) ? EFI_UNSUPPORTED : call.status;
255 static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
261 DECLARE_CALL(query_capsule_capabilities);
263 if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
264 return EFI_UNSUPPORTED;
266 set_xen_guest_handle(call.u.query_capsule_capabilities.capsule_header_array,
268 call.u.query_capsule_capabilities.capsule_count = count;
270 err = HYPERVISOR_platform_op(&op);
272 return EFI_UNSUPPORTED;
274 *max_size = call.u.query_capsule_capabilities.max_capsule_size;
275 *reset_type = call.u.query_capsule_capabilities.reset_type;
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,
307 static int __init setup_noefi(char *arg)
312 early_param("noefi", setup_noefi);
315 int efi_set_rtc_mmss(unsigned long nowtime)
317 int real_seconds, real_minutes;
322 status = efi.get_time(&eft, &cap);
323 if (status != EFI_SUCCESS) {
324 pr_err("Oops: efitime: can't read time!\n");
328 real_seconds = nowtime % 60;
329 real_minutes = nowtime / 60;
330 if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
333 eft.minute = real_minutes;
334 eft.second = real_seconds;
336 status = efi.set_time(&eft);
337 if (status != EFI_SUCCESS) {
338 pr_err("Oops: efitime: can't write time!\n");
344 unsigned long efi_get_time(void)
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();
356 return mktime(eft.year, eft.month, eft.day, eft.hour,
357 eft.minute, eft.second);
360 void __init efi_probe(void)
362 static struct xen_platform_op __initdata op = {
363 .cmd = XENPF_firmware_info,
365 .type = XEN_FW_EFI_INFO,
366 .index = XEN_FW_EFI_CONFIG_TABLE
370 if (HYPERVISOR_platform_op(&op) == 0)
374 void __init efi_reserve_boot_services(void) { }
376 static int __init efi_config_init(u64 tables, unsigned int nr_tables)
378 void *config_tables, *tablep;
379 unsigned int i, sz = sizeof(efi_config_table_t);
382 * Let's see what config tables the firmware passed to us.
384 config_tables = early_ioremap(tables, nr_tables * sz);
385 if (config_tables == NULL) {
386 pr_err("Could not map Configuration table!\n");
390 tablep = config_tables;
392 for (i = 0; i < nr_tables; i++) {
396 guid = ((efi_config_table_t *)tablep)->guid;
397 table = ((efi_config_table_t *)tablep)->table;
398 if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
400 pr_cont(" MPS=0x%lx ", table);
401 } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
403 pr_cont(" ACPI 2.0=0x%lx ", table);
404 } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
406 pr_cont(" ACPI=0x%lx ", table);
407 } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
409 pr_cont(" SMBIOS=0x%lx ", table);
410 } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
412 pr_cont(" HCDP=0x%lx ", table);
413 } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
415 pr_cont(" UGA=0x%lx ", table);
420 early_iounmap(config_tables, nr_tables * sz);
424 void __init efi_init(void)
426 efi_char16_t c16[100];
427 char vendor[ARRAY_SIZE(c16)] = "unknown";
429 struct xen_platform_op op;
430 union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
432 op.cmd = XENPF_firmware_info;
433 op.u.firmware_info.type = XEN_FW_EFI_INFO;
436 * Show what we know for posterity
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);
443 for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
447 pr_err("Could not get the firmware vendor!\n");
449 op.u.firmware_info.index = XEN_FW_EFI_VERSION;
450 ret = HYPERVISOR_platform_op(&op);
452 pr_info("EFI v%u.%.02u by %s\n",
454 info->version & 0xffff, vendor);
456 pr_err("Could not get EFI revision!\n");
458 op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
459 ret = HYPERVISOR_platform_op(&op);
461 efi.runtime_version = info->version;
463 pr_warn("Could not get runtime services revision.\n");
465 op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
466 if (HYPERVISOR_platform_op(&op))
468 if (efi_config_init(info->cfg.addr, info->cfg.nent)) {
473 x86_platform.get_wallclock = efi_get_time;
474 x86_platform.set_wallclock = efi_set_rtc_mmss;
477 void __init efi_enter_virtual_mode(void) { }
479 static struct platform_device rtc_efi_dev = {
484 static int __init rtc_init(void)
486 if (efi_enabled && platform_device_register(&rtc_efi_dev) < 0)
487 pr_err("unable to register rtc device...\n");
489 /* not necessarily an error */
492 arch_initcall(rtc_init);
495 * Convenience functions to obtain memory types and attributes
497 u32 efi_mem_type(unsigned long phys_addr)
499 struct xen_platform_op op;
500 union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
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;
507 return HYPERVISOR_platform_op(&op) ? 0 : info->mem.type;
510 u64 efi_mem_attributes(unsigned long phys_addr)
512 struct xen_platform_op op;
513 union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
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;
520 return HYPERVISOR_platform_op(&op) ? 0 : info->mem.attr;