diff options
| -rw-r--r-- | arch/x86/xen/enlighten.c | 15 | ||||
| -rw-r--r-- | drivers/xen/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/xen/Makefile | 3 | ||||
| -rw-r--r-- | drivers/xen/efi.c | 368 | ||||
| -rw-r--r-- | include/xen/xen-ops.h | 11 |
5 files changed, 401 insertions, 0 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index f17b29210ac4..bc89647f0325 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
| 33 | #include <linux/memblock.h> | 33 | #include <linux/memblock.h> |
| 34 | #include <linux/edd.h> | 34 | #include <linux/edd.h> |
| 35 | #include <linux/efi.h> | ||
| 35 | 36 | ||
| 36 | #include <xen/xen.h> | 37 | #include <xen/xen.h> |
| 37 | #include <xen/events.h> | 38 | #include <xen/events.h> |
| @@ -1520,6 +1521,7 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
| 1520 | { | 1521 | { |
| 1521 | struct physdev_set_iopl set_iopl; | 1522 | struct physdev_set_iopl set_iopl; |
| 1522 | int rc; | 1523 | int rc; |
| 1524 | efi_system_table_t *efi_systab_xen; | ||
| 1523 | 1525 | ||
| 1524 | if (!xen_start_info) | 1526 | if (!xen_start_info) |
| 1525 | return; | 1527 | return; |
| @@ -1715,6 +1717,19 @@ asmlinkage __visible void __init xen_start_kernel(void) | |||
| 1715 | 1717 | ||
| 1716 | xen_setup_runstate_info(0); | 1718 | xen_setup_runstate_info(0); |
| 1717 | 1719 | ||
| 1720 | efi_systab_xen = xen_efi_probe(); | ||
| 1721 | |||
| 1722 | if (efi_systab_xen) { | ||
| 1723 | strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen", | ||
| 1724 | sizeof(boot_params.efi_info.efi_loader_signature)); | ||
| 1725 | boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen); | ||
| 1726 | boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32); | ||
| 1727 | |||
| 1728 | set_bit(EFI_BOOT, &efi.flags); | ||
| 1729 | set_bit(EFI_PARAVIRT, &efi.flags); | ||
| 1730 | set_bit(EFI_64BIT, &efi.flags); | ||
| 1731 | } | ||
| 1732 | |||
| 1718 | /* Start the world */ | 1733 | /* Start the world */ |
| 1719 | #ifdef CONFIG_X86_32 | 1734 | #ifdef CONFIG_X86_32 |
| 1720 | i386_start_kernel(); | 1735 | i386_start_kernel(); |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 38fb36e1c592..8bc01838daf9 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
| @@ -240,4 +240,8 @@ config XEN_MCE_LOG | |||
| 240 | config XEN_HAVE_PVMMU | 240 | config XEN_HAVE_PVMMU |
| 241 | bool | 241 | bool |
| 242 | 242 | ||
| 243 | config XEN_EFI | ||
| 244 | def_bool y | ||
| 245 | depends on X86_64 && EFI | ||
| 246 | |||
| 243 | endmenu | 247 | endmenu |
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 45e00afa7f2d..84044b554e33 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
| @@ -9,6 +9,8 @@ obj-y += xenbus/ | |||
| 9 | nostackp := $(call cc-option, -fno-stack-protector) | 9 | nostackp := $(call cc-option, -fno-stack-protector) |
| 10 | CFLAGS_features.o := $(nostackp) | 10 | CFLAGS_features.o := $(nostackp) |
| 11 | 11 | ||
| 12 | CFLAGS_efi.o += -fshort-wchar | ||
| 13 | |||
| 12 | dom0-$(CONFIG_PCI) += pci.o | 14 | dom0-$(CONFIG_PCI) += pci.o |
| 13 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o | 15 | dom0-$(CONFIG_USB_SUPPORT) += dbgp.o |
| 14 | dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y) | 16 | dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y) |
| @@ -33,6 +35,7 @@ obj-$(CONFIG_XEN_STUB) += xen-stub.o | |||
| 33 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o | 35 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o |
| 34 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o | 36 | obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o |
| 35 | obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o | 37 | obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o |
| 38 | obj-$(CONFIG_XEN_EFI) += efi.o | ||
| 36 | xen-evtchn-y := evtchn.o | 39 | xen-evtchn-y := evtchn.o |
| 37 | xen-gntdev-y := gntdev.o | 40 | xen-gntdev-y := gntdev.o |
| 38 | xen-gntalloc-y := gntalloc.o | 41 | xen-gntalloc-y := gntalloc.o |
diff --git a/drivers/xen/efi.c b/drivers/xen/efi.c new file mode 100644 index 000000000000..31f618a49661 --- /dev/null +++ b/drivers/xen/efi.c | |||
| @@ -0,0 +1,368 @@ | |||
| 1 | /* | ||
| 2 | * EFI support for Xen. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1999 VA Linux Systems | ||
| 5 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | ||
| 6 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | ||
| 7 | * David Mosberger-Tang <davidm@hpl.hp.com> | ||
| 8 | * Stephane Eranian <eranian@hpl.hp.com> | ||
| 9 | * Copyright (C) 2005-2008 Intel Co. | ||
| 10 | * Fenghua Yu <fenghua.yu@intel.com> | ||
| 11 | * Bibo Mao <bibo.mao@intel.com> | ||
| 12 | * Chandramouli Narayanan <mouli@linux.intel.com> | ||
| 13 | * Huang Ying <ying.huang@intel.com> | ||
| 14 | * Copyright (C) 2011 Novell Co. | ||
| 15 | * Jan Beulich <JBeulich@suse.com> | ||
| 16 | * Copyright (C) 2011-2012 Oracle Co. | ||
| 17 | * Liang Tang <liang.tang@oracle.com> | ||
| 18 | * Copyright (c) 2014 Oracle Co., Daniel Kiper | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/bug.h> | ||
| 22 | #include <linux/efi.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/string.h> | ||
| 25 | |||
| 26 | #include <xen/interface/xen.h> | ||
| 27 | #include <xen/interface/platform.h> | ||
| 28 | #include <xen/xen.h> | ||
| 29 | |||
| 30 | #include <asm/xen/hypercall.h> | ||
| 31 | |||
| 32 | #define INIT_EFI_OP(name) \ | ||
| 33 | {.cmd = XENPF_efi_runtime_call, \ | ||
| 34 | .u.efi_runtime_call.function = XEN_EFI_##name, \ | ||
| 35 | .u.efi_runtime_call.misc = 0} | ||
| 36 | |||
| 37 | #define efi_data(op) (op.u.efi_runtime_call) | ||
| 38 | |||
| 39 | static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
| 40 | { | ||
| 41 | struct xen_platform_op op = INIT_EFI_OP(get_time); | ||
| 42 | |||
| 43 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 44 | return EFI_UNSUPPORTED; | ||
| 45 | |||
| 46 | if (tm) { | ||
| 47 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_time.time)); | ||
| 48 | memcpy(tm, &efi_data(op).u.get_time.time, sizeof(*tm)); | ||
| 49 | } | ||
| 50 | |||
| 51 | if (tc) { | ||
| 52 | tc->resolution = efi_data(op).u.get_time.resolution; | ||
| 53 | tc->accuracy = efi_data(op).u.get_time.accuracy; | ||
| 54 | tc->sets_to_zero = !!(efi_data(op).misc & | ||
| 55 | XEN_EFI_GET_TIME_SET_CLEARS_NS); | ||
| 56 | } | ||
| 57 | |||
| 58 | return efi_data(op).status; | ||
| 59 | } | ||
| 60 | |||
| 61 | static efi_status_t xen_efi_set_time(efi_time_t *tm) | ||
| 62 | { | ||
| 63 | struct xen_platform_op op = INIT_EFI_OP(set_time); | ||
| 64 | |||
| 65 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_time)); | ||
| 66 | memcpy(&efi_data(op).u.set_time, tm, sizeof(*tm)); | ||
| 67 | |||
| 68 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 69 | return EFI_UNSUPPORTED; | ||
| 70 | |||
| 71 | return efi_data(op).status; | ||
| 72 | } | ||
| 73 | |||
| 74 | static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled, | ||
| 75 | efi_bool_t *pending, | ||
| 76 | efi_time_t *tm) | ||
| 77 | { | ||
| 78 | struct xen_platform_op op = INIT_EFI_OP(get_wakeup_time); | ||
| 79 | |||
| 80 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 81 | return EFI_UNSUPPORTED; | ||
| 82 | |||
| 83 | if (tm) { | ||
| 84 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.get_wakeup_time)); | ||
| 85 | memcpy(tm, &efi_data(op).u.get_wakeup_time, sizeof(*tm)); | ||
| 86 | } | ||
| 87 | |||
| 88 | if (enabled) | ||
| 89 | *enabled = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED); | ||
| 90 | |||
| 91 | if (pending) | ||
| 92 | *pending = !!(efi_data(op).misc & XEN_EFI_GET_WAKEUP_TIME_PENDING); | ||
| 93 | |||
| 94 | return efi_data(op).status; | ||
| 95 | } | ||
| 96 | |||
| 97 | static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | ||
| 98 | { | ||
| 99 | struct xen_platform_op op = INIT_EFI_OP(set_wakeup_time); | ||
| 100 | |||
| 101 | BUILD_BUG_ON(sizeof(*tm) != sizeof(efi_data(op).u.set_wakeup_time)); | ||
| 102 | if (enabled) | ||
| 103 | efi_data(op).misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE; | ||
| 104 | if (tm) | ||
| 105 | memcpy(&efi_data(op).u.set_wakeup_time, tm, sizeof(*tm)); | ||
| 106 | else | ||
| 107 | efi_data(op).misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY; | ||
| 108 | |||
| 109 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 110 | return EFI_UNSUPPORTED; | ||
| 111 | |||
| 112 | return efi_data(op).status; | ||
| 113 | } | ||
| 114 | |||
| 115 | static efi_status_t xen_efi_get_variable(efi_char16_t *name, | ||
| 116 | efi_guid_t *vendor, | ||
| 117 | u32 *attr, | ||
| 118 | unsigned long *data_size, | ||
| 119 | void *data) | ||
| 120 | { | ||
| 121 | struct xen_platform_op op = INIT_EFI_OP(get_variable); | ||
| 122 | |||
| 123 | set_xen_guest_handle(efi_data(op).u.get_variable.name, name); | ||
| 124 | BUILD_BUG_ON(sizeof(*vendor) != | ||
| 125 | sizeof(efi_data(op).u.get_variable.vendor_guid)); | ||
| 126 | memcpy(&efi_data(op).u.get_variable.vendor_guid, vendor, sizeof(*vendor)); | ||
| 127 | efi_data(op).u.get_variable.size = *data_size; | ||
| 128 | set_xen_guest_handle(efi_data(op).u.get_variable.data, data); | ||
| 129 | |||
| 130 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 131 | return EFI_UNSUPPORTED; | ||
| 132 | |||
| 133 | *data_size = efi_data(op).u.get_variable.size; | ||
| 134 | if (attr) | ||
| 135 | *attr = efi_data(op).misc; | ||
| 136 | |||
| 137 | return efi_data(op).status; | ||
| 138 | } | ||
| 139 | |||
| 140 | static efi_status_t xen_efi_get_next_variable(unsigned long *name_size, | ||
| 141 | efi_char16_t *name, | ||
| 142 | efi_guid_t *vendor) | ||
| 143 | { | ||
| 144 | struct xen_platform_op op = INIT_EFI_OP(get_next_variable_name); | ||
| 145 | |||
| 146 | efi_data(op).u.get_next_variable_name.size = *name_size; | ||
| 147 | set_xen_guest_handle(efi_data(op).u.get_next_variable_name.name, name); | ||
| 148 | BUILD_BUG_ON(sizeof(*vendor) != | ||
| 149 | sizeof(efi_data(op).u.get_next_variable_name.vendor_guid)); | ||
| 150 | memcpy(&efi_data(op).u.get_next_variable_name.vendor_guid, vendor, | ||
| 151 | sizeof(*vendor)); | ||
| 152 | |||
| 153 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 154 | return EFI_UNSUPPORTED; | ||
| 155 | |||
| 156 | *name_size = efi_data(op).u.get_next_variable_name.size; | ||
| 157 | memcpy(vendor, &efi_data(op).u.get_next_variable_name.vendor_guid, | ||
| 158 | sizeof(*vendor)); | ||
| 159 | |||
| 160 | return efi_data(op).status; | ||
| 161 | } | ||
| 162 | |||
| 163 | static efi_status_t xen_efi_set_variable(efi_char16_t *name, | ||
| 164 | efi_guid_t *vendor, | ||
| 165 | u32 attr, | ||
| 166 | unsigned long data_size, | ||
| 167 | void *data) | ||
| 168 | { | ||
| 169 | struct xen_platform_op op = INIT_EFI_OP(set_variable); | ||
| 170 | |||
| 171 | set_xen_guest_handle(efi_data(op).u.set_variable.name, name); | ||
| 172 | efi_data(op).misc = attr; | ||
| 173 | BUILD_BUG_ON(sizeof(*vendor) != | ||
| 174 | sizeof(efi_data(op).u.set_variable.vendor_guid)); | ||
| 175 | memcpy(&efi_data(op).u.set_variable.vendor_guid, vendor, sizeof(*vendor)); | ||
| 176 | efi_data(op).u.set_variable.size = data_size; | ||
| 177 | set_xen_guest_handle(efi_data(op).u.set_variable.data, data); | ||
| 178 | |||
| 179 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 180 | return EFI_UNSUPPORTED; | ||
| 181 | |||
| 182 | return efi_data(op).status; | ||
| 183 | } | ||
| 184 | |||
| 185 | static efi_status_t xen_efi_query_variable_info(u32 attr, | ||
| 186 | u64 *storage_space, | ||
| 187 | u64 *remaining_space, | ||
| 188 | u64 *max_variable_size) | ||
| 189 | { | ||
| 190 | struct xen_platform_op op = INIT_EFI_OP(query_variable_info); | ||
| 191 | |||
| 192 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 193 | return EFI_UNSUPPORTED; | ||
| 194 | |||
| 195 | efi_data(op).u.query_variable_info.attr = attr; | ||
| 196 | |||
| 197 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 198 | return EFI_UNSUPPORTED; | ||
| 199 | |||
| 200 | *storage_space = efi_data(op).u.query_variable_info.max_store_size; | ||
| 201 | *remaining_space = efi_data(op).u.query_variable_info.remain_store_size; | ||
| 202 | *max_variable_size = efi_data(op).u.query_variable_info.max_size; | ||
| 203 | |||
| 204 | return efi_data(op).status; | ||
| 205 | } | ||
| 206 | |||
| 207 | static efi_status_t xen_efi_get_next_high_mono_count(u32 *count) | ||
| 208 | { | ||
| 209 | struct xen_platform_op op = INIT_EFI_OP(get_next_high_monotonic_count); | ||
| 210 | |||
| 211 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 212 | return EFI_UNSUPPORTED; | ||
| 213 | |||
| 214 | *count = efi_data(op).misc; | ||
| 215 | |||
| 216 | return efi_data(op).status; | ||
| 217 | } | ||
| 218 | |||
| 219 | static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules, | ||
| 220 | unsigned long count, | ||
| 221 | unsigned long sg_list) | ||
| 222 | { | ||
| 223 | struct xen_platform_op op = INIT_EFI_OP(update_capsule); | ||
| 224 | |||
| 225 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 226 | return EFI_UNSUPPORTED; | ||
| 227 | |||
| 228 | set_xen_guest_handle(efi_data(op).u.update_capsule.capsule_header_array, | ||
| 229 | capsules); | ||
| 230 | efi_data(op).u.update_capsule.capsule_count = count; | ||
| 231 | efi_data(op).u.update_capsule.sg_list = sg_list; | ||
| 232 | |||
| 233 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 234 | return EFI_UNSUPPORTED; | ||
| 235 | |||
| 236 | return efi_data(op).status; | ||
| 237 | } | ||
| 238 | |||
| 239 | static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules, | ||
| 240 | unsigned long count, | ||
| 241 | u64 *max_size, | ||
| 242 | int *reset_type) | ||
| 243 | { | ||
| 244 | struct xen_platform_op op = INIT_EFI_OP(query_capsule_capabilities); | ||
| 245 | |||
| 246 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 247 | return EFI_UNSUPPORTED; | ||
| 248 | |||
| 249 | set_xen_guest_handle(efi_data(op).u.query_capsule_capabilities.capsule_header_array, | ||
| 250 | capsules); | ||
| 251 | efi_data(op).u.query_capsule_capabilities.capsule_count = count; | ||
| 252 | |||
| 253 | if (HYPERVISOR_dom0_op(&op) < 0) | ||
| 254 | return EFI_UNSUPPORTED; | ||
| 255 | |||
| 256 | *max_size = efi_data(op).u.query_capsule_capabilities.max_capsule_size; | ||
| 257 | *reset_type = efi_data(op).u.query_capsule_capabilities.reset_type; | ||
| 258 | |||
| 259 | return efi_data(op).status; | ||
| 260 | } | ||
| 261 | |||
| 262 | static efi_char16_t vendor[100] __initdata; | ||
| 263 | |||
| 264 | static efi_system_table_t efi_systab_xen __initdata = { | ||
| 265 | .hdr = { | ||
| 266 | .signature = EFI_SYSTEM_TABLE_SIGNATURE, | ||
| 267 | .revision = 0, /* Initialized later. */ | ||
| 268 | .headersize = 0, /* Ignored by Linux Kernel. */ | ||
| 269 | .crc32 = 0, /* Ignored by Linux Kernel. */ | ||
| 270 | .reserved = 0 | ||
| 271 | }, | ||
| 272 | .fw_vendor = EFI_INVALID_TABLE_ADDR, /* Initialized later. */ | ||
| 273 | .fw_revision = 0, /* Initialized later. */ | ||
| 274 | .con_in_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 275 | .con_in = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 276 | .con_out_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 277 | .con_out = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 278 | .stderr_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 279 | .stderr = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ | ||
| 280 | .runtime = (efi_runtime_services_t *)EFI_INVALID_TABLE_ADDR, | ||
| 281 | /* Not used under Xen. */ | ||
| 282 | .boottime = (efi_boot_services_t *)EFI_INVALID_TABLE_ADDR, | ||
| 283 | /* Not used under Xen. */ | ||
| 284 | .nr_tables = 0, /* Initialized later. */ | ||
| 285 | .tables = EFI_INVALID_TABLE_ADDR /* Initialized later. */ | ||
| 286 | }; | ||
| 287 | |||
| 288 | static const struct efi efi_xen __initconst = { | ||
| 289 | .systab = NULL, /* Initialized later. */ | ||
| 290 | .runtime_version = 0, /* Initialized later. */ | ||
| 291 | .mps = EFI_INVALID_TABLE_ADDR, | ||
| 292 | .acpi = EFI_INVALID_TABLE_ADDR, | ||
| 293 | .acpi20 = EFI_INVALID_TABLE_ADDR, | ||
| 294 | .smbios = EFI_INVALID_TABLE_ADDR, | ||
| 295 | .sal_systab = EFI_INVALID_TABLE_ADDR, | ||
| 296 | .boot_info = EFI_INVALID_TABLE_ADDR, | ||
| 297 | .hcdp = EFI_INVALID_TABLE_ADDR, | ||
| 298 | .uga = EFI_INVALID_TABLE_ADDR, | ||
| 299 | .uv_systab = EFI_INVALID_TABLE_ADDR, | ||
| 300 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | ||
| 301 | .runtime = EFI_INVALID_TABLE_ADDR, | ||
| 302 | .config_table = EFI_INVALID_TABLE_ADDR, | ||
| 303 | .get_time = xen_efi_get_time, | ||
| 304 | .set_time = xen_efi_set_time, | ||
| 305 | .get_wakeup_time = xen_efi_get_wakeup_time, | ||
| 306 | .set_wakeup_time = xen_efi_set_wakeup_time, | ||
| 307 | .get_variable = xen_efi_get_variable, | ||
| 308 | .get_next_variable = xen_efi_get_next_variable, | ||
| 309 | .set_variable = xen_efi_set_variable, | ||
| 310 | .query_variable_info = xen_efi_query_variable_info, | ||
| 311 | .update_capsule = xen_efi_update_capsule, | ||
| 312 | .query_capsule_caps = xen_efi_query_capsule_caps, | ||
| 313 | .get_next_high_mono_count = xen_efi_get_next_high_mono_count, | ||
| 314 | .reset_system = NULL, /* Functionality provided by Xen. */ | ||
| 315 | .set_virtual_address_map = NULL, /* Not used under Xen. */ | ||
| 316 | .memmap = NULL, /* Not used under Xen. */ | ||
| 317 | .flags = 0 /* Initialized later. */ | ||
| 318 | }; | ||
| 319 | |||
| 320 | efi_system_table_t __init *xen_efi_probe(void) | ||
| 321 | { | ||
| 322 | struct xen_platform_op op = { | ||
| 323 | .cmd = XENPF_firmware_info, | ||
| 324 | .u.firmware_info = { | ||
| 325 | .type = XEN_FW_EFI_INFO, | ||
| 326 | .index = XEN_FW_EFI_CONFIG_TABLE | ||
| 327 | } | ||
| 328 | }; | ||
| 329 | union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; | ||
| 330 | |||
| 331 | if (!xen_initial_domain() || HYPERVISOR_dom0_op(&op) < 0) | ||
| 332 | return NULL; | ||
| 333 | |||
| 334 | /* Here we know that Xen runs on EFI platform. */ | ||
| 335 | |||
| 336 | efi = efi_xen; | ||
| 337 | |||
| 338 | efi_systab_xen.tables = info->cfg.addr; | ||
| 339 | efi_systab_xen.nr_tables = info->cfg.nent; | ||
| 340 | |||
| 341 | op.cmd = XENPF_firmware_info; | ||
| 342 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
| 343 | op.u.firmware_info.index = XEN_FW_EFI_VENDOR; | ||
| 344 | info->vendor.bufsz = sizeof(vendor); | ||
| 345 | set_xen_guest_handle(info->vendor.name, vendor); | ||
| 346 | |||
| 347 | if (HYPERVISOR_dom0_op(&op) == 0) { | ||
| 348 | efi_systab_xen.fw_vendor = __pa_symbol(vendor); | ||
| 349 | efi_systab_xen.fw_revision = info->vendor.revision; | ||
| 350 | } else | ||
| 351 | efi_systab_xen.fw_vendor = __pa_symbol(L"UNKNOWN"); | ||
| 352 | |||
| 353 | op.cmd = XENPF_firmware_info; | ||
| 354 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
| 355 | op.u.firmware_info.index = XEN_FW_EFI_VERSION; | ||
| 356 | |||
| 357 | if (HYPERVISOR_dom0_op(&op) == 0) | ||
| 358 | efi_systab_xen.hdr.revision = info->version; | ||
| 359 | |||
| 360 | op.cmd = XENPF_firmware_info; | ||
| 361 | op.u.firmware_info.type = XEN_FW_EFI_INFO; | ||
| 362 | op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION; | ||
| 363 | |||
| 364 | if (HYPERVISOR_dom0_op(&op) == 0) | ||
| 365 | efi.runtime_version = info->version; | ||
| 366 | |||
| 367 | return &efi_systab_xen; | ||
| 368 | } | ||
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 0b3149ed7eaa..771bbba27ccb 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/percpu.h> | 4 | #include <linux/percpu.h> |
| 5 | #include <linux/notifier.h> | 5 | #include <linux/notifier.h> |
| 6 | #include <linux/efi.h> | ||
| 6 | #include <asm/xen/interface.h> | 7 | #include <asm/xen/interface.h> |
| 7 | 8 | ||
| 8 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | 9 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); |
| @@ -35,4 +36,14 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | |||
| 35 | int numpgs, struct page **pages); | 36 | int numpgs, struct page **pages); |
| 36 | 37 | ||
| 37 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); | 38 | bool xen_running_on_version_or_later(unsigned int major, unsigned int minor); |
| 39 | |||
| 40 | #ifdef CONFIG_XEN_EFI | ||
| 41 | extern efi_system_table_t *xen_efi_probe(void); | ||
| 42 | #else | ||
| 43 | static efi_system_table_t __init *xen_efi_probe(void) | ||
| 44 | { | ||
| 45 | return NULL; | ||
| 46 | } | ||
| 47 | #endif | ||
| 48 | |||
| 38 | #endif /* INCLUDE_XEN_OPS_H */ | 49 | #endif /* INCLUDE_XEN_OPS_H */ |
