All of lore.kernel.org
 help / color / mirror / Atom feed
* [REBASE] xen: patches (against Linux kernel) for supporting efi
@ 2013-05-23 10:04 Eric Shelton
  2013-05-23 10:19 ` Jan Beulich
  2013-05-24 14:24 ` Konrad Rzeszutek Wilk
  0 siblings, 2 replies; 7+ messages in thread
From: Eric Shelton @ 2013-05-23 10:04 UTC (permalink / raw)
  To: xen-devel, Tang Liang, Konrad Rzeszutek Wilk, Jan Beulich

[-- Attachment #1: Type: text/plain, Size: 31974 bytes --]

Please find attached and below a rebased version of the patches to the
Linux kernel needed to get a Linux-based dom0 to come up under
xen.efi, which were last posted by Tang on Feb 23, 2012.  The provided
patch was made against Linux 3.9.3, but should either apply against or
be easily backported to older kernel versions (for example, only 2
hunks fail against 3.7.10).  I tried to take into account Jan's
comments offered for the Feb 8, 2012 ver 1 of the patches.

Using the provided patch, I am able to successfully do a native EFI
boot using xen.efi on a 2012 MacBook Air, with refind kicking off the
boot.  I have noticed no difference from a non-Xen boot; KDE and wifi
work normally, for example.  A non-Xen boot of the patched 3.9.3
kernel works fine as well.  The below xen.cfg was used:

video=gfx-1366x768x32
options=debug console=vga loglvl=all guest_loglvl=all e820-verbose=1
iommu=debug,verbose console_timestamps=true font=8x16
kernel=393test.efi ro root=/dev/sda3 debug ignore_loglevel
earlyprintk=xen i8042.noaux

In order of importance, three items are outstanding:
1) The attached code only works on 64-bit systems, due to setting the
EFI_64BIT in xen_efi_probe().  It looks like a new hypercall is needed
or an existing hypercall needs to be added to check whether the EFI
BIOS is 32- or 64-bit (see comment in code).
2) efivars is not tested
3) XEN_FW_EFI_PCI_ROM hypercall was added in the interim, but is unused in dom0

I apologize for the attached patch not being split up into 5 pieces as
previously presented, and for not observing the formalities for patch
presentation (which is why I also include an attachment).  I hope that
someone with a little more experience and time can address the above
items (particularly #1) and get it incorporated into the kernel this
time around.

Signed-off-by: Eric Shelton <eshelton@pobox.com>


On February 23, 2012, Tang Liang wrote:
> Hi
>
> The following patches introduce and implement efi support in dom0.
> The efi memory is owned by Xen and efi run-time service can not be called
> directly in dom0, so a new efi driver is needed by Xen efi.
> These patches are based on v3.3.0-rc2+.
>
> Descriptions for these patches:
>
> The efi public functions are changed to function pointers in efi_init_funcs
> struct. They act as efi generic functions as default.
> As a benefit from this change, we can register xen efi init func.
>
> In order to add xen efi video support, it is required to add xen-efi's
> new video type(XEN_VGATYPE_EFI_LFB) case handler in the function xen_init_vga
> and set the video type to VIDEO_TYPE_EFI to enable efi video mode.
>
> I have tested this patch on Dell Opti 790.
>
> Xen efi boot support is added by Jan Beulich, more detail information can be
> gotten from the url:
> http://wiki.xen.org/xenwiki/XenParavirtOps, search "efi" in the page.
>
> The example of config file for efi boot:
> kernel=vmlinuz-3.3.0-rc2+ root=xx ro console=tty0
> ramdisk=initramfs-3.3.0-rc2+.img
> video=gfx-x.0
>
> The detailed test which i have done:
> First, Check efifb driver work well or not and check the kernel messesge ro
> see the follow info:
> [    0.576705] efifb: probing for efifb
> [    0.577357] efifb: framebuffer at 0xd0000000, mapped to 0xffffc90005800000, using 3752k, total 65472k
> [    0.577360] efifb: mode is 800x600x32, linelength=3200, pages=1
> [    0.577362] efifb: scrolling: redraw
> [    0.577364] efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0
>
> Second, Check efi systab and variable is work well or not.
> cat the information in /sys/firmware/efi to check the efi systab and variable
> is right or not.
>
> Third, Run Linux firmware testing tools which is downloaded from this Url.
> http://linuxfirmwarekit.org/download.php
>
> Jan Beulich (1):
>       EFI: add efi driver for Xen efi
>
> Tang Liang (4):
>       EFI: Provide registration for efi_init.. etc efi public      function
>       EFI: seperate get efi table info code to single function
>       Xen efi: Add xen efi enabled detect
>       Xen vga: add the xen efi video mode support
>
> arch/x86/platform/efi/Makefile   |    2 +-
> arch/x86/platform/efi/efi-xen.c  |  460 ++++++++++++++++++++++++++++++++++++++
> arch/x86/platform/efi/efi.c      |   63 +++++-
> arch/x86/xen/enlighten.c         |    3 +
> arch/x86/xen/vga.c               |    7 +
> include/linux/efi.h              |   14 +-
> include/xen/interface/platform.h |  122 ++++++++++
> include/xen/interface/xen.h      |    1 +
> 8 files changed, 665 insertions(+), 7 deletions(-)
>
> Thanks
> Liang.

=========== PATCH BELOW ===========

diff -urN a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
--- a/arch/x86/platform/efi/efi.c 2013-05-22 20:37:13.432000000 -0400
+++ b/arch/x86/platform/efi/efi.c 2013-05-23 02:23:03.384000000 -0400
@@ -95,6 +95,29 @@
 }
 EXPORT_SYMBOL(efi_enabled);

+static void efi_init_generic(void);
+static void efi_late_init_generic(void);
+
+static void efi_enter_virtual_mode_generic(void);
+static u32 efi_mem_type_generic(unsigned long phys_addr);
+static u64 efi_mem_attributes_generic(unsigned long phys_addr);
+static void efi_reserve_boot_services_generic(void);
+static void efi_free_boot_services_generic(void);
+static int efi_memblock_x86_reserve_range_generic(void);
+
+static const struct efi_init_funcs __initconst efi_generic_funcs = {
+ .init       = efi_init_generic,
+ .late_init       = efi_late_init_generic,
+ .reserve_boot_services = efi_reserve_boot_services_generic,
+ .free_boot_services    = efi_free_boot_services_generic,
+ .enter_virtual_mode    = efi_enter_virtual_mode_generic,
+ .mem_type       = efi_mem_type_generic,
+ .mem_attributes       = efi_mem_attributes_generic,
+ .x86_reserve_range     = efi_memblock_x86_reserve_range_generic
+};
+
+const struct efi_init_funcs *efi_override_funcs =  &efi_generic_funcs;
+
 static bool __initdata disable_runtime = false;
 static int __init setup_noefi(char *arg)
 {
@@ -443,7 +466,7 @@
  sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }

-int __init efi_memblock_x86_reserve_range(void)
+int __init efi_memblock_x86_reserve_range_generic(void)
 {
  unsigned long pmap;

@@ -475,6 +498,8 @@
  void *p;
  int i;

+ if (memmap.map == NULL) return;
+
  for (p = memmap.map, i = 0;
      p < memmap.map_end;
      p += memmap.desc_size, i++) {
@@ -488,7 +513,7 @@
 }
 #endif  /*  EFI_DEBUG  */

-void __init efi_reserve_boot_services(void)
+static void efi_reserve_boot_services_generic(void)
 {
  void *p;

@@ -529,7 +554,7 @@
  }
 }

-void __init efi_free_boot_services(void)
+void __init efi_free_boot_services_generic(void)
 {
  void *p;

@@ -644,7 +669,7 @@
  return 0;
 }

-static int __init efi_config_init(u64 tables, int nr_tables)
+int __init efi_config_init(u64 tables, int nr_tables, struct efi *efi_t)
 {
  void *config_tables, *tablep;
  int i, sz;
@@ -665,7 +690,7 @@

  tablep = config_tables;
  pr_info("");
- for (i = 0; i < efi.systab->nr_tables; i++) {
+ for (i = 0; i < nr_tables; i++) {
  efi_guid_t guid;
  unsigned long table;

@@ -679,7 +704,7 @@
  pr_cont("\n");
  pr_err("Table located above 4GB, disabling EFI.\n");
  early_iounmap(config_tables,
-      efi.systab->nr_tables * sz);
+      nr_tables * sz);
  return -EINVAL;
  }
 #endif
@@ -688,33 +713,33 @@
  table = ((efi_config_table_32_t *)tablep)->table;
  }
  if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
- efi.mps = table;
+ efi_t->mps = table;
  pr_cont(" MPS=0x%lx ", table);
  } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
- efi.acpi20 = table;
+ efi_t->acpi20 = table;
  pr_cont(" ACPI 2.0=0x%lx ", table);
  } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
- efi.acpi = table;
+ efi_t->acpi = table;
  pr_cont(" ACPI=0x%lx ", table);
  } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
- efi.smbios = table;
+ efi_t->smbios = table;
  pr_cont(" SMBIOS=0x%lx ", table);
 #ifdef CONFIG_X86_UV
  } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) {
- efi.uv_systab = table;
+ efi_t->uv_systab = table;
  pr_cont(" UVsystab=0x%lx ", table);
 #endif
  } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
- efi.hcdp = table;
+ efi_t->hcdp = table;
  pr_cont(" HCDP=0x%lx ", table);
  } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
- efi.uga = table;
+ efi_t->uga = table;
  pr_cont(" UGA=0x%lx ", table);
  }
  tablep += sz;
  }
  pr_cont("\n");
- early_iounmap(config_tables, efi.systab->nr_tables * sz);
+ early_iounmap(config_tables, nr_tables * sz);
  return 0;
 }

@@ -770,7 +795,7 @@
  return 0;
 }

-void __init efi_init(void)
+static void efi_init_generic(void)
 {
  efi_char16_t *c16;
  char vendor[100] = "unknown";
@@ -830,7 +855,7 @@
  efi.systab->hdr.revision >> 16,
  efi.systab->hdr.revision & 0xffff, vendor);

- if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
+ if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, &efi))
  return;

  set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
@@ -865,9 +890,11 @@
 #endif
 }

-void __init efi_late_init(void)
+void __init efi_late_init_generic(void)
 {
+#ifdef CONFIG_ACPI_BGRT
  efi_bgrt_init();
+#endif
 }

 void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
@@ -947,7 +974,7 @@
  * This enables the runtime services to be called without having to
  * thunk back into physical mode for every invocation.
  */
-void __init efi_enter_virtual_mode(void)
+static void efi_enter_virtual_mode_generic(void)
 {
  efi_memory_desc_t *md, *prev_md = NULL;
  efi_status_t status;
@@ -1080,7 +1107,7 @@
 /*
  * Convenience functions to obtain memory types and attributes
  */
-u32 efi_mem_type(unsigned long phys_addr)
+static u32 efi_mem_type_generic(unsigned long phys_addr)
 {
  efi_memory_desc_t *md;
  void *p;
@@ -1098,7 +1125,7 @@
  return 0;
 }

-u64 efi_mem_attributes(unsigned long phys_addr)
+static u64 efi_mem_attributes_generic(unsigned long phys_addr)
 {
  efi_memory_desc_t *md;
  void *p;
@@ -1113,6 +1140,68 @@
  return 0;
 }

+void efi_init_function_register(const struct efi_init_funcs *funcs)
+{
+ efi_override_funcs = funcs;
+}
+
+void __init efi_init(void)
+{
+ if (efi_override_funcs->init)
+ {
+ efi_override_funcs->init();
+ }
+ else
+ {
+ memmap.map = NULL;  /* Xen case */
+ }
+}
+
+void __init efi_late_init(void)
+{
+ if (efi_override_funcs->late_init)
+ efi_override_funcs->late_init();
+}
+
+void __init efi_reserve_boot_services(void)
+{
+ if (efi_override_funcs->reserve_boot_services)
+ efi_override_funcs->reserve_boot_services();
+}
+
+void __init efi_free_boot_services(void)
+{
+ if (efi_override_funcs->free_boot_services)
+ efi_override_funcs->free_boot_services();
+}
+
+void __init efi_enter_virtual_mode(void)
+{
+ if (efi_override_funcs->enter_virtual_mode)
+ efi_override_funcs->enter_virtual_mode();
+}
+
+int __init efi_memblock_x86_reserve_range(void)
+{
+ if (efi_override_funcs->x86_reserve_range)
+ return efi_override_funcs->x86_reserve_range();
+ return 0;
+}
+
+u32 efi_mem_type(unsigned long phys_addr)
+{
+ if (efi_override_funcs->mem_type)
+ return efi_override_funcs->mem_type(phys_addr);
+ return EFI_INVALID_TYPE;
+}
+
+u64 efi_mem_attributes(unsigned long phys_addr)
+{
+ if (efi_override_funcs->mem_attributes)
+ return efi_override_funcs->mem_attributes(phys_addr);
+ return EFI_INVALID_ATTRIBUTE;
+}
+
 /*
  * Some firmware has serious problems when using more than 50% of the EFI
  * variable store, i.e. it triggers bugs that can brick machines. Ensure that
diff -urN a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
--- a/arch/x86/platform/efi/Makefile 2013-05-22 20:39:05.260000000 -0400
+++ b/arch/x86/platform/efi/Makefile 2013-05-23 02:04:00.048000000 -0400
@@ -1,2 +1,5 @@
 obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
+ifdef CONFIG_XEN
+obj-$(CONFIG_EFI) += xen.o
+endif
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
diff -urN a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
--- a/arch/x86/platform/efi/xen.c 1969-12-31 19:00:00.000000000 -0500
+++ b/arch/x86/platform/efi/xen.c 2013-05-23 02:28:22.340000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * Xen EFI (Extensible Firmware Interface) support functions
+ * Based on related efforts in SLE and SUSE trees
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2005-2008 Intel Co.
+ * Fenghua Yu <fenghua.yu@intel.com>
+ * Bibo Mao <bibo.mao@intel.com>
+ * Chandramouli Narayanan <mouli@linux.intel.com>
+ * Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2011 Novell Co.
+ * Jan Beulic <JBeulich@suse.com>
+ * Copyright (C) 2011-2012 Oracle Co.
+ * Liang Tang <liang.tang@oracle.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/efi.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+
+#include <asm/setup.h>
+#include <asm/efi.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/x86_init.h>
+
+#include <xen/interface/platform.h>
+#include <asm/xen/hypercall.h>
+
+#define PFX "EFI: "
+
+#define call (op.u.efi_runtime_call)
+#define DECLARE_CALL(what) \
+ struct xen_platform_op op; \
+ op.cmd = XENPF_efi_runtime_call; \
+ call.function = XEN_EFI_##what; \
+ call.misc = 0
+
+static void register_xen_efi_function(void);
+
+static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+ int err;
+ DECLARE_CALL(get_time);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ if (tm) {
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
+ memcpy(tm, &call.u.get_time.time, sizeof(*tm));
+ }
+
+ if (tc) {
+ tc->resolution = call.u.get_time.resolution;
+ tc->accuracy = call.u.get_time.accuracy;
+ tc->sets_to_zero = !!(call.misc &
+      XEN_EFI_GET_TIME_SET_CLEARS_NS);
+ }
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_time(efi_time_t *tm)
+{
+ DECLARE_CALL(set_time);
+
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
+ memcpy(&call.u.set_time, tm, sizeof(*tm));
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
+    efi_bool_t *pending,
+    efi_time_t *tm)
+{
+ int err;
+ DECLARE_CALL(get_wakeup_time);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ if (tm) {
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
+ memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
+ }
+
+ if (enabled)
+ *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
+
+ if (pending)
+ *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+{
+ DECLARE_CALL(set_wakeup_time);
+
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
+ if (enabled)
+ call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
+ if (tm)
+ memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
+ else
+ call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 *attr,
+ unsigned long *data_size,
+ void *data)
+{
+ int err;
+ DECLARE_CALL(get_variable);
+
+ set_xen_guest_handle(call.u.get_variable.name, name);
+ BUILD_BUG_ON(sizeof(*vendor) !=
+     sizeof(call.u.get_variable.vendor_guid));
+ memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
+ call.u.get_variable.size = *data_size;
+ set_xen_guest_handle(call.u.get_variable.data, data);
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *data_size = call.u.get_variable.size;
+ *attr = call.misc; /* misc in struction is U32 variable*/
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
+      efi_char16_t *name,
+      efi_guid_t *vendor)
+{
+ int err;
+ DECLARE_CALL(get_next_variable_name);
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+ call.u.get_next_variable_name.size = *name_size;
+ set_xen_guest_handle(call.u.get_next_variable_name.name, name);
+ BUILD_BUG_ON(sizeof(*vendor) !=
+     sizeof(call.u.get_next_variable_name.vendor_guid));
+ memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
+       sizeof(*vendor));
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *name_size = call.u.get_next_variable_name.size;
+ memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
+       sizeof(*vendor));
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 attr,
+ unsigned long data_size,
+ void *data)
+{
+ DECLARE_CALL(set_variable);
+
+ set_xen_guest_handle(call.u.set_variable.name, name);
+ call.misc = attr;
+ BUILD_BUG_ON(sizeof(*vendor) !=
+     sizeof(call.u.set_variable.vendor_guid));
+ memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
+ call.u.set_variable.size = data_size;
+ set_xen_guest_handle(call.u.set_variable.data, data);
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_variable_info(u32 attr,
+ u64 *storage_space,
+ u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ int err;
+ DECLARE_CALL(query_variable_info);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *storage_space = call.u.query_variable_info.max_store_size;
+ *remaining_space = call.u.query_variable_info.remain_store_size;
+ *max_variable_size = call.u.query_variable_info.max_size;
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
+{
+ int err;
+ DECLARE_CALL(get_next_high_monotonic_count);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *count = call.misc;
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
+   unsigned long count,
+   unsigned long sg_list)
+{
+ DECLARE_CALL(update_capsule);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
+     capsules);
+ call.u.update_capsule.capsule_count = count;
+ call.u.update_capsule.sg_list = sg_list;
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+       unsigned long count,
+       u64 *max_size,
+       int *reset_type)
+{
+ int err;
+ DECLARE_CALL(query_capsule_capabilities);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ set_xen_guest_handle(call.u.query_capsule_capabilities.
+ capsule_header_array, capsules);
+ call.u.query_capsule_capabilities.capsule_count = count;
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *max_size = call.u.query_capsule_capabilities.max_capsule_size;
+ *reset_type = call.u.query_capsule_capabilities.reset_type;
+
+ return call.status;
+}
+
+#undef DECLARE_CALL
+#undef call
+
+static const struct efi __initconst efi_xen = {
+ .mps                      = EFI_INVALID_TABLE_ADDR,
+ .acpi                     = EFI_INVALID_TABLE_ADDR,
+ .acpi20                   = EFI_INVALID_TABLE_ADDR,
+ .smbios                   = EFI_INVALID_TABLE_ADDR,
+ .sal_systab               = EFI_INVALID_TABLE_ADDR,
+ .boot_info                = EFI_INVALID_TABLE_ADDR,
+ .hcdp                     = EFI_INVALID_TABLE_ADDR,
+ .uga                      = EFI_INVALID_TABLE_ADDR,
+ .uv_systab                = EFI_INVALID_TABLE_ADDR,
+ .get_time                 = xen_efi_get_time,
+ .set_time                 = xen_efi_set_time,
+ .get_wakeup_time          = xen_efi_get_wakeup_time,
+ .set_wakeup_time          = xen_efi_set_wakeup_time,
+ .get_variable             = xen_efi_get_variable,
+ .get_next_variable        = xen_efi_get_next_variable,
+ .set_variable             = xen_efi_set_variable,
+ .get_next_high_mono_count = xen_efi_get_next_high_mono_count,
+ .query_variable_info      = xen_efi_query_variable_info,
+ .update_capsule           = xen_efi_update_capsule,
+ .query_capsule_caps       = xen_efi_query_capsule_caps,
+};
+
+void xen_efi_probe(void)
+{
+ static struct xen_platform_op __initdata op = {
+ .cmd = XENPF_firmware_info,
+ .u.firmware_info = {
+ .type = XEN_FW_EFI_INFO,
+ .index = XEN_FW_EFI_CONFIG_TABLE
+ }
+ };
+
+ if (HYPERVISOR_dom0_op(&op) == 0) {
+ /*efi_enabled = 1;*/
+ set_bit(EFI_BOOT, &x86_efi_facility);
+ /* this should be set based on whether the EFI loader
+ * signature contains "EL64" (see arch/x86/kernel/setup.c).
+ * Looks like a new hypercall will be needed for this */
+ set_bit(EFI_64BIT, &x86_efi_facility);
+
+ register_xen_efi_function();
+ }
+}
+
+
+static void __init efi_init_xen(void)
+{
+ efi_char16_t c16[100];
+ char vendor[ARRAY_SIZE(c16)] = "unknown";
+ int ret, i;
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ efi = efi_xen;
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+
+ /*
+ * Show what we know for posterity
+ */
+ op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
+ info->vendor.bufsz = sizeof(c16);
+ set_xen_guest_handle(info->vendor.name, c16);
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret) {
+ for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+ vendor[i] = c16[i];
+ vendor[i] = '\0';
+ } else
+ pr_err("Could not get the firmware vendor!\n");
+
+ op.u.firmware_info.index = XEN_FW_EFI_VERSION;
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret)
+ pr_info("EFI-xen v%u.%.02u by %s\n",
+       info->version >> 16,
+       info->version & 0xffff, vendor);
+ else
+ pr_err("Could not get EFI revision!\n");
+
+ op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret)
+ efi.runtime_version = info->version;
+ else
+ pr_warn(PFX "Could not get runtime services revision.\n");
+ set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
+
+ /*
+ * Let's see what config tables the firmware passed to us.
+ */
+ op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
+ if (HYPERVISOR_dom0_op(&op))
+ BUG();
+
+ if (efi_config_init(info->cfg.addr, info->cfg.nent, &efi))
+ panic("Could not init EFI Configuration Tables!\n");
+ set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
+
+ /* the EFI memory info is digested by the hypervisor and
+ * supplied to dom0 via E820 entries */
+ set_bit(EFI_MEMMAP, &x86_efi_facility);
+
+ set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
+
+ /* NOTE: efi.c only does this for CONFIG_X86_32 */
+ x86_platform.get_wallclock = efi_get_time;
+ x86_platform.set_wallclock = efi_set_rtc_mmss;
+}
+
+/*
+ * Convenience functions to obtain memory types and attributes
+ */
+static u32 efi_mem_type_xen(unsigned long phys_addr)
+{
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+ op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+ info->mem.addr = phys_addr;
+ info->mem.size = 0;
+ return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
+}
+
+static u64 efi_mem_attributes_xen(unsigned long phys_addr)
+{
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+ op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+ info->mem.addr = phys_addr;
+ info->mem.size = 0;
+ return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
+}
+
+static const struct __initconst efi_init_funcs xen_efi_funcs = {
+ .init        = efi_init_xen,
+ .late_init = NULL,
+ .reserve_boot_services  = NULL,
+ .free_boot_services     = NULL,
+ .enter_virtual_mode     = NULL,
+ .mem_type        = efi_mem_type_xen,
+ .mem_attributes        = efi_mem_attributes_xen,
+ .x86_reserve_range = NULL
+};
+
+static void register_xen_efi_function(void)
+{
+ efi_init_function_register(&xen_efi_funcs);
+}
diff -urN a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
--- a/arch/x86/xen/enlighten.c 2013-05-22 20:36:48.608000000 -0400
+++ b/arch/x86/xen/enlighten.c 2013-05-22 20:44:15.784000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/efi.h>

 #include <xen/xen.h>
 #include <xen/events.h>
@@ -1532,6 +1533,8 @@

  xen_setup_runstate_info(0);

+ if (xen_initial_domain())
+ xen_efi_probe();
  /* Start the world */
 #ifdef CONFIG_X86_32
  i386_start_kernel();
diff -urN a/include/linux/efi.h b/include/linux/efi.h
--- a/include/linux/efi.h 2013-05-22 20:36:14.820000000 -0400
+++ b/include/linux/efi.h 2013-05-23 02:22:12.544000000 -0400
@@ -84,7 +84,10 @@
 #define EFI_PAL_CODE 13
 #define EFI_MAX_MEMORY_TYPE 14

+#define EFI_INVALID_TYPE 0xffffffff
+
 /* Attribute values: */
+#define EFI_INVALID_ATTRIBUTE ((u64)0x0000000000000000ULL) /* invalid
attribute*/
 #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
 #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
 #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
@@ -554,6 +557,17 @@
  efi_set_virtual_address_map_t *set_virtual_address_map;
 } efi;

+struct efi_init_funcs {
+ void (*init)(void);
+ void (*late_init)(void);
+ void (*reserve_boot_services)(void);
+ void (*free_boot_services)(void);
+ void (*enter_virtual_mode)(void);
+ u32 (*mem_type)(unsigned long phys_addr);
+ u64 (*mem_attributes)(unsigned long phys_addr);
+ int (*x86_reserve_range)(void);
+};
+
 static inline int
 efi_guidcmp (efi_guid_t left, efi_guid_t right)
 {
@@ -591,13 +605,16 @@
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
 extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int __init efi_uart_console_only (void);
+extern int efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
  struct resource *data_resource, struct resource *bss_resource);
 extern unsigned long efi_get_time(void);
 extern int efi_set_rtc_mmss(unsigned long nowtime);
 extern void efi_reserve_boot_services(void);
 extern struct efi_memory_map memmap;
+extern void efi_init_function_register(const struct efi_init_funcs *funcs);
+extern int efi_config_init(u64 tables, int nr_tables, struct efi *efi_t);
+extern void xen_efi_probe(void);

 /**
  * efi_range_is_wc - check the WC bit on an address range
@@ -621,7 +638,7 @@
 }

 #ifdef CONFIG_EFI_PCDP
-extern int __init efi_setup_pcdp_console(char *);
+extern int efi_setup_pcdp_console(char *);
 #endif

 /*
diff -urN a/include/xen/interface/platform.h b/include/xen/interface/platform.h
--- a/include/xen/interface/platform.h 2013-05-22 20:35:50.280000000 -0400
+++ b/include/xen/interface/platform.h 2013-05-22 20:43:17.068000000 -0400
@@ -108,10 +108,111 @@
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);

+#define XENPF_efi_runtime_call    49
+#define XEN_EFI_get_time                      1
+#define XEN_EFI_set_time                      2
+#define XEN_EFI_get_wakeup_time               3
+#define XEN_EFI_set_wakeup_time               4
+#define XEN_EFI_get_next_high_monotonic_count 5
+#define XEN_EFI_get_variable                  6
+#define XEN_EFI_set_variable                  7
+#define XEN_EFI_get_next_variable_name        8
+#define XEN_EFI_query_variable_info           9
+#define XEN_EFI_query_capsule_capabilities   10
+#define XEN_EFI_update_capsule               11
+
+struct xenpf_efi_runtime_call {
+ uint32_t function;
+    /*
+     * This field is generally used for per sub-function flags (defined
+     * below), except for the XEN_EFI_get_next_high_monotonic_count case,
+     * where it holds the single returned value.
+     */
+ uint32_t misc;
+ unsigned long status;
+ union {
+#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
+ struct {
+ struct xenpf_efi_time {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t min;
+ uint8_t sec;
+ uint32_t ns;
+ int16_t tz;
+ uint8_t daylight;
+ } time;
+ uint32_t resolution;
+ uint32_t accuracy;
+ } get_time;
+
+ struct xenpf_efi_time set_time;
+
+#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
+#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
+ struct xenpf_efi_time get_wakeup_time;
+
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE      0x00000001
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
+ struct xenpf_efi_time set_wakeup_time;
+
+#define XEN_EFI_VARIABLE_NON_VOLATILE       0x00000001
+#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define XEN_EFI_VARIABLE_RUNTIME_ACCESS     0x00000004
+ struct {
+ GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+ unsigned long size;
+ GUEST_HANDLE(void) data;
+ struct xenpf_efi_guid {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+ } vendor_guid;
+ } get_variable, set_variable;
+
+ struct {
+ unsigned long size;
+ GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+ struct xenpf_efi_guid vendor_guid;
+ } get_next_variable_name;
+
+ struct {
+ uint32_t attr;
+ uint64_t max_store_size;
+ uint64_t remain_store_size;
+ uint64_t max_size;
+ } query_variable_info;
+
+ struct {
+ GUEST_HANDLE(void) capsule_header_array;
+ unsigned long capsule_count;
+ uint64_t max_capsule_size;
+ unsigned int reset_type;
+ } query_capsule_capabilities;
+
+ struct {
+ GUEST_HANDLE(void) capsule_header_array;
+ unsigned long capsule_count;
+ uint64_t sg_list; /* machine address */
+ } update_capsule;
+ } u;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
+
 #define XENPF_firmware_info       50
 #define XEN_FW_DISK_INFO          1 /* from int 13 AH=08/41/48 */
 #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
 #define XEN_FW_VBEDDC_INFO        3 /* from int 10 AX=4f15 */
+#define XEN_FW_EFI_INFO           4 /* from EFI */
+#define  XEN_FW_EFI_VERSION        0
+#define  XEN_FW_EFI_CONFIG_TABLE   1
+#define  XEN_FW_EFI_VENDOR         2
+#define  XEN_FW_EFI_MEM_INFO       3
+#define  XEN_FW_EFI_RT_VERSION     4
+#define  XEN_FW_EFI_PCI_ROM        5
 #define XEN_FW_KBD_SHIFT_FLAGS    5 /* Int16, Fn02: Get keyboard
shift flags. */
 struct xenpf_firmware_info {
  /* IN variables. */
@@ -143,6 +244,36 @@
  /* must refer to 128-byte buffer */
  GUEST_HANDLE(uchar) edid;
  } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
+ union xenpf_efi_info {
+ uint32_t version;
+ struct {
+ uint64_t addr;   /* EFI_CONFIGURATION_TABLE */
+ uint32_t nent;
+ } cfg;
+ struct {
+ uint32_t revision;
+ uint32_t bufsz;  /* input, in bytes */
+ GUEST_HANDLE(void) name;
+ /* UCS-2/UTF-16 string */
+ } vendor;
+ struct {
+ uint64_t addr;
+ uint64_t size;
+ uint64_t attr;
+ uint32_t type;
+ } mem;
+ struct {
+ /* IN variables */
+ uint16_t segment;
+ uint8_t bus;
+ uint8_t devfn;
+ uint16_t vendor;
+ uint16_t devid;
+ /* OUT variables */
+ uint64_t address;
+ xen_ulong_t size;
+ } pci_rom;
+ } efi_info; /* XEN_FW_EFI_INFO */

  uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
  } u;
@@ -361,6 +492,7 @@
  struct xenpf_read_memtype      read_memtype;
  struct xenpf_microcode_update  microcode;
  struct xenpf_platform_quirk    platform_quirk;
+ struct xenpf_efi_runtime_call  efi_runtime_call;
  struct xenpf_firmware_info     firmware_info;
  struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
  struct xenpf_change_freq       change_freq;
diff -urN a/init/main.c b/init/main.c
--- a/init/main.c 2013-05-22 20:35:17.768000000 -0400
+++ b/init/main.c 2013-05-22 20:43:51.468000000 -0400
@@ -634,10 +634,12 @@
  acpi_early_init(); /* before LAPIC and SMP init */
  sfi_init_late();

+#ifdef CONFIG_X86
  if (efi_enabled(EFI_RUNTIME_SERVICES)) {
  efi_late_init();
  efi_free_boot_services();
  }
+#endif

  ftrace_init();

[-- Attachment #2: xen-efi-rebase-3.9.3.patch --]
[-- Type: application/octet-stream, Size: 27871 bytes --]

diff -urN a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
--- a/arch/x86/platform/efi/efi.c	2013-05-22 20:37:13.432000000 -0400
+++ b/arch/x86/platform/efi/efi.c	2013-05-23 02:23:03.384000000 -0400
@@ -95,6 +95,29 @@
 }
 EXPORT_SYMBOL(efi_enabled);
 
+static void efi_init_generic(void);
+static void efi_late_init_generic(void);
+
+static void efi_enter_virtual_mode_generic(void);
+static u32 efi_mem_type_generic(unsigned long phys_addr);
+static u64 efi_mem_attributes_generic(unsigned long phys_addr);
+static void efi_reserve_boot_services_generic(void);
+static void efi_free_boot_services_generic(void);
+static int efi_memblock_x86_reserve_range_generic(void);
+
+static const struct efi_init_funcs __initconst efi_generic_funcs = {
+	.init		       = efi_init_generic,
+	.late_init	       = efi_late_init_generic,
+	.reserve_boot_services = efi_reserve_boot_services_generic,
+	.free_boot_services    = efi_free_boot_services_generic,
+	.enter_virtual_mode    = efi_enter_virtual_mode_generic,
+	.mem_type	       = efi_mem_type_generic,
+	.mem_attributes	       = efi_mem_attributes_generic,
+	.x86_reserve_range     = efi_memblock_x86_reserve_range_generic
+};
+
+const struct efi_init_funcs *efi_override_funcs =  &efi_generic_funcs;
+
 static bool __initdata disable_runtime = false;
 static int __init setup_noefi(char *arg)
 {
@@ -443,7 +466,7 @@
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
-int __init efi_memblock_x86_reserve_range(void)
+int __init efi_memblock_x86_reserve_range_generic(void)
 {
 	unsigned long pmap;
 
@@ -475,6 +498,8 @@
 	void *p;
 	int i;
 
+	if (memmap.map == NULL) return;
+
 	for (p = memmap.map, i = 0;
 	     p < memmap.map_end;
 	     p += memmap.desc_size, i++) {
@@ -488,7 +513,7 @@
 }
 #endif  /*  EFI_DEBUG  */
 
-void __init efi_reserve_boot_services(void)
+static void efi_reserve_boot_services_generic(void)
 {
 	void *p;
 
@@ -529,7 +554,7 @@
 	}
 }
 
-void __init efi_free_boot_services(void)
+void __init efi_free_boot_services_generic(void)
 {
 	void *p;
 
@@ -644,7 +669,7 @@
 	return 0;
 }
 
-static int __init efi_config_init(u64 tables, int nr_tables)
+int __init efi_config_init(u64 tables, int nr_tables, struct efi *efi_t)
 {
 	void *config_tables, *tablep;
 	int i, sz;
@@ -665,7 +690,7 @@
 
 	tablep = config_tables;
 	pr_info("");
-	for (i = 0; i < efi.systab->nr_tables; i++) {
+	for (i = 0; i < nr_tables; i++) {
 		efi_guid_t guid;
 		unsigned long table;
 
@@ -679,7 +704,7 @@
 				pr_cont("\n");
 				pr_err("Table located above 4GB, disabling EFI.\n");
 				early_iounmap(config_tables,
-					      efi.systab->nr_tables * sz);
+					      nr_tables * sz);
 				return -EINVAL;
 			}
 #endif
@@ -688,33 +713,33 @@
 			table = ((efi_config_table_32_t *)tablep)->table;
 		}
 		if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
-			efi.mps = table;
+			efi_t->mps = table;
 			pr_cont(" MPS=0x%lx ", table);
 		} else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
-			efi.acpi20 = table;
+			efi_t->acpi20 = table;
 			pr_cont(" ACPI 2.0=0x%lx ", table);
 		} else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
-			efi.acpi = table;
+			efi_t->acpi = table;
 			pr_cont(" ACPI=0x%lx ", table);
 		} else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
-			efi.smbios = table;
+			efi_t->smbios = table;
 			pr_cont(" SMBIOS=0x%lx ", table);
 #ifdef CONFIG_X86_UV
 		} else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) {
-			efi.uv_systab = table;
+			efi_t->uv_systab = table;
 			pr_cont(" UVsystab=0x%lx ", table);
 #endif
 		} else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
-			efi.hcdp = table;
+			efi_t->hcdp = table;
 			pr_cont(" HCDP=0x%lx ", table);
 		} else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
-			efi.uga = table;
+			efi_t->uga = table;
 			pr_cont(" UGA=0x%lx ", table);
 		}
 		tablep += sz;
 	}
 	pr_cont("\n");
-	early_iounmap(config_tables, efi.systab->nr_tables * sz);
+	early_iounmap(config_tables, nr_tables * sz);
 	return 0;
 }
 
@@ -770,7 +795,7 @@
 	return 0;
 }
 
-void __init efi_init(void)
+static void efi_init_generic(void)
 {
 	efi_char16_t *c16;
 	char vendor[100] = "unknown";
@@ -830,7 +855,7 @@
 		efi.systab->hdr.revision >> 16,
 		efi.systab->hdr.revision & 0xffff, vendor);
 
-	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
+	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, &efi))
 		return;
 
 	set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
@@ -865,9 +890,11 @@
 #endif
 }
 
-void __init efi_late_init(void)
+void __init efi_late_init_generic(void)
 {
+#ifdef CONFIG_ACPI_BGRT
 	efi_bgrt_init();
+#endif
 }
 
 void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
@@ -947,7 +974,7 @@
  * This enables the runtime services to be called without having to
  * thunk back into physical mode for every invocation.
  */
-void __init efi_enter_virtual_mode(void)
+static void efi_enter_virtual_mode_generic(void)
 {
 	efi_memory_desc_t *md, *prev_md = NULL;
 	efi_status_t status;
@@ -1080,7 +1107,7 @@
 /*
  * Convenience functions to obtain memory types and attributes
  */
-u32 efi_mem_type(unsigned long phys_addr)
+static u32 efi_mem_type_generic(unsigned long phys_addr)
 {
 	efi_memory_desc_t *md;
 	void *p;
@@ -1098,7 +1125,7 @@
 	return 0;
 }
 
-u64 efi_mem_attributes(unsigned long phys_addr)
+static u64 efi_mem_attributes_generic(unsigned long phys_addr)
 {
 	efi_memory_desc_t *md;
 	void *p;
@@ -1113,6 +1140,68 @@
 	return 0;
 }
 
+void efi_init_function_register(const struct efi_init_funcs *funcs)
+{
+	efi_override_funcs = funcs;
+}
+
+void __init efi_init(void)
+{
+	if (efi_override_funcs->init)
+	{
+		efi_override_funcs->init();
+	}
+	else
+	{
+		memmap.map = NULL;  /* Xen case */
+	}
+}
+
+void __init efi_late_init(void)
+{
+	if (efi_override_funcs->late_init)
+		efi_override_funcs->late_init();
+}
+
+void __init efi_reserve_boot_services(void)
+{
+	if (efi_override_funcs->reserve_boot_services)
+		efi_override_funcs->reserve_boot_services();
+}
+
+void __init efi_free_boot_services(void)
+{
+	if (efi_override_funcs->free_boot_services)
+		efi_override_funcs->free_boot_services();
+}
+
+void __init efi_enter_virtual_mode(void)
+{
+	if (efi_override_funcs->enter_virtual_mode)
+		efi_override_funcs->enter_virtual_mode();
+}
+
+int __init efi_memblock_x86_reserve_range(void)
+{
+	if (efi_override_funcs->x86_reserve_range)
+		return efi_override_funcs->x86_reserve_range();
+	return 0;
+}
+
+u32 efi_mem_type(unsigned long phys_addr)
+{
+	if (efi_override_funcs->mem_type)
+		return efi_override_funcs->mem_type(phys_addr);
+	return EFI_INVALID_TYPE;
+}
+
+u64 efi_mem_attributes(unsigned long phys_addr)
+{
+	if (efi_override_funcs->mem_attributes)
+		return efi_override_funcs->mem_attributes(phys_addr);
+	return EFI_INVALID_ATTRIBUTE;
+}
+
 /*
  * Some firmware has serious problems when using more than 50% of the EFI
  * variable store, i.e. it triggers bugs that can brick machines. Ensure that
diff -urN a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
--- a/arch/x86/platform/efi/Makefile	2013-05-22 20:39:05.260000000 -0400
+++ b/arch/x86/platform/efi/Makefile	2013-05-23 02:04:00.048000000 -0400
@@ -1,2 +1,5 @@
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
+ifdef CONFIG_XEN
+obj-$(CONFIG_EFI)		+= xen.o
+endif
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
diff -urN a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
--- a/arch/x86/platform/efi/xen.c	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/x86/platform/efi/xen.c	2013-05-23 02:28:22.340000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * Xen EFI (Extensible Firmware Interface) support functions
+ * Based on related efforts in SLE and SUSE trees
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *	Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2005-2008 Intel Co.
+ *	Fenghua Yu <fenghua.yu@intel.com>
+ *	Bibo Mao <bibo.mao@intel.com>
+ *	Chandramouli Narayanan <mouli@linux.intel.com>
+ *	Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2011 Novell Co.
+ *	Jan Beulic <JBeulich@suse.com>
+ * Copyright (C) 2011-2012 Oracle Co.
+ *	Liang Tang <liang.tang@oracle.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/efi.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+
+#include <asm/setup.h>
+#include <asm/efi.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/x86_init.h>
+
+#include <xen/interface/platform.h>
+#include <asm/xen/hypercall.h>
+
+#define PFX		"EFI: "
+
+#define call (op.u.efi_runtime_call)
+#define DECLARE_CALL(what) \
+	struct xen_platform_op op; \
+	op.cmd = XENPF_efi_runtime_call; \
+	call.function = XEN_EFI_##what; \
+	call.misc = 0
+
+static void register_xen_efi_function(void);
+
+static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+	int err;
+	DECLARE_CALL(get_time);
+
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	if (tm) {
+		BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
+		memcpy(tm, &call.u.get_time.time, sizeof(*tm));
+	}
+
+	if (tc) {
+		tc->resolution = call.u.get_time.resolution;
+		tc->accuracy = call.u.get_time.accuracy;
+		tc->sets_to_zero = !!(call.misc &
+				      XEN_EFI_GET_TIME_SET_CLEARS_NS);
+	}
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_set_time(efi_time_t *tm)
+{
+	DECLARE_CALL(set_time);
+
+	BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
+	memcpy(&call.u.set_time, tm, sizeof(*tm));
+
+	return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
+					    efi_bool_t *pending,
+					    efi_time_t *tm)
+{
+	int err;
+	DECLARE_CALL(get_wakeup_time);
+
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	if (tm) {
+		BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
+		memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
+	}
+
+	if (enabled)
+		*enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
+
+	if (pending)
+		*pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
+{
+	DECLARE_CALL(set_wakeup_time);
+
+	BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
+	if (enabled)
+		call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
+	if (tm)
+		memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
+	else
+		call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
+
+	return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_variable(efi_char16_t *name,
+					 efi_guid_t *vendor,
+					 u32 *attr,
+					 unsigned long *data_size,
+					 void *data)
+{
+	int err;
+	DECLARE_CALL(get_variable);
+
+	set_xen_guest_handle(call.u.get_variable.name, name);
+	BUILD_BUG_ON(sizeof(*vendor) !=
+		     sizeof(call.u.get_variable.vendor_guid));
+	memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
+	call.u.get_variable.size = *data_size;
+	set_xen_guest_handle(call.u.get_variable.data, data);
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	*data_size = call.u.get_variable.size;
+	*attr = call.misc; /* misc in struction is U32 variable*/
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
+					      efi_char16_t *name,
+					      efi_guid_t *vendor)
+{
+	int err;
+	DECLARE_CALL(get_next_variable_name);
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+	call.u.get_next_variable_name.size = *name_size;
+	set_xen_guest_handle(call.u.get_next_variable_name.name, name);
+	BUILD_BUG_ON(sizeof(*vendor) !=
+		     sizeof(call.u.get_next_variable_name.vendor_guid));
+	memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
+	       sizeof(*vendor));
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	*name_size = call.u.get_next_variable_name.size;
+	memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
+	       sizeof(*vendor));
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_set_variable(efi_char16_t *name,
+					 efi_guid_t *vendor,
+					 u32 attr,
+					 unsigned long data_size,
+					 void *data)
+{
+	DECLARE_CALL(set_variable);
+
+	set_xen_guest_handle(call.u.set_variable.name, name);
+	call.misc = attr;
+	BUILD_BUG_ON(sizeof(*vendor) !=
+		     sizeof(call.u.set_variable.vendor_guid));
+	memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
+	call.u.set_variable.size = data_size;
+	set_xen_guest_handle(call.u.set_variable.data, data);
+
+	return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_variable_info(u32 attr,
+						u64 *storage_space,
+						u64 *remaining_space,
+						u64 *max_variable_size)
+{
+	int err;
+	DECLARE_CALL(query_variable_info);
+
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	*storage_space = call.u.query_variable_info.max_store_size;
+	*remaining_space = call.u.query_variable_info.remain_store_size;
+	*max_variable_size = call.u.query_variable_info.max_size;
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
+{
+	int err;
+	DECLARE_CALL(get_next_high_monotonic_count);
+
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	*count = call.misc;
+
+	return call.status;
+}
+
+static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
+					   unsigned long count,
+					   unsigned long sg_list)
+{
+	DECLARE_CALL(update_capsule);
+
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
+			     capsules);
+	call.u.update_capsule.capsule_count = count;
+	call.u.update_capsule.sg_list = sg_list;
+
+	return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+					       unsigned long count,
+					       u64 *max_size,
+					       int *reset_type)
+{
+	int err;
+	DECLARE_CALL(query_capsule_capabilities);
+
+	if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+		return EFI_UNSUPPORTED;
+
+	set_xen_guest_handle(call.u.query_capsule_capabilities.
+		capsule_header_array, capsules);
+	call.u.query_capsule_capabilities.capsule_count = count;
+
+	err = HYPERVISOR_dom0_op(&op);
+	if (err)
+		return EFI_UNSUPPORTED;
+
+	*max_size = call.u.query_capsule_capabilities.max_capsule_size;
+	*reset_type = call.u.query_capsule_capabilities.reset_type;
+
+	return call.status;
+}
+
+#undef DECLARE_CALL
+#undef call
+
+static const struct efi __initconst efi_xen = {
+	.mps                      = EFI_INVALID_TABLE_ADDR,
+	.acpi                     = EFI_INVALID_TABLE_ADDR,
+	.acpi20                   = EFI_INVALID_TABLE_ADDR,
+	.smbios                   = EFI_INVALID_TABLE_ADDR,
+	.sal_systab               = EFI_INVALID_TABLE_ADDR,
+	.boot_info                = EFI_INVALID_TABLE_ADDR,
+	.hcdp                     = EFI_INVALID_TABLE_ADDR,
+	.uga                      = EFI_INVALID_TABLE_ADDR,
+	.uv_systab                = EFI_INVALID_TABLE_ADDR,
+	.get_time                 = xen_efi_get_time,
+	.set_time                 = xen_efi_set_time,
+	.get_wakeup_time          = xen_efi_get_wakeup_time,
+	.set_wakeup_time          = xen_efi_set_wakeup_time,
+	.get_variable             = xen_efi_get_variable,
+	.get_next_variable        = xen_efi_get_next_variable,
+	.set_variable             = xen_efi_set_variable,
+	.get_next_high_mono_count = xen_efi_get_next_high_mono_count,
+	.query_variable_info      = xen_efi_query_variable_info,
+	.update_capsule           = xen_efi_update_capsule,
+	.query_capsule_caps       = xen_efi_query_capsule_caps,
+};
+
+void xen_efi_probe(void)
+{
+	static struct xen_platform_op __initdata op = {
+		.cmd = XENPF_firmware_info,
+		.u.firmware_info = {
+			.type = XEN_FW_EFI_INFO,
+			.index = XEN_FW_EFI_CONFIG_TABLE
+		}
+	};
+
+	if (HYPERVISOR_dom0_op(&op) == 0) {
+		/*efi_enabled = 1;*/
+		set_bit(EFI_BOOT, &x86_efi_facility);
+		/* this should be set based on whether the EFI loader
+		 * signature contains "EL64" (see arch/x86/kernel/setup.c).
+		 * Looks like a new hypercall will be needed for this */
+		set_bit(EFI_64BIT, &x86_efi_facility);
+
+		register_xen_efi_function();
+	}
+}
+
+
+static void __init efi_init_xen(void)
+{
+	efi_char16_t c16[100];
+	char vendor[ARRAY_SIZE(c16)] = "unknown";
+	int ret, i;
+	struct xen_platform_op op;
+	union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+	efi = efi_xen;
+	op.cmd = XENPF_firmware_info;
+	op.u.firmware_info.type = XEN_FW_EFI_INFO;
+
+	/*
+	 * Show what we know for posterity
+	 */
+	op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
+	info->vendor.bufsz = sizeof(c16);
+	set_xen_guest_handle(info->vendor.name, c16);
+	ret = HYPERVISOR_dom0_op(&op);
+	if (!ret) {
+		for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+			vendor[i] = c16[i];
+		vendor[i] = '\0';
+	} else
+		pr_err("Could not get the firmware vendor!\n");
+
+	op.u.firmware_info.index = XEN_FW_EFI_VERSION;
+	ret = HYPERVISOR_dom0_op(&op);
+	if (!ret)
+		pr_info("EFI-xen v%u.%.02u by %s\n",
+		       info->version >> 16,
+		       info->version & 0xffff, vendor);
+	else
+		pr_err("Could not get EFI revision!\n");
+
+	op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
+	ret = HYPERVISOR_dom0_op(&op);
+	if (!ret)
+		efi.runtime_version = info->version;
+	else
+		pr_warn(PFX "Could not get runtime services revision.\n");
+	set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
+
+	/*
+	 * Let's see what config tables the firmware passed to us.
+	 */
+	op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
+	if (HYPERVISOR_dom0_op(&op))
+		BUG();
+
+	if (efi_config_init(info->cfg.addr, info->cfg.nent, &efi))
+		panic("Could not init EFI Configuration Tables!\n");
+	set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
+
+	/* the EFI memory info is digested by the hypervisor and
+	 * supplied to dom0 via E820 entries */
+	set_bit(EFI_MEMMAP, &x86_efi_facility);
+
+	set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
+
+	/* NOTE: efi.c only does this for CONFIG_X86_32 */
+	x86_platform.get_wallclock = efi_get_time;
+	x86_platform.set_wallclock = efi_set_rtc_mmss;
+}
+
+/*
+ * Convenience functions to obtain memory types and attributes
+ */
+static u32 efi_mem_type_xen(unsigned long phys_addr)
+{
+	struct xen_platform_op op;
+	union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+	op.cmd = XENPF_firmware_info;
+	op.u.firmware_info.type = XEN_FW_EFI_INFO;
+	op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+	info->mem.addr = phys_addr;
+	info->mem.size = 0;
+	return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
+}
+
+static u64 efi_mem_attributes_xen(unsigned long phys_addr)
+{
+	struct xen_platform_op op;
+	union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+	op.cmd = XENPF_firmware_info;
+	op.u.firmware_info.type = XEN_FW_EFI_INFO;
+	op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+	info->mem.addr = phys_addr;
+	info->mem.size = 0;
+	return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
+}
+
+static const struct __initconst efi_init_funcs xen_efi_funcs = {
+	.init		        = efi_init_xen,
+	.late_init		= NULL,
+	.reserve_boot_services  = NULL,
+	.free_boot_services     = NULL,
+	.enter_virtual_mode     = NULL,
+	.mem_type	        = efi_mem_type_xen,
+	.mem_attributes	        = efi_mem_attributes_xen,
+	.x86_reserve_range	= NULL
+};
+
+static void register_xen_efi_function(void)
+{
+	efi_init_function_register(&xen_efi_funcs);
+}
diff -urN a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
--- a/arch/x86/xen/enlighten.c	2013-05-22 20:36:48.608000000 -0400
+++ b/arch/x86/xen/enlighten.c	2013-05-22 20:44:15.784000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/efi.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -1532,6 +1533,8 @@
 
 	xen_setup_runstate_info(0);
 
+	if (xen_initial_domain())
+		xen_efi_probe();
 	/* Start the world */
 #ifdef CONFIG_X86_32
 	i386_start_kernel();
diff -urN a/include/linux/efi.h b/include/linux/efi.h
--- a/include/linux/efi.h	2013-05-22 20:36:14.820000000 -0400
+++ b/include/linux/efi.h	2013-05-23 02:22:12.544000000 -0400
@@ -84,7 +84,10 @@
 #define EFI_PAL_CODE			13
 #define EFI_MAX_MEMORY_TYPE		14
 
+#define EFI_INVALID_TYPE		0xffffffff
+
 /* Attribute values: */
+#define EFI_INVALID_ATTRIBUTE	((u64)0x0000000000000000ULL)	/* invalid attribute*/
 #define EFI_MEMORY_UC		((u64)0x0000000000000001ULL)	/* uncached */
 #define EFI_MEMORY_WC		((u64)0x0000000000000002ULL)	/* write-coalescing */
 #define EFI_MEMORY_WT		((u64)0x0000000000000004ULL)	/* write-through */
@@ -554,6 +557,17 @@
 	efi_set_virtual_address_map_t *set_virtual_address_map;
 } efi;
 
+struct efi_init_funcs {
+	void (*init)(void);
+	void (*late_init)(void);
+	void (*reserve_boot_services)(void);
+	void (*free_boot_services)(void);
+	void (*enter_virtual_mode)(void);
+	u32 (*mem_type)(unsigned long phys_addr);
+	u64 (*mem_attributes)(unsigned long phys_addr);
+	int (*x86_reserve_range)(void);
+};
+
 static inline int
 efi_guidcmp (efi_guid_t left, efi_guid_t right)
 {
@@ -591,13 +605,16 @@
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
 extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
-extern int __init efi_uart_console_only (void);
+extern int efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
 		struct resource *data_resource, struct resource *bss_resource);
 extern unsigned long efi_get_time(void);
 extern int efi_set_rtc_mmss(unsigned long nowtime);
 extern void efi_reserve_boot_services(void);
 extern struct efi_memory_map memmap;
+extern void efi_init_function_register(const struct efi_init_funcs *funcs);
+extern int efi_config_init(u64 tables, int nr_tables, struct efi *efi_t);
+extern void xen_efi_probe(void);
 
 /**
  * efi_range_is_wc - check the WC bit on an address range
@@ -621,7 +638,7 @@
 }
 
 #ifdef CONFIG_EFI_PCDP
-extern int __init efi_setup_pcdp_console(char *);
+extern int efi_setup_pcdp_console(char *);
 #endif
 
 /*
diff -urN a/include/xen/interface/platform.h b/include/xen/interface/platform.h
--- a/include/xen/interface/platform.h	2013-05-22 20:35:50.280000000 -0400
+++ b/include/xen/interface/platform.h	2013-05-22 20:43:17.068000000 -0400
@@ -108,10 +108,111 @@
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);
 
+#define XENPF_efi_runtime_call    49
+#define XEN_EFI_get_time                      1
+#define XEN_EFI_set_time                      2
+#define XEN_EFI_get_wakeup_time               3
+#define XEN_EFI_set_wakeup_time               4
+#define XEN_EFI_get_next_high_monotonic_count 5
+#define XEN_EFI_get_variable                  6
+#define XEN_EFI_set_variable                  7
+#define XEN_EFI_get_next_variable_name        8
+#define XEN_EFI_query_variable_info           9
+#define XEN_EFI_query_capsule_capabilities   10
+#define XEN_EFI_update_capsule               11
+
+struct xenpf_efi_runtime_call {
+	uint32_t function;
+    /*
+     * This field is generally used for per sub-function flags (defined
+     * below), except for the XEN_EFI_get_next_high_monotonic_count case,
+     * where it holds the single returned value.
+     */
+	uint32_t misc;
+	unsigned long status;
+	union {
+#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
+	struct {
+		struct xenpf_efi_time {
+			uint16_t year;
+			uint8_t month;
+			uint8_t day;
+			uint8_t hour;
+			uint8_t min;
+			uint8_t sec;
+			uint32_t ns;
+			int16_t tz;
+			uint8_t daylight;
+		} time;
+		uint32_t resolution;
+		uint32_t accuracy;
+	} get_time;
+
+	struct xenpf_efi_time set_time;
+
+#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
+#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
+	struct xenpf_efi_time get_wakeup_time;
+
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE      0x00000001
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
+	struct xenpf_efi_time set_wakeup_time;
+
+#define XEN_EFI_VARIABLE_NON_VOLATILE       0x00000001
+#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define XEN_EFI_VARIABLE_RUNTIME_ACCESS     0x00000004
+	struct {
+		GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+		unsigned long size;
+		GUEST_HANDLE(void) data;
+		struct xenpf_efi_guid {
+			uint32_t data1;
+			uint16_t data2;
+			uint16_t data3;
+			uint8_t data4[8];
+			} vendor_guid;
+		} get_variable, set_variable;
+
+	struct {
+		unsigned long size;
+		GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+		struct xenpf_efi_guid vendor_guid;
+		} get_next_variable_name;
+
+	struct {
+		uint32_t attr;
+		uint64_t max_store_size;
+		uint64_t remain_store_size;
+		uint64_t max_size;
+		} query_variable_info;
+
+	struct {
+		GUEST_HANDLE(void) capsule_header_array;
+		unsigned long capsule_count;
+		uint64_t max_capsule_size;
+		unsigned int reset_type;
+		} query_capsule_capabilities;
+
+	struct {
+		GUEST_HANDLE(void) capsule_header_array;
+		unsigned long capsule_count;
+		uint64_t sg_list; /* machine address */
+		} update_capsule;
+	} u;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
+
 #define XENPF_firmware_info       50
 #define XEN_FW_DISK_INFO          1 /* from int 13 AH=08/41/48 */
 #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
 #define XEN_FW_VBEDDC_INFO        3 /* from int 10 AX=4f15 */
+#define XEN_FW_EFI_INFO           4 /* from EFI */
+#define  XEN_FW_EFI_VERSION        0
+#define  XEN_FW_EFI_CONFIG_TABLE   1
+#define  XEN_FW_EFI_VENDOR         2
+#define  XEN_FW_EFI_MEM_INFO       3
+#define  XEN_FW_EFI_RT_VERSION     4
+#define  XEN_FW_EFI_PCI_ROM        5
 #define XEN_FW_KBD_SHIFT_FLAGS    5 /* Int16, Fn02: Get keyboard shift flags. */
 struct xenpf_firmware_info {
 	/* IN variables. */
@@ -143,6 +244,36 @@
 			/* must refer to 128-byte buffer */
 			GUEST_HANDLE(uchar) edid;
 		} vbeddc_info; /* XEN_FW_VBEDDC_INFO */
+		union xenpf_efi_info {
+			uint32_t version;
+			struct {
+				uint64_t addr;   /* EFI_CONFIGURATION_TABLE */
+				uint32_t nent;
+			} cfg;
+			struct {
+				uint32_t revision;
+				uint32_t bufsz;  /* input, in bytes */
+				GUEST_HANDLE(void) name;
+				/* UCS-2/UTF-16 string */
+				} vendor;
+			struct {
+				uint64_t addr;
+				uint64_t size;
+				uint64_t attr;
+				uint32_t type;
+				} mem;
+			struct {
+				/* IN variables */
+				uint16_t segment;
+				uint8_t bus;
+				uint8_t devfn;
+				uint16_t vendor;
+				uint16_t devid;
+				/* OUT variables */
+				uint64_t address;
+				xen_ulong_t size;
+				} pci_rom;
+		} efi_info; /* XEN_FW_EFI_INFO */
 
 		uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
 	} u;
@@ -361,6 +492,7 @@
 		struct xenpf_read_memtype      read_memtype;
 		struct xenpf_microcode_update  microcode;
 		struct xenpf_platform_quirk    platform_quirk;
+		struct xenpf_efi_runtime_call  efi_runtime_call;
 		struct xenpf_firmware_info     firmware_info;
 		struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
 		struct xenpf_change_freq       change_freq;
diff -urN a/init/main.c b/init/main.c
--- a/init/main.c	2013-05-22 20:35:17.768000000 -0400
+++ b/init/main.c	2013-05-22 20:43:51.468000000 -0400
@@ -634,10 +634,12 @@
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
+#ifdef CONFIG_X86
 	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
 		efi_late_init();
 		efi_free_boot_services();
 	}
+#endif
 
 	ftrace_init();
 

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 10:04 [REBASE] xen: patches (against Linux kernel) for supporting efi Eric Shelton
@ 2013-05-23 10:19 ` Jan Beulich
  2013-05-23 11:05   ` Eric Shelton
  2013-05-24 14:24 ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 7+ messages in thread
From: Jan Beulich @ 2013-05-23 10:19 UTC (permalink / raw)
  To: Eric Shelton; +Cc: Tang Liang, Konrad Rzeszutek Wilk, xen-devel

>>> On 23.05.13 at 12:04, Eric Shelton <eshelton@pobox.com> wrote:
> 1) The attached code only works on 64-bit systems, due to setting the
> EFI_64BIT in xen_efi_probe().  It looks like a new hypercall is needed
> or an existing hypercall needs to be added to check whether the EFI
> BIOS is 32- or 64-bit (see comment in code).

This is bogus: For one, Xen only works on 64-bit UEFI. And then,
with the actual runtime calls being done by Xen (after translating
arguments as necessary), a 32-bit kernel can call them as much as
a 64-bit one. An obvious benefit of the intermediate hypercall layer.

Jan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 10:19 ` Jan Beulich
@ 2013-05-23 11:05   ` Eric Shelton
  2013-05-23 11:18     ` Jan Beulich
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Shelton @ 2013-05-23 11:05 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Tang Liang, Konrad Rzeszutek Wilk, xen-devel

On Thu, May 23, 2013 at 6:19 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 23.05.13 at 12:04, Eric Shelton <eshelton@pobox.com> wrote:
>> 1) The attached code only works on 64-bit systems, due to setting the
>> EFI_64BIT in xen_efi_probe().  It looks like a new hypercall is needed
>> or an existing hypercall needs to be added to check whether the EFI
>> BIOS is 32- or 64-bit (see comment in code).
>
> This is bogus: For one, Xen only works on 64-bit UEFI. And then,
> with the actual runtime calls being done by Xen (after translating
> arguments as necessary), a 32-bit kernel can call them as much as
> a 64-bit one. An obvious benefit of the intermediate hypercall layer.
>
> Jan
>

This does not appear to be entirely correct, although it appears you
are describing the intended design.  For one, if you look at
efi_config_init() in efi.c, a hypercall is used to obtain the address
of the config table.  However, the table entries have different sizes
(see efi_config_table_64_t and efi_config_table_32_t).  This affects
(1) how much memory is mapped for the config table, and (2) accessing
the table entries at the correct addresses.  Thus, dom0 has to know
whether EFI is 32 or 64 bit for at least this aspect, at least under
how XEN_FW_EFI_CONFIG_TABLE is presently implemented.  However, as
currently implemented, it appears there is a "bogus" hypervisor
interface that overlooks this "obvious" issue.  This might be
corrected by having the hypervisor mediate access to the config table
rather than depending on dom0 to directly map and access the config
table.

Eric

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 11:05   ` Eric Shelton
@ 2013-05-23 11:18     ` Jan Beulich
  2013-05-23 14:11       ` Eric Shelton
  0 siblings, 1 reply; 7+ messages in thread
From: Jan Beulich @ 2013-05-23 11:18 UTC (permalink / raw)
  To: Eric Shelton; +Cc: Tang Liang, Konrad Rzeszutek Wilk, xen-devel

>>> On 23.05.13 at 13:05, Eric Shelton <eshelton@pobox.com> wrote:
> This does not appear to be entirely correct, although it appears you
> are describing the intended design.  For one, if you look at
> efi_config_init() in efi.c, a hypercall is used to obtain the address
> of the config table.  However, the table entries have different sizes
> (see efi_config_table_64_t and efi_config_table_32_t).  This affects
> (1) how much memory is mapped for the config table, and (2) accessing
> the table entries at the correct addresses.  Thus, dom0 has to know
> whether EFI is 32 or 64 bit for at least this aspect, at least under
> how XEN_FW_EFI_CONFIG_TABLE is presently implemented.  However, as
> currently implemented, it appears there is a "bogus" hypervisor
> interface that overlooks this "obvious" issue.  This might be
> corrected by having the hypervisor mediate access to the config table
> rather than depending on dom0 to directly map and access the config
> table.

Dealing with this in the hypervisor is pointless - we don't want to
make a 32-bit clone of the table (the more that there's no
guarantee we wouldn't truncate addresses). Instead, the Dom0
code simply should use efi_config_table_64_t instead of
efi_config_table_t.

Jan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 11:18     ` Jan Beulich
@ 2013-05-23 14:11       ` Eric Shelton
  2013-05-23 14:45         ` Jan Beulich
  0 siblings, 1 reply; 7+ messages in thread
From: Eric Shelton @ 2013-05-23 14:11 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Tang Liang, Konrad Rzeszutek Wilk, xen-devel

On 5/23/13, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 23.05.13 at 13:05, Eric Shelton <eshelton@pobox.com> wrote:
>> This does not appear to be entirely correct, although it appears you
>> are describing the intended design.  For one, if you look at
>> efi_config_init() in efi.c, a hypercall is used to obtain the address
>> of the config table.  However, the table entries have different sizes
>> (see efi_config_table_64_t and efi_config_table_32_t).  This affects
>> (1) how much memory is mapped for the config table, and (2) accessing
>> the table entries at the correct addresses.  Thus, dom0 has to know
>> whether EFI is 32 or 64 bit for at least this aspect, at least under
>> how XEN_FW_EFI_CONFIG_TABLE is presently implemented.  However, as
>> currently implemented, it appears there is a "bogus" hypervisor
>> interface that overlooks this "obvious" issue.  This might be
>> corrected by having the hypervisor mediate access to the config table
>> rather than depending on dom0 to directly map and access the config
>> table.
>
> Dealing with this in the hypervisor is pointless - we don't want to
> make a 32-bit clone of the table (the more that there's no
> guarantee we wouldn't truncate addresses). Instead, the Dom0
> code simply should use efi_config_table_64_t instead of
> efi_config_table_t.
>
> Jan
>

I see, and I should have caught it from your first comment (although
my understanding is that EFI ver 1.xx works in addition to UEFI).  It
sounds like the patch as presented, minus any comments suggesting the
need for determining if there is a 32-bit EFI, is good on this point,
since it always sets the EFI_64BIT bit.

Just curious: why does Xen only work on 64-bit EFI?  Is there an
architectural issue, or is 64-bit x86 so overwhelmingly prevalent that
there are essentially no Xen users running on 32-bit EFI systems?  It
looks like the Linux kernel bothers to support both 32 and 64 bit EFI,
but does not support EFI runtime where there is a 32/64 bit mix of
BIOS & OS (which appears to not be an issue for 64-bit Xen & a 32-bit
dom0).

Eric

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 14:11       ` Eric Shelton
@ 2013-05-23 14:45         ` Jan Beulich
  0 siblings, 0 replies; 7+ messages in thread
From: Jan Beulich @ 2013-05-23 14:45 UTC (permalink / raw)
  To: Eric Shelton; +Cc: Tang Liang, Konrad Rzeszutek Wilk, xen-devel

>>> On 23.05.13 at 16:11, Eric Shelton <eshelton@pobox.com> wrote:
> I see, and I should have caught it from your first comment (although
> my understanding is that EFI ver 1.xx works in addition to UEFI).

Not sure what you're trying to tell me here.

>  It
> sounds like the patch as presented, minus any comments suggesting the
> need for determining if there is a 32-bit EFI, is good on this point,
> since it always sets the EFI_64BIT bit.

Really it should probably set this bit simply cased upon the
CONFIG_64BIT value.

> Just curious: why does Xen only work on 64-bit EFI?  Is there an
> architectural issue, or is 64-bit x86 so overwhelmingly prevalent that
> there are essentially no Xen users running on 32-bit EFI systems?  It
> looks like the Linux kernel bothers to support both 32 and 64 bit EFI,
> but does not support EFI runtime where there is a 32/64 bit mix of
> BIOS & OS (which appears to not be an issue for 64-bit Xen & a 32-bit
> dom0).

First of all, -unstable (which is what will become 4.3) doesn't support
running as 32-bit hypervisor at all anymore.

And then, when 32-bit support was still there, i.e. in 4.2, there was
no support for booting from 32-bit EFI in the code (largely because
at that point it was already clear that any effort to make 32-bit EFI
would be mostly wasted as 32-bit support was going to go away
soon anyway). Plus there was never any demand for booting 32-bit
Xen from EFI according to all I know.

Jan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
  2013-05-23 10:04 [REBASE] xen: patches (against Linux kernel) for supporting efi Eric Shelton
  2013-05-23 10:19 ` Jan Beulich
@ 2013-05-24 14:24 ` Konrad Rzeszutek Wilk
  1 sibling, 0 replies; 7+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-05-24 14:24 UTC (permalink / raw)
  To: Eric Shelton, Daniel Kiper; +Cc: Tang Liang, Jan Beulich, xen-devel

On Thu, May 23, 2013 at 06:04:19AM -0400, Eric Shelton wrote:
> Please find attached and below a rebased version of the patches to the
> Linux kernel needed to get a Linux-based dom0 to come up under
> xen.efi, which were last posted by Tang on Feb 23, 2012.  The provided
> patch was made against Linux 3.9.3, but should either apply against or
> be easily backported to older kernel versions (for example, only 2
> hunks fail against 3.7.10).  I tried to take into account Jan's
> comments offered for the Feb 8, 2012 ver 1 of the patches.

Hey Eric!

> 
> Using the provided patch, I am able to successfully do a native EFI
> boot using xen.efi on a 2012 MacBook Air, with refind kicking off the
> boot.  I have noticed no difference from a non-Xen boot; KDE and wifi
> work normally, for example.  A non-Xen boot of the patched 3.9.3
> kernel works fine as well.  The below xen.cfg was used:
> 
> video=gfx-1366x768x32
> options=debug console=vga loglvl=all guest_loglvl=all e820-verbose=1
> iommu=debug,verbose console_timestamps=true font=8x16
> kernel=393test.efi ro root=/dev/sda3 debug ignore_loglevel
> earlyprintk=xen i8042.noaux

Sweet!
> 
> In order of importance, three items are outstanding:
> 1) The attached code only works on 64-bit systems, due to setting the
> EFI_64BIT in xen_efi_probe().  It looks like a new hypercall is needed
> or an existing hypercall needs to be added to check whether the EFI
> BIOS is 32- or 64-bit (see comment in code).
> 2) efivars is not tested
> 3) XEN_FW_EFI_PCI_ROM hypercall was added in the interim, but is unused in dom0

Right, that is needed for FrameBuffer handover right?

Are MacBook's the only ones that do this?
> 
> I apologize for the attached patch not being split up into 5 pieces as
> previously presented, and for not observing the formalities for patch
> presentation (which is why I also include an attachment).  I hope that
> someone with a little more experience and time can address the above
> items (particularly #1) and get it incorporated into the kernel this
> time around.

Cc-ing Daniel here. He is right now focusing on making Xen working
well with GRUB2-EFI and then focusing on making the Linux kernel EFI
work with Xen properly. This will be a good starting point

> 
> Signed-off-by: Eric Shelton <eshelton@pobox.com>
> 
> 
> On February 23, 2012, Tang Liang wrote:
> > Hi
> >
> > The following patches introduce and implement efi support in dom0.
> > The efi memory is owned by Xen and efi run-time service can not be called
> > directly in dom0, so a new efi driver is needed by Xen efi.
> > These patches are based on v3.3.0-rc2+.
> >
> > Descriptions for these patches:
> >
> > The efi public functions are changed to function pointers in efi_init_funcs
> > struct. They act as efi generic functions as default.
> > As a benefit from this change, we can register xen efi init func.
> >
> > In order to add xen efi video support, it is required to add xen-efi's
> > new video type(XEN_VGATYPE_EFI_LFB) case handler in the function xen_init_vga
> > and set the video type to VIDEO_TYPE_EFI to enable efi video mode.
> >
> > I have tested this patch on Dell Opti 790.
> >
> > Xen efi boot support is added by Jan Beulich, more detail information can be
> > gotten from the url:
> > http://wiki.xen.org/xenwiki/XenParavirtOps, search "efi" in the page.
> >
> > The example of config file for efi boot:
> > kernel=vmlinuz-3.3.0-rc2+ root=xx ro console=tty0
> > ramdisk=initramfs-3.3.0-rc2+.img
> > video=gfx-x.0
> >
> > The detailed test which i have done:
> > First, Check efifb driver work well or not and check the kernel messesge ro
> > see the follow info:
> > [    0.576705] efifb: probing for efifb
> > [    0.577357] efifb: framebuffer at 0xd0000000, mapped to 0xffffc90005800000, using 3752k, total 65472k
> > [    0.577360] efifb: mode is 800x600x32, linelength=3200, pages=1
> > [    0.577362] efifb: scrolling: redraw
> > [    0.577364] efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0
> >
> > Second, Check efi systab and variable is work well or not.
> > cat the information in /sys/firmware/efi to check the efi systab and variable
> > is right or not.
> >
> > Third, Run Linux firmware testing tools which is downloaded from this Url.
> > http://linuxfirmwarekit.org/download.php
> >
> > Jan Beulich (1):
> >       EFI: add efi driver for Xen efi
> >
> > Tang Liang (4):
> >       EFI: Provide registration for efi_init.. etc efi public      function
> >       EFI: seperate get efi table info code to single function
> >       Xen efi: Add xen efi enabled detect
> >       Xen vga: add the xen efi video mode support
> >
> > arch/x86/platform/efi/Makefile   |    2 +-
> > arch/x86/platform/efi/efi-xen.c  |  460 ++++++++++++++++++++++++++++++++++++++
> > arch/x86/platform/efi/efi.c      |   63 +++++-
> > arch/x86/xen/enlighten.c         |    3 +
> > arch/x86/xen/vga.c               |    7 +
> > include/linux/efi.h              |   14 +-
> > include/xen/interface/platform.h |  122 ++++++++++
> > include/xen/interface/xen.h      |    1 +
> > 8 files changed, 665 insertions(+), 7 deletions(-)
> >
> > Thanks
> > Liang.
> 
> =========== PATCH BELOW ===========
> 
> diff -urN a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> --- a/arch/x86/platform/efi/efi.c 2013-05-22 20:37:13.432000000 -0400
> +++ b/arch/x86/platform/efi/efi.c 2013-05-23 02:23:03.384000000 -0400
> @@ -95,6 +95,29 @@
>  }
>  EXPORT_SYMBOL(efi_enabled);
> 
> +static void efi_init_generic(void);
> +static void efi_late_init_generic(void);
> +
> +static void efi_enter_virtual_mode_generic(void);
> +static u32 efi_mem_type_generic(unsigned long phys_addr);
> +static u64 efi_mem_attributes_generic(unsigned long phys_addr);
> +static void efi_reserve_boot_services_generic(void);
> +static void efi_free_boot_services_generic(void);
> +static int efi_memblock_x86_reserve_range_generic(void);
> +
> +static const struct efi_init_funcs __initconst efi_generic_funcs = {
> + .init       = efi_init_generic,
> + .late_init       = efi_late_init_generic,
> + .reserve_boot_services = efi_reserve_boot_services_generic,
> + .free_boot_services    = efi_free_boot_services_generic,
> + .enter_virtual_mode    = efi_enter_virtual_mode_generic,
> + .mem_type       = efi_mem_type_generic,
> + .mem_attributes       = efi_mem_attributes_generic,
> + .x86_reserve_range     = efi_memblock_x86_reserve_range_generic
> +};
> +
> +const struct efi_init_funcs *efi_override_funcs =  &efi_generic_funcs;
> +
>  static bool __initdata disable_runtime = false;
>  static int __init setup_noefi(char *arg)
>  {
> @@ -443,7 +466,7 @@
>   sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
>  }
> 
> -int __init efi_memblock_x86_reserve_range(void)
> +int __init efi_memblock_x86_reserve_range_generic(void)
>  {
>   unsigned long pmap;
> 
> @@ -475,6 +498,8 @@
>   void *p;
>   int i;
> 
> + if (memmap.map == NULL) return;
> +
>   for (p = memmap.map, i = 0;
>       p < memmap.map_end;
>       p += memmap.desc_size, i++) {
> @@ -488,7 +513,7 @@
>  }
>  #endif  /*  EFI_DEBUG  */
> 
> -void __init efi_reserve_boot_services(void)
> +static void efi_reserve_boot_services_generic(void)
>  {
>   void *p;
> 
> @@ -529,7 +554,7 @@
>   }
>  }
> 
> -void __init efi_free_boot_services(void)
> +void __init efi_free_boot_services_generic(void)
>  {
>   void *p;
> 
> @@ -644,7 +669,7 @@
>   return 0;
>  }
> 
> -static int __init efi_config_init(u64 tables, int nr_tables)
> +int __init efi_config_init(u64 tables, int nr_tables, struct efi *efi_t)
>  {
>   void *config_tables, *tablep;
>   int i, sz;
> @@ -665,7 +690,7 @@
> 
>   tablep = config_tables;
>   pr_info("");
> - for (i = 0; i < efi.systab->nr_tables; i++) {
> + for (i = 0; i < nr_tables; i++) {
>   efi_guid_t guid;
>   unsigned long table;
> 
> @@ -679,7 +704,7 @@
>   pr_cont("\n");
>   pr_err("Table located above 4GB, disabling EFI.\n");
>   early_iounmap(config_tables,
> -      efi.systab->nr_tables * sz);
> +      nr_tables * sz);
>   return -EINVAL;
>   }
>  #endif
> @@ -688,33 +713,33 @@
>   table = ((efi_config_table_32_t *)tablep)->table;
>   }
>   if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
> - efi.mps = table;
> + efi_t->mps = table;
>   pr_cont(" MPS=0x%lx ", table);
>   } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
> - efi.acpi20 = table;
> + efi_t->acpi20 = table;
>   pr_cont(" ACPI 2.0=0x%lx ", table);
>   } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
> - efi.acpi = table;
> + efi_t->acpi = table;
>   pr_cont(" ACPI=0x%lx ", table);
>   } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
> - efi.smbios = table;
> + efi_t->smbios = table;
>   pr_cont(" SMBIOS=0x%lx ", table);
>  #ifdef CONFIG_X86_UV
>   } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) {
> - efi.uv_systab = table;
> + efi_t->uv_systab = table;
>   pr_cont(" UVsystab=0x%lx ", table);
>  #endif
>   } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
> - efi.hcdp = table;
> + efi_t->hcdp = table;
>   pr_cont(" HCDP=0x%lx ", table);
>   } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
> - efi.uga = table;
> + efi_t->uga = table;
>   pr_cont(" UGA=0x%lx ", table);
>   }
>   tablep += sz;
>   }
>   pr_cont("\n");
> - early_iounmap(config_tables, efi.systab->nr_tables * sz);
> + early_iounmap(config_tables, nr_tables * sz);
>   return 0;
>  }
> 
> @@ -770,7 +795,7 @@
>   return 0;
>  }
> 
> -void __init efi_init(void)
> +static void efi_init_generic(void)
>  {
>   efi_char16_t *c16;
>   char vendor[100] = "unknown";
> @@ -830,7 +855,7 @@
>   efi.systab->hdr.revision >> 16,
>   efi.systab->hdr.revision & 0xffff, vendor);
> 
> - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
> + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, &efi))
>   return;
> 
>   set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> @@ -865,9 +890,11 @@
>  #endif
>  }
> 
> -void __init efi_late_init(void)
> +void __init efi_late_init_generic(void)
>  {
> +#ifdef CONFIG_ACPI_BGRT
>   efi_bgrt_init();
> +#endif
>  }
> 
>  void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
> @@ -947,7 +974,7 @@
>   * This enables the runtime services to be called without having to
>   * thunk back into physical mode for every invocation.
>   */
> -void __init efi_enter_virtual_mode(void)
> +static void efi_enter_virtual_mode_generic(void)
>  {
>   efi_memory_desc_t *md, *prev_md = NULL;
>   efi_status_t status;
> @@ -1080,7 +1107,7 @@
>  /*
>   * Convenience functions to obtain memory types and attributes
>   */
> -u32 efi_mem_type(unsigned long phys_addr)
> +static u32 efi_mem_type_generic(unsigned long phys_addr)
>  {
>   efi_memory_desc_t *md;
>   void *p;
> @@ -1098,7 +1125,7 @@
>   return 0;
>  }
> 
> -u64 efi_mem_attributes(unsigned long phys_addr)
> +static u64 efi_mem_attributes_generic(unsigned long phys_addr)
>  {
>   efi_memory_desc_t *md;
>   void *p;
> @@ -1113,6 +1140,68 @@
>   return 0;
>  }
> 
> +void efi_init_function_register(const struct efi_init_funcs *funcs)
> +{
> + efi_override_funcs = funcs;
> +}
> +
> +void __init efi_init(void)
> +{
> + if (efi_override_funcs->init)
> + {
> + efi_override_funcs->init();
> + }
> + else
> + {
> + memmap.map = NULL;  /* Xen case */
> + }
> +}
> +
> +void __init efi_late_init(void)
> +{
> + if (efi_override_funcs->late_init)
> + efi_override_funcs->late_init();
> +}
> +
> +void __init efi_reserve_boot_services(void)
> +{
> + if (efi_override_funcs->reserve_boot_services)
> + efi_override_funcs->reserve_boot_services();
> +}
> +
> +void __init efi_free_boot_services(void)
> +{
> + if (efi_override_funcs->free_boot_services)
> + efi_override_funcs->free_boot_services();
> +}
> +
> +void __init efi_enter_virtual_mode(void)
> +{
> + if (efi_override_funcs->enter_virtual_mode)
> + efi_override_funcs->enter_virtual_mode();
> +}
> +
> +int __init efi_memblock_x86_reserve_range(void)
> +{
> + if (efi_override_funcs->x86_reserve_range)
> + return efi_override_funcs->x86_reserve_range();
> + return 0;
> +}
> +
> +u32 efi_mem_type(unsigned long phys_addr)
> +{
> + if (efi_override_funcs->mem_type)
> + return efi_override_funcs->mem_type(phys_addr);
> + return EFI_INVALID_TYPE;
> +}
> +
> +u64 efi_mem_attributes(unsigned long phys_addr)
> +{
> + if (efi_override_funcs->mem_attributes)
> + return efi_override_funcs->mem_attributes(phys_addr);
> + return EFI_INVALID_ATTRIBUTE;
> +}
> +
>  /*
>   * Some firmware has serious problems when using more than 50% of the EFI
>   * variable store, i.e. it triggers bugs that can brick machines. Ensure that
> diff -urN a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
> --- a/arch/x86/platform/efi/Makefile 2013-05-22 20:39:05.260000000 -0400
> +++ b/arch/x86/platform/efi/Makefile 2013-05-23 02:04:00.048000000 -0400
> @@ -1,2 +1,5 @@
>  obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
> +ifdef CONFIG_XEN
> +obj-$(CONFIG_EFI) += xen.o
> +endif
>  obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
> diff -urN a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
> --- a/arch/x86/platform/efi/xen.c 1969-12-31 19:00:00.000000000 -0500
> +++ b/arch/x86/platform/efi/xen.c 2013-05-23 02:28:22.340000000 -0400
> @@ -0,0 +1,428 @@
> +/*
> + * Xen EFI (Extensible Firmware Interface) support functions
> + * Based on related efforts in SLE and SUSE trees
> + *
> + * Copyright (C) 1999 VA Linux Systems
> + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
> + * Copyright (C) 1999-2002 Hewlett-Packard Co.
> + * David Mosberger-Tang <davidm@hpl.hp.com>
> + * Stephane Eranian <eranian@hpl.hp.com>
> + * Copyright (C) 2005-2008 Intel Co.
> + * Fenghua Yu <fenghua.yu@intel.com>
> + * Bibo Mao <bibo.mao@intel.com>
> + * Chandramouli Narayanan <mouli@linux.intel.com>
> + * Huang Ying <ying.huang@intel.com>
> + * Copyright (C) 2011 Novell Co.
> + * Jan Beulic <JBeulich@suse.com>
> + * Copyright (C) 2011-2012 Oracle Co.
> + * Liang Tang <liang.tang@oracle.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/efi.h>
> +#include <linux/export.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/time.h>
> +
> +#include <asm/setup.h>
> +#include <asm/efi.h>
> +#include <asm/time.h>
> +#include <asm/cacheflush.h>
> +#include <asm/tlbflush.h>
> +#include <asm/x86_init.h>
> +
> +#include <xen/interface/platform.h>
> +#include <asm/xen/hypercall.h>
> +
> +#define PFX "EFI: "
> +
> +#define call (op.u.efi_runtime_call)
> +#define DECLARE_CALL(what) \
> + struct xen_platform_op op; \
> + op.cmd = XENPF_efi_runtime_call; \
> + call.function = XEN_EFI_##what; \
> + call.misc = 0
> +
> +static void register_xen_efi_function(void);
> +
> +static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> +{
> + int err;
> + DECLARE_CALL(get_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
> + memcpy(tm, &call.u.get_time.time, sizeof(*tm));
> + }
> +
> + if (tc) {
> + tc->resolution = call.u.get_time.resolution;
> + tc->accuracy = call.u.get_time.accuracy;
> + tc->sets_to_zero = !!(call.misc &
> +      XEN_EFI_GET_TIME_SET_CLEARS_NS);
> + }
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_time(efi_time_t *tm)
> +{
> + DECLARE_CALL(set_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
> + memcpy(&call.u.set_time, tm, sizeof(*tm));
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
> +    efi_bool_t *pending,
> +    efi_time_t *tm)
> +{
> + int err;
> + DECLARE_CALL(get_wakeup_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
> + memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
> + }
> +
> + if (enabled)
> + *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
> +
> + if (pending)
> + *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
> +{
> + DECLARE_CALL(set_wakeup_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
> + if (enabled)
> + call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
> + if (tm)
> + memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
> + else
> + call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 *attr,
> + unsigned long *data_size,
> + void *data)
> +{
> + int err;
> + DECLARE_CALL(get_variable);
> +
> + set_xen_guest_handle(call.u.get_variable.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> +     sizeof(call.u.get_variable.vendor_guid));
> + memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.get_variable.size = *data_size;
> + set_xen_guest_handle(call.u.get_variable.data, data);
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *data_size = call.u.get_variable.size;
> + *attr = call.misc; /* misc in struction is U32 variable*/
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
> +      efi_char16_t *name,
> +      efi_guid_t *vendor)
> +{
> + int err;
> + DECLARE_CALL(get_next_variable_name);
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> + call.u.get_next_variable_name.size = *name_size;
> + set_xen_guest_handle(call.u.get_next_variable_name.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> +     sizeof(call.u.get_next_variable_name.vendor_guid));
> + memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
> +       sizeof(*vendor));
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *name_size = call.u.get_next_variable_name.size;
> + memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
> +       sizeof(*vendor));
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 attr,
> + unsigned long data_size,
> + void *data)
> +{
> + DECLARE_CALL(set_variable);
> +
> + set_xen_guest_handle(call.u.set_variable.name, name);
> + call.misc = attr;
> + BUILD_BUG_ON(sizeof(*vendor) !=
> +     sizeof(call.u.set_variable.vendor_guid));
> + memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.set_variable.size = data_size;
> + set_xen_guest_handle(call.u.set_variable.data, data);
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_variable_info(u32 attr,
> + u64 *storage_space,
> + u64 *remaining_space,
> + u64 *max_variable_size)
> +{
> + int err;
> + DECLARE_CALL(query_variable_info);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *storage_space = call.u.query_variable_info.max_store_size;
> + *remaining_space = call.u.query_variable_info.remain_store_size;
> + *max_variable_size = call.u.query_variable_info.max_size;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
> +{
> + int err;
> + DECLARE_CALL(get_next_high_monotonic_count);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *count = call.misc;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
> +   unsigned long count,
> +   unsigned long sg_list)
> +{
> + DECLARE_CALL(update_capsule);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
> +     capsules);
> + call.u.update_capsule.capsule_count = count;
> + call.u.update_capsule.sg_list = sg_list;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
> +       unsigned long count,
> +       u64 *max_size,
> +       int *reset_type)
> +{
> + int err;
> + DECLARE_CALL(query_capsule_capabilities);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.query_capsule_capabilities.
> + capsule_header_array, capsules);
> + call.u.query_capsule_capabilities.capsule_count = count;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *max_size = call.u.query_capsule_capabilities.max_capsule_size;
> + *reset_type = call.u.query_capsule_capabilities.reset_type;
> +
> + return call.status;
> +}
> +
> +#undef DECLARE_CALL
> +#undef call
> +
> +static const struct efi __initconst efi_xen = {
> + .mps                      = EFI_INVALID_TABLE_ADDR,
> + .acpi                     = EFI_INVALID_TABLE_ADDR,
> + .acpi20                   = EFI_INVALID_TABLE_ADDR,
> + .smbios                   = EFI_INVALID_TABLE_ADDR,
> + .sal_systab               = EFI_INVALID_TABLE_ADDR,
> + .boot_info                = EFI_INVALID_TABLE_ADDR,
> + .hcdp                     = EFI_INVALID_TABLE_ADDR,
> + .uga                      = EFI_INVALID_TABLE_ADDR,
> + .uv_systab                = EFI_INVALID_TABLE_ADDR,
> + .get_time                 = xen_efi_get_time,
> + .set_time                 = xen_efi_set_time,
> + .get_wakeup_time          = xen_efi_get_wakeup_time,
> + .set_wakeup_time          = xen_efi_set_wakeup_time,
> + .get_variable             = xen_efi_get_variable,
> + .get_next_variable        = xen_efi_get_next_variable,
> + .set_variable             = xen_efi_set_variable,
> + .get_next_high_mono_count = xen_efi_get_next_high_mono_count,
> + .query_variable_info      = xen_efi_query_variable_info,
> + .update_capsule           = xen_efi_update_capsule,
> + .query_capsule_caps       = xen_efi_query_capsule_caps,
> +};
> +
> +void xen_efi_probe(void)
> +{
> + static struct xen_platform_op __initdata op = {
> + .cmd = XENPF_firmware_info,
> + .u.firmware_info = {
> + .type = XEN_FW_EFI_INFO,
> + .index = XEN_FW_EFI_CONFIG_TABLE
> + }
> + };
> +
> + if (HYPERVISOR_dom0_op(&op) == 0) {
> + /*efi_enabled = 1;*/
> + set_bit(EFI_BOOT, &x86_efi_facility);
> + /* this should be set based on whether the EFI loader
> + * signature contains "EL64" (see arch/x86/kernel/setup.c).
> + * Looks like a new hypercall will be needed for this */
> + set_bit(EFI_64BIT, &x86_efi_facility);
> +
> + register_xen_efi_function();
> + }
> +}
> +
> +
> +static void __init efi_init_xen(void)
> +{
> + efi_char16_t c16[100];
> + char vendor[ARRAY_SIZE(c16)] = "unknown";
> + int ret, i;
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + efi = efi_xen;
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> +
> + /*
> + * Show what we know for posterity
> + */
> + op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
> + info->vendor.bufsz = sizeof(c16);
> + set_xen_guest_handle(info->vendor.name, c16);
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret) {
> + for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
> + vendor[i] = c16[i];
> + vendor[i] = '\0';
> + } else
> + pr_err("Could not get the firmware vendor!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + pr_info("EFI-xen v%u.%.02u by %s\n",
> +       info->version >> 16,
> +       info->version & 0xffff, vendor);
> + else
> + pr_err("Could not get EFI revision!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + efi.runtime_version = info->version;
> + else
> + pr_warn(PFX "Could not get runtime services revision.\n");
> + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
> +
> + /*
> + * Let's see what config tables the firmware passed to us.
> + */
> + op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
> + if (HYPERVISOR_dom0_op(&op))
> + BUG();
> +
> + if (efi_config_init(info->cfg.addr, info->cfg.nent, &efi))
> + panic("Could not init EFI Configuration Tables!\n");
> + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> +
> + /* the EFI memory info is digested by the hypervisor and
> + * supplied to dom0 via E820 entries */
> + set_bit(EFI_MEMMAP, &x86_efi_facility);
> +
> + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
> +
> + /* NOTE: efi.c only does this for CONFIG_X86_32 */
> + x86_platform.get_wallclock = efi_get_time;
> + x86_platform.set_wallclock = efi_set_rtc_mmss;
> +}
> +
> +/*
> + * Convenience functions to obtain memory types and attributes
> + */
> +static u32 efi_mem_type_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
> +}
> +
> +static u64 efi_mem_attributes_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
> +}
> +
> +static const struct __initconst efi_init_funcs xen_efi_funcs = {
> + .init        = efi_init_xen,
> + .late_init = NULL,
> + .reserve_boot_services  = NULL,
> + .free_boot_services     = NULL,
> + .enter_virtual_mode     = NULL,
> + .mem_type        = efi_mem_type_xen,
> + .mem_attributes        = efi_mem_attributes_xen,
> + .x86_reserve_range = NULL
> +};
> +
> +static void register_xen_efi_function(void)
> +{
> + efi_init_function_register(&xen_efi_funcs);
> +}
> diff -urN a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> --- a/arch/x86/xen/enlighten.c 2013-05-22 20:36:48.608000000 -0400
> +++ b/arch/x86/xen/enlighten.c 2013-05-22 20:44:15.784000000 -0400
> @@ -31,6 +31,7 @@
>  #include <linux/pci.h>
>  #include <linux/gfp.h>
>  #include <linux/memblock.h>
> +#include <linux/efi.h>
> 
>  #include <xen/xen.h>
>  #include <xen/events.h>
> @@ -1532,6 +1533,8 @@
> 
>   xen_setup_runstate_info(0);
> 
> + if (xen_initial_domain())
> + xen_efi_probe();
>   /* Start the world */
>  #ifdef CONFIG_X86_32
>   i386_start_kernel();
> diff -urN a/include/linux/efi.h b/include/linux/efi.h
> --- a/include/linux/efi.h 2013-05-22 20:36:14.820000000 -0400
> +++ b/include/linux/efi.h 2013-05-23 02:22:12.544000000 -0400
> @@ -84,7 +84,10 @@
>  #define EFI_PAL_CODE 13
>  #define EFI_MAX_MEMORY_TYPE 14
> 
> +#define EFI_INVALID_TYPE 0xffffffff
> +
>  /* Attribute values: */
> +#define EFI_INVALID_ATTRIBUTE ((u64)0x0000000000000000ULL) /* invalid
> attribute*/
>  #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
>  #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
>  #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
> @@ -554,6 +557,17 @@
>   efi_set_virtual_address_map_t *set_virtual_address_map;
>  } efi;
> 
> +struct efi_init_funcs {
> + void (*init)(void);
> + void (*late_init)(void);
> + void (*reserve_boot_services)(void);
> + void (*free_boot_services)(void);
> + void (*enter_virtual_mode)(void);
> + u32 (*mem_type)(unsigned long phys_addr);
> + u64 (*mem_attributes)(unsigned long phys_addr);
> + int (*x86_reserve_range)(void);
> +};
> +
>  static inline int
>  efi_guidcmp (efi_guid_t left, efi_guid_t right)
>  {
> @@ -591,13 +605,16 @@
>  extern u32 efi_mem_type (unsigned long phys_addr);
>  extern u64 efi_mem_attributes (unsigned long phys_addr);
>  extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
> -extern int __init efi_uart_console_only (void);
> +extern int efi_uart_console_only (void);
>  extern void efi_initialize_iomem_resources(struct resource *code_resource,
>   struct resource *data_resource, struct resource *bss_resource);
>  extern unsigned long efi_get_time(void);
>  extern int efi_set_rtc_mmss(unsigned long nowtime);
>  extern void efi_reserve_boot_services(void);
>  extern struct efi_memory_map memmap;
> +extern void efi_init_function_register(const struct efi_init_funcs *funcs);
> +extern int efi_config_init(u64 tables, int nr_tables, struct efi *efi_t);
> +extern void xen_efi_probe(void);
> 
>  /**
>   * efi_range_is_wc - check the WC bit on an address range
> @@ -621,7 +638,7 @@
>  }
> 
>  #ifdef CONFIG_EFI_PCDP
> -extern int __init efi_setup_pcdp_console(char *);
> +extern int efi_setup_pcdp_console(char *);
>  #endif
> 
>  /*
> diff -urN a/include/xen/interface/platform.h b/include/xen/interface/platform.h
> --- a/include/xen/interface/platform.h 2013-05-22 20:35:50.280000000 -0400
> +++ b/include/xen/interface/platform.h 2013-05-22 20:43:17.068000000 -0400
> @@ -108,10 +108,111 @@
>  };
>  DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);
> 
> +#define XENPF_efi_runtime_call    49
> +#define XEN_EFI_get_time                      1
> +#define XEN_EFI_set_time                      2
> +#define XEN_EFI_get_wakeup_time               3
> +#define XEN_EFI_set_wakeup_time               4
> +#define XEN_EFI_get_next_high_monotonic_count 5
> +#define XEN_EFI_get_variable                  6
> +#define XEN_EFI_set_variable                  7
> +#define XEN_EFI_get_next_variable_name        8
> +#define XEN_EFI_query_variable_info           9
> +#define XEN_EFI_query_capsule_capabilities   10
> +#define XEN_EFI_update_capsule               11
> +
> +struct xenpf_efi_runtime_call {
> + uint32_t function;
> +    /*
> +     * This field is generally used for per sub-function flags (defined
> +     * below), except for the XEN_EFI_get_next_high_monotonic_count case,
> +     * where it holds the single returned value.
> +     */
> + uint32_t misc;
> + unsigned long status;
> + union {
> +#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
> + struct {
> + struct xenpf_efi_time {
> + uint16_t year;
> + uint8_t month;
> + uint8_t day;
> + uint8_t hour;
> + uint8_t min;
> + uint8_t sec;
> + uint32_t ns;
> + int16_t tz;
> + uint8_t daylight;
> + } time;
> + uint32_t resolution;
> + uint32_t accuracy;
> + } get_time;
> +
> + struct xenpf_efi_time set_time;
> +
> +#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
> +#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
> + struct xenpf_efi_time get_wakeup_time;
> +
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE      0x00000001
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
> + struct xenpf_efi_time set_wakeup_time;
> +
> +#define XEN_EFI_VARIABLE_NON_VOLATILE       0x00000001
> +#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
> +#define XEN_EFI_VARIABLE_RUNTIME_ACCESS     0x00000004
> + struct {
> + GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
> + unsigned long size;
> + GUEST_HANDLE(void) data;
> + struct xenpf_efi_guid {
> + uint32_t data1;
> + uint16_t data2;
> + uint16_t data3;
> + uint8_t data4[8];
> + } vendor_guid;
> + } get_variable, set_variable;
> +
> + struct {
> + unsigned long size;
> + GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
> + struct xenpf_efi_guid vendor_guid;
> + } get_next_variable_name;
> +
> + struct {
> + uint32_t attr;
> + uint64_t max_store_size;
> + uint64_t remain_store_size;
> + uint64_t max_size;
> + } query_variable_info;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t max_capsule_size;
> + unsigned int reset_type;
> + } query_capsule_capabilities;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t sg_list; /* machine address */
> + } update_capsule;
> + } u;
> +};
> +DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
> +
>  #define XENPF_firmware_info       50
>  #define XEN_FW_DISK_INFO          1 /* from int 13 AH=08/41/48 */
>  #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
>  #define XEN_FW_VBEDDC_INFO        3 /* from int 10 AX=4f15 */
> +#define XEN_FW_EFI_INFO           4 /* from EFI */
> +#define  XEN_FW_EFI_VERSION        0
> +#define  XEN_FW_EFI_CONFIG_TABLE   1
> +#define  XEN_FW_EFI_VENDOR         2
> +#define  XEN_FW_EFI_MEM_INFO       3
> +#define  XEN_FW_EFI_RT_VERSION     4
> +#define  XEN_FW_EFI_PCI_ROM        5
>  #define XEN_FW_KBD_SHIFT_FLAGS    5 /* Int16, Fn02: Get keyboard
> shift flags. */
>  struct xenpf_firmware_info {
>   /* IN variables. */
> @@ -143,6 +244,36 @@
>   /* must refer to 128-byte buffer */
>   GUEST_HANDLE(uchar) edid;
>   } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
> + union xenpf_efi_info {
> + uint32_t version;
> + struct {
> + uint64_t addr;   /* EFI_CONFIGURATION_TABLE */
> + uint32_t nent;
> + } cfg;
> + struct {
> + uint32_t revision;
> + uint32_t bufsz;  /* input, in bytes */
> + GUEST_HANDLE(void) name;
> + /* UCS-2/UTF-16 string */
> + } vendor;
> + struct {
> + uint64_t addr;
> + uint64_t size;
> + uint64_t attr;
> + uint32_t type;
> + } mem;
> + struct {
> + /* IN variables */
> + uint16_t segment;
> + uint8_t bus;
> + uint8_t devfn;
> + uint16_t vendor;
> + uint16_t devid;
> + /* OUT variables */
> + uint64_t address;
> + xen_ulong_t size;
> + } pci_rom;
> + } efi_info; /* XEN_FW_EFI_INFO */
> 
>   uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
>   } u;
> @@ -361,6 +492,7 @@
>   struct xenpf_read_memtype      read_memtype;
>   struct xenpf_microcode_update  microcode;
>   struct xenpf_platform_quirk    platform_quirk;
> + struct xenpf_efi_runtime_call  efi_runtime_call;
>   struct xenpf_firmware_info     firmware_info;
>   struct xenpf_enter_acpi_sleep  enter_acpi_sleep;
>   struct xenpf_change_freq       change_freq;
> diff -urN a/init/main.c b/init/main.c
> --- a/init/main.c 2013-05-22 20:35:17.768000000 -0400
> +++ b/init/main.c 2013-05-22 20:43:51.468000000 -0400
> @@ -634,10 +634,12 @@
>   acpi_early_init(); /* before LAPIC and SMP init */
>   sfi_init_late();
> 
> +#ifdef CONFIG_X86
>   if (efi_enabled(EFI_RUNTIME_SERVICES)) {
>   efi_late_init();
>   efi_free_boot_services();
>   }
> +#endif
> 
>   ftrace_init();


> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-05-24 14:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-23 10:04 [REBASE] xen: patches (against Linux kernel) for supporting efi Eric Shelton
2013-05-23 10:19 ` Jan Beulich
2013-05-23 11:05   ` Eric Shelton
2013-05-23 11:18     ` Jan Beulich
2013-05-23 14:11       ` Eric Shelton
2013-05-23 14:45         ` Jan Beulich
2013-05-24 14:24 ` Konrad Rzeszutek Wilk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.