[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [REBASE] xen: patches (against Linux kernel) for supporting efi



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@xxxxxxxxx>
> 
> 
> 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@xxxxxxxxxxx>
> + * Copyright (C) 1999-2002 Hewlett-Packard Co.
> + * David Mosberger-Tang <davidm@xxxxxxxxxx>
> + * Stephane Eranian <eranian@xxxxxxxxxx>
> + * Copyright (C) 2005-2008 Intel Co.
> + * Fenghua Yu <fenghua.yu@xxxxxxxxx>
> + * Bibo Mao <bibo.mao@xxxxxxxxx>
> + * Chandramouli Narayanan <mouli@xxxxxxxxxxxxxxx>
> + * Huang Ying <ying.huang@xxxxxxxxx>
> + * Copyright (C) 2011 Novell Co.
> + * Jan Beulic <JBeulich@xxxxxxxx>
> + * Copyright (C) 2011-2012 Oracle Co.
> + * Liang Tang <liang.tang@xxxxxxxxxx>
> + */
> +
> +#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@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.