[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |