From ed105f0f5442dd88be4201c37092c3897a7347eeefe3bfa42e964af014d2f072 Mon Sep 17 00:00:00 2001 From: Charles Arnold Date: Fri, 1 Jul 2011 19:31:25 +0000 Subject: [PATCH] - fate#309894: Xen needs to correctly understand family 15h CPU topology - fate#311376: EFI support in SP2 - fate#311529: Native UEFI booting under Xen (installation) 23074-pfn.h.patch 23571-vtd-fault-verbosity.patch 23574-x86-dom0-compressed-ELF.patch 23575-x86-DMI.patch 23610-x86-topology-info.patch 23611-amd-fam15-topology.patch 23613-EFI-headers.patch 23614-x86_64-EFI-boot.patch 23615-x86_64-EFI-runtime.patch 23616-x86_64-EFI-MPS.patch - Mark xen-scsi.ko supported (bnc#582265, fate#309459). - fate#310308: Hypervisor assisted watchdog driver ioemu-watchdog-support.patch ioemu-watchdog-linkage.patch ioemu-watchdog-ib700-timer.patch tools-watchdog-support.patch - bnc#702025 - VUL-0: xen: VT-d (PCI passthrough) MSI trap injection (CVE-2011-1898) Fixed in Xen version 4.1.1 - fate#310956: Support Direct Kernel Boot for FV guests kernel-boot-hvm.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=130 --- 23074-pfn.h.patch | 114 + 23481-x86-SMEP.patch | 4 +- 23571-vtd-fault-verbosity.patch | 142 + 23574-x86-dom0-compressed-ELF.patch | 123 + 23575-x86-DMI.patch | 154 + 23610-x86-topology-info.patch | 212 ++ 23611-amd-fam15-topology.patch | 168 + 23613-EFI-headers.patch | 2725 +++++++++++++++++ 23614-x86_64-EFI-boot.patch | 2485 +++++++++++++++ 23615-x86_64-EFI-runtime.patch | 787 +++++ 23616-x86_64-EFI-MPS.patch | 150 + 32on64-extra-mem.patch | 2 +- change-vnc-passwd.patch | 157 + disable_emulated_device.diff | 2 +- hv_extid_compatibility.patch | 8 +- ioemu-disable-emulated-ide-if-pv.patch | 6 +- ioemu-watchdog-ib700-timer.patch | 34 + ioemu-watchdog-linkage.patch | 72 + ioemu-watchdog-support.patch | 963 ++++++ kernel-boot-hvm.patch | 245 ++ log-guest-console.patch | 141 + supported_module.diff | 7 +- tools-watchdog-support.patch | 149 + x86-cpufreq-report.patch | 22 +- x86-show-page-walk-early.patch | 6 +- xen-changeset.diff | 10 +- xen-warnings-unused.diff | 12 +- xen.changes | 77 + ...ate311487.xen_platform_pci.dmistring.patch | 42 + xen.spec | 190 +- xend-domain-lock-sfex.patch | 8 +- xend-domain-lock.patch | 4 +- xenpaging.autostart.patch | 16 +- 33 files changed, 9136 insertions(+), 101 deletions(-) create mode 100644 23074-pfn.h.patch create mode 100644 23571-vtd-fault-verbosity.patch create mode 100644 23574-x86-dom0-compressed-ELF.patch create mode 100644 23575-x86-DMI.patch create mode 100644 23610-x86-topology-info.patch create mode 100644 23611-amd-fam15-topology.patch create mode 100644 23613-EFI-headers.patch create mode 100644 23614-x86_64-EFI-boot.patch create mode 100644 23615-x86_64-EFI-runtime.patch create mode 100644 23616-x86_64-EFI-MPS.patch create mode 100644 change-vnc-passwd.patch create mode 100644 ioemu-watchdog-ib700-timer.patch create mode 100644 ioemu-watchdog-linkage.patch create mode 100644 ioemu-watchdog-support.patch create mode 100644 kernel-boot-hvm.patch create mode 100644 log-guest-console.patch create mode 100644 tools-watchdog-support.patch create mode 100644 xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch diff --git a/23074-pfn.h.patch b/23074-pfn.h.patch new file mode 100644 index 0000000..154ba88 --- /dev/null +++ b/23074-pfn.h.patch @@ -0,0 +1,114 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Keir Fraser +# Date 1300887295 0 +# Node ID c80e0fb4fe932b4d8379ea5739af93ae22a30ea5 +# Parent 3831bd253e02aa0536ed32e936777d026abb955e +Define new header for PFN_{DOWN,UP} macros. + +Signed-off-by: Keir Fraser + +--- a/xen/arch/x86/domain_build.c ++++ b/xen/arch/x86/domain_build.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/xen/arch/x86/e820.c ++++ b/xen/arch/x86/e820.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -99,6 +99,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/xen/arch/x86/msi.c ++++ b/xen/arch/x86/msi.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/xen/arch/x86/numa.c ++++ b/xen/arch/x86/numa.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + +--- a/xen/arch/x86/setup.c ++++ b/xen/arch/x86/setup.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #ifdef CONFIG_COMPAT +--- a/xen/arch/x86/srat.c ++++ b/xen/arch/x86/srat.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + +--- a/xen/arch/x86/tboot.c ++++ b/xen/arch/x86/tboot.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + #include + #include +--- a/xen/include/asm-x86/page.h ++++ b/xen/include/asm-x86/page.h +@@ -396,8 +396,6 @@ static inline uint32_t cacheattr_to_pte_ + + #endif /* !__ASSEMBLY__ */ + +-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) + #define PAGE_ALIGN(x) (((x) + PAGE_SIZE - 1) & PAGE_MASK) + + #endif /* __X86_PAGE_H__ */ +--- /dev/null ++++ b/xen/include/xen/pfn.h +@@ -0,0 +1,9 @@ ++#ifndef __XEN_PFN_H__ ++#define __XEN_PFN_H__ ++ ++#include ++ ++#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) ++#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) ++ ++#endif /* __XEN_PFN_H__ */ diff --git a/23481-x86-SMEP.patch b/23481-x86-SMEP.patch index 6297f7c..03d9ee5 100644 --- a/23481-x86-SMEP.patch +++ b/23481-x86-SMEP.patch @@ -25,7 +25,7 @@ Signed-off-by: Keir Fraser --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c -@@ -61,6 +61,10 @@ integer_param("maxcpus", max_cpus); +@@ -62,6 +62,10 @@ integer_param("maxcpus", max_cpus); static bool_t __initdata opt_watchdog; boolean_param("watchdog", opt_watchdog); @@ -36,7 +36,7 @@ Signed-off-by: Keir Fraser /* **** Linux config option: propagated to domain0. */ /* "acpi=off": Sisables both ACPI table parsing and interpreter. */ /* "acpi=force": Override the disable blacklist. */ -@@ -1204,11 +1208,17 @@ void __init __start_xen(unsigned long mb +@@ -1205,11 +1209,17 @@ void __init __start_xen(unsigned long mb arch_init_memory(); identify_cpu(&boot_cpu_data); diff --git a/23571-vtd-fault-verbosity.patch b/23571-vtd-fault-verbosity.patch new file mode 100644 index 0000000..fa20b09 --- /dev/null +++ b/23571-vtd-fault-verbosity.patch @@ -0,0 +1,142 @@ +# HG changeset patch +# User Allen Kay +# Date 1308823884 -3600 +# Node ID d3ac71f22e8621d9a7604f82f3976337e6c97a9a +# Parent 065ca14be963fe4da55d629ed0b3692a14253a86 +[VTD] print out debug message in vt-d fault handler only when iommu=debug is set + +Print out debug messages in vtd_page_fault() handler only when +iommu=debug is set xen boot parameter. + +Signed-off-by: Allen Kay + +--- a/xen/drivers/passthrough/amd/iommu_acpi.c ++++ b/xen/drivers/passthrough/amd/iommu_acpi.c +@@ -822,7 +822,7 @@ static int __init parse_ivrs_table(struc + + BUG_ON(!table); + +- if ( amd_iommu_debug ) ++ if ( iommu_debug ) + dump_acpi_table_header(table); + + /* parse IVRS blocks */ +--- a/xen/drivers/passthrough/iommu.c ++++ b/xen/drivers/passthrough/iommu.c +@@ -48,7 +48,7 @@ bool_t __read_mostly iommu_snoop = 1; + bool_t __read_mostly iommu_qinval = 1; + bool_t __read_mostly iommu_intremap = 1; + bool_t __read_mostly iommu_hap_pt_share; +-bool_t __read_mostly amd_iommu_debug; ++bool_t __read_mostly iommu_debug; + bool_t __read_mostly amd_iommu_perdev_intremap; + + static void __init parse_iommu_param(char *s) +@@ -74,8 +74,8 @@ static void __init parse_iommu_param(cha + iommu_qinval = 0; + else if ( !strcmp(s, "no-intremap") ) + iommu_intremap = 0; +- else if ( !strcmp(s, "amd-iommu-debug") ) +- amd_iommu_debug = 1; ++ else if ( !strcmp(s, "debug") ) ++ iommu_debug = 1; + else if ( !strcmp(s, "amd-iommu-perdev-intremap") ) + amd_iommu_perdev_intremap = 1; + else if ( !strcmp(s, "dom0-passthrough") ) +--- a/xen/drivers/passthrough/vtd/iommu.c ++++ b/xen/drivers/passthrough/vtd/iommu.c +@@ -821,7 +821,7 @@ static int iommu_page_fault_do_one(struc + + if ( fault_type == DMA_REMAP ) + { +- dprintk(XENLOG_WARNING VTDPREFIX, ++ INTEL_IOMMU_DEBUG( + "DMAR:[%s] Request device [%02x:%02x.%d] " + "fault addr %"PRIx64", iommu reg = %p\n" + "DMAR:[fault reason %02xh] %s\n", +@@ -830,12 +830,13 @@ static int iommu_page_fault_do_one(struc + PCI_FUNC(source_id & 0xFF), addr, iommu->reg, + fault_reason, reason); + #ifndef __i386__ /* map_domain_page() cannot be used in this context */ +- print_vtd_entries(iommu, (source_id >> 8), ++ if (iommu_debug) ++ print_vtd_entries(iommu, (source_id >> 8), + (source_id & 0xff), (addr >> PAGE_SHIFT)); + #endif + } + else +- dprintk(XENLOG_WARNING VTDPREFIX, ++ INTEL_IOMMU_DEBUG( + "INTR-REMAP: Request device [%02x:%02x.%d] " + "fault index %"PRIx64", iommu reg = %p\n" + "INTR-REMAP:[fault reason %02xh] %s\n", +@@ -849,26 +850,19 @@ static int iommu_page_fault_do_one(struc + static void iommu_fault_status(u32 fault_status) + { + if ( fault_status & DMA_FSTS_PFO ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Fault Overflow\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Fault Overflow\n"); + if ( fault_status & DMA_FSTS_PPF ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Primary Pending Fault\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Primary Pending Fault\n"); + if ( fault_status & DMA_FSTS_AFO ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Advanced Fault Overflow\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Advanced Fault Overflow\n"); + if ( fault_status & DMA_FSTS_APF ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Advanced Pending Fault\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Advanced Pending Fault\n"); + if ( fault_status & DMA_FSTS_IQE ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Invalidation Queue Error\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Invalidation Queue Error\n"); + if ( fault_status & DMA_FSTS_ICE ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Invalidation Completion Error\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Invalidation Completion Error\n"); + if ( fault_status & DMA_FSTS_ITE ) +- dprintk(XENLOG_ERR VTDPREFIX, +- "iommu_fault_status: Invalidation Time-out Error\n"); ++ INTEL_IOMMU_DEBUG("iommu_fault_status: Invalidation Time-out Error\n"); + } + + #define PRIMARY_FAULT_REG_LEN (16) +--- a/xen/drivers/passthrough/vtd/iommu.h ++++ b/xen/drivers/passthrough/vtd/iommu.h +@@ -512,4 +512,11 @@ struct intel_iommu { + struct acpi_drhd_unit *drhd; + }; + ++#define INTEL_IOMMU_DEBUG(fmt, args...) \ ++ do \ ++ { \ ++ if ( iommu_debug ) \ ++ dprintk(XENLOG_WARNING VTDPREFIX, fmt, ## args); \ ++ } while(0) ++ + #endif +--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h ++++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +@@ -34,7 +34,7 @@ + #define AMD_IOMMU_DEBUG(fmt, args...) \ + do \ + { \ +- if ( amd_iommu_debug ) \ ++ if ( iommu_debug ) \ + printk(XENLOG_INFO "AMD-Vi: " fmt, ## args); \ + } while(0) + +--- a/xen/include/xen/iommu.h ++++ b/xen/include/xen/iommu.h +@@ -31,7 +31,7 @@ extern bool_t force_iommu, iommu_verbose + extern bool_t iommu_workaround_bios_bug, iommu_passthrough; + extern bool_t iommu_snoop, iommu_qinval, iommu_intremap; + extern bool_t iommu_hap_pt_share; +-extern bool_t amd_iommu_debug; ++extern bool_t iommu_debug; + extern bool_t amd_iommu_perdev_intremap; + + extern struct rangeset *mmio_ro_ranges; diff --git a/23574-x86-dom0-compressed-ELF.patch b/23574-x86-dom0-compressed-ELF.patch new file mode 100644 index 0000000..92bcbb3 --- /dev/null +++ b/23574-x86-dom0-compressed-ELF.patch @@ -0,0 +1,123 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1308825237 -3600 +# Node ID d7644abc218d3232b9d957ce94fc4b4bcc1f456e +# Parent 584c2e5e03d96f912cdfe90f8e9f910d5d661706 +x86: allow Dom0 image to be compressed ELF + +Rather than being able to decompress only the payloads of bzImage +containers, extend the logic to also decompress simple compressed ELF +images. At once, allow uncompressed bzImage payloads. + +This is a prerequisite for native EFI booting support (where, in the +absence of a capable secondary boot loader, the image will always be +in compressed form). + +Signed-off-by: Jan Beulich + +--- a/xen/arch/x86/bzimage.c ++++ b/xen/arch/x86/bzimage.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + + #define HEAPORDER 3 +@@ -199,25 +200,36 @@ static __init int bzimage_check(struct s + return 1; + } + +-int __init bzimage_headroom(char *image_start, unsigned long image_length) ++static unsigned long __initdata orig_image_len; ++ ++unsigned long __init bzimage_headroom(char *image_start, ++ unsigned long image_length) + { + struct setup_header *hdr = (struct setup_header *)image_start; +- char *img; +- int err, headroom; ++ int err; ++ unsigned long headroom; + + err = bzimage_check(hdr, image_length); +- if (err < 1) ++ if ( err < 0 ) + return 0; + +- img = image_start + (hdr->setup_sects+1) * 512; +- img += hdr->payload_offset; ++ if ( err > 0 ) ++ { ++ image_start += (hdr->setup_sects + 1) * 512 + hdr->payload_offset; ++ image_length = hdr->payload_length; ++ } ++ ++ if ( elf_is_elfbinary(image_start) ) ++ return 0; + +- headroom = output_length(img, hdr->payload_length); +- if (gzip_check(img, hdr->payload_length)) { ++ orig_image_len = image_length; ++ headroom = output_length(image_start, image_length); ++ if (gzip_check(image_start, image_length)) ++ { + headroom += headroom >> 12; /* Add 8 bytes for every 32K input block */ + headroom += (32768 + 18); /* Add 32K + 18 bytes of extra headroom */ + } else +- headroom += hdr->payload_length; ++ headroom += image_length; + headroom = (headroom + 4095) & ~4095; + + return headroom; +@@ -229,18 +241,24 @@ int __init bzimage_parse(char *image_bas + int err = bzimage_check(hdr, *image_len); + unsigned long output_len; + +- if (err < 1) ++ if ( err < 0 ) + return err; + ++ if ( err > 0 ) ++ { ++ *image_start += (hdr->setup_sects + 1) * 512 + hdr->payload_offset; ++ *image_len = hdr->payload_length; ++ } ++ ++ if ( elf_is_elfbinary(*image_start) ) ++ return 0; ++ + BUG_ON(!(image_base < *image_start)); + +- *image_start += (hdr->setup_sects+1) * 512; +- *image_start += hdr->payload_offset; +- *image_len = hdr->payload_length; +- output_len = output_length(*image_start, *image_len); ++ output_len = output_length(*image_start, orig_image_len); + +- if ( (err = perform_gunzip(image_base, *image_start, *image_len)) > 0 ) +- err = decompress(*image_start, *image_len, image_base); ++ if ( (err = perform_gunzip(image_base, *image_start, orig_image_len)) > 0 ) ++ err = decompress(*image_start, orig_image_len, image_base); + + if ( !err ) + { +--- a/xen/include/asm-x86/bzimage.h ++++ b/xen/include/asm-x86/bzimage.h +@@ -4,10 +4,9 @@ + #include + #include + +-int __init bzimage_headroom(char *image_start, unsigned long image_length); ++unsigned long bzimage_headroom(char *image_start, unsigned long image_length); + +-int __init bzimage_parse(char *image_base, +- char **image_start, +- unsigned long *image_len); ++int bzimage_parse(char *image_base, char **image_start, ++ unsigned long *image_len); + + #endif /* __X86_BZIMAGE_H__ */ diff --git a/23575-x86-DMI.patch b/23575-x86-DMI.patch new file mode 100644 index 0000000..19124e2 --- /dev/null +++ b/23575-x86-DMI.patch @@ -0,0 +1,154 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1308825280 -3600 +# Node ID 4d9598a6a7777c50e109d7e2eb6d1cb28bcb4509 +# Parent d7644abc218d3232b9d957ce94fc4b4bcc1f456e +x86/DMI: use proper structures instead of byte offsets + +Besides being (in my eyes) desirable cleanup, this at once represents +another prerequisite for native EFI booting support. + +Signed-off-by: Jan Beulich + +--- a/xen/arch/x86/dmi_scan.c ++++ b/xen/arch/x86/dmi_scan.c +@@ -10,11 +10,31 @@ + #include + #include + +-#define bt_ioremap(b,l) ((u8 *)__acpi_map_table(b,l)) ++#define bt_ioremap(b,l) ((void *)__acpi_map_table(b,l)) + #define bt_iounmap(b,l) ((void)0) + #define memcpy_fromio memcpy + #define alloc_bootmem(l) xmalloc_bytes(l) + ++struct dmi_eps { ++ char anchor[5]; /* "_DMI_" */ ++ u8 checksum; ++ u16 size; ++ u32 address; ++ u16 num_structures; ++ u8 revision; ++} __attribute__((packed)); ++ ++struct smbios_eps { ++ char anchor[4]; /* "_SM_" */ ++ u8 checksum; ++ u8 length; ++ u8 major, minor; ++ u16 max_size; ++ u8 revision; ++ u8 _rsrvd_[5]; ++ struct dmi_eps dmi; ++} __attribute__((packed)); ++ + struct dmi_header + { + u8 type; +@@ -90,62 +110,70 @@ static int __init dmi_table(u32 base, in + } + + +-inline static int __init dmi_checksum(u8 *buf) ++static inline bool_t __init dmi_checksum(const void __iomem *buf, ++ unsigned int len) + { +- u8 sum=0; +- int a; ++ u8 sum = 0; ++ const u8 *p = buf; ++ unsigned int a; + +- for(a=0; a<15; a++) +- sum+=buf[a]; +- return (sum==0); ++ for (a = 0; a < len; a++) ++ sum += p[a]; ++ return sum == 0; + } + + int __init dmi_get_table(u32 *base, u32 *len) + { +- u8 buf[15]; ++ struct dmi_eps eps; + char __iomem *p, *q; + + p = maddr_to_virt(0xF0000); + for (q = p; q < p + 0x10000; q += 16) { +- memcpy_fromio(buf, q, 15); +- if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) { +- *base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; +- *len=buf[7]<<8|buf[6]; ++ memcpy_fromio(&eps, q, 15); ++ if (memcmp(eps.anchor, "_DMI_", 5) == 0 && ++ dmi_checksum(&eps, sizeof(eps))) { ++ *base = eps.address; ++ *len = eps.size; + return 0; + } + } + return -1; + } + ++static int __init _dmi_iterate(const struct dmi_eps *dmi, ++ const struct smbios_eps __iomem *smbios, ++ void (*decode)(struct dmi_header *)) ++{ ++ u16 num = dmi->num_structures; ++ u16 len = dmi->size; ++ u32 base = dmi->address; ++ ++ /* ++ * DMI version 0.0 means that the real version is taken from ++ * the SMBIOS version, which we may not know at this point. ++ */ ++ if (dmi->revision) ++ printk(KERN_INFO "DMI %d.%d present.\n", ++ dmi->revision >> 4, dmi->revision & 0x0f); ++ else if (!smbios) ++ printk(KERN_INFO "DMI present.\n"); ++ dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", ++ num, len)); ++ dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base)); ++ return dmi_table(base, len, num, decode); ++} ++ + static int __init dmi_iterate(void (*decode)(struct dmi_header *)) + { +- u8 buf[15]; ++ struct dmi_eps eps; + char __iomem *p, *q; + + p = maddr_to_virt(0xF0000); + for (q = p; q < p + 0x10000; q += 16) { +- memcpy_fromio(buf, q, 15); +- if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) { +- u16 num=buf[13]<<8|buf[12]; +- u16 len=buf[7]<<8|buf[6]; +- u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; +- +- /* +- * DMI version 0.0 means that the real version is taken from +- * the SMBIOS version, which we don't know at this point. +- */ +- if(buf[14]!=0) +- printk(KERN_INFO "DMI %d.%d present.\n", +- buf[14]>>4, buf[14]&0x0F); +- else +- printk(KERN_INFO "DMI present.\n"); +- dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", +- num, len)); +- dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", +- base)); +- if(dmi_table(base,len, num, decode)==0) +- return 0; +- } ++ memcpy_fromio(&eps, q, sizeof(eps)); ++ if (memcmp(eps.anchor, "_DMI_", 5) == 0 && ++ dmi_checksum(&eps, sizeof(eps))) ++ return _dmi_iterate(&eps, NULL, decode); + } + return -1; + } diff --git a/23610-x86-topology-info.patch b/23610-x86-topology-info.patch new file mode 100644 index 0000000..7925ac2 --- /dev/null +++ b/23610-x86-topology-info.patch @@ -0,0 +1,212 @@ +References: fate#309894 + +# HG changeset patch +# User Wei Huang +# Date 1309248811 -3600 +# Node ID 87c2013c2aa2d4874f892507e6cc7b52219a3acf +# Parent 819c315a919daec434f80ffb6e790ac492cbd2a7 +x86: consolidate cpu_core_id and phys_proc_id into cpuinfo_x86 struct + +This patch moves cpu_core_id and phys_proc_id into cpuinfo_x86 +structure. This is similar to upstream Linux kernel's approach. + +Signed-off-by: Wei Huang + +--- a/xen/arch/x86/cpu/amd.c ++++ b/xen/arch/x86/cpu/amd.c +@@ -579,11 +579,11 @@ static void __devinit init_amd(struct cp + while ((1 << bits) < c->x86_max_cores) + bits++; + } +- cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<>= bits; ++ c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; + if (opt_cpu_info) + printk("CPU %d(%d) -> Core %d\n", +- cpu, c->x86_max_cores, cpu_core_id[cpu]); ++ cpu, c->x86_max_cores, c->cpu_core_id); + } + #endif + +--- a/xen/arch/x86/cpu/common.c ++++ b/xen/arch/x86/cpu/common.c +@@ -326,7 +326,7 @@ void __cpuinit generic_identify(struct c + early_intel_workaround(c); + + #ifdef CONFIG_X86_HT +- phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff; ++ c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; + #endif + } + +@@ -362,6 +362,8 @@ void __cpuinit identify_cpu(struct cpuin + c->x86_max_cores = 1; + c->x86_num_siblings = 1; + c->x86_clflush_size = 0; ++ c->phys_proc_id = BAD_APICID; ++ c->cpu_core_id = BAD_APICID; + memset(&c->x86_capability, 0, sizeof c->x86_capability); + + if (!have_cpuid_p()) { +@@ -510,7 +512,6 @@ void __cpuinit detect_extended_topology( + unsigned int ht_mask_width, core_plus_mask_width; + unsigned int core_select_mask, core_level_siblings; + unsigned int initial_apicid; +- int cpu = smp_processor_id(); + + if ( c->cpuid_level < 0xb ) + return; +@@ -545,9 +546,9 @@ void __cpuinit detect_extended_topology( + + core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; + +- cpu_core_id[cpu] = phys_pkg_id(initial_apicid, ht_mask_width) ++ c->cpu_core_id = phys_pkg_id(initial_apicid, ht_mask_width) + & core_select_mask; +- phys_proc_id[cpu] = phys_pkg_id(initial_apicid, core_plus_mask_width); ++ c->phys_proc_id = phys_pkg_id(initial_apicid, core_plus_mask_width); + + c->apicid = phys_pkg_id(initial_apicid, 0); + c->x86_max_cores = (core_level_siblings / c->x86_num_siblings); +@@ -555,10 +556,10 @@ void __cpuinit detect_extended_topology( + if ( opt_cpu_info ) + { + printk("CPU: Physical Processor ID: %d\n", +- phys_proc_id[cpu]); ++ c->phys_proc_id); + if ( c->x86_max_cores > 1 ) + printk("CPU: Processor Core ID: %d\n", +- cpu_core_id[cpu]); ++ c->cpu_core_id); + } + } + +@@ -567,7 +568,6 @@ void __cpuinit detect_ht(struct cpuinfo_ + { + u32 eax, ebx, ecx, edx; + int index_msb, core_bits; +- int cpu = smp_processor_id(); + + cpuid(1, &eax, &ebx, &ecx, &edx); + +@@ -590,11 +590,11 @@ void __cpuinit detect_ht(struct cpuinfo_ + } + + index_msb = get_count_order(c->x86_num_siblings); +- phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); ++ c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); + + if (opt_cpu_info) + printk("CPU: Physical Processor ID: %d\n", +- phys_proc_id[cpu]); ++ c->phys_proc_id); + + c->x86_num_siblings = c->x86_num_siblings / c->x86_max_cores; + +@@ -602,12 +602,12 @@ void __cpuinit detect_ht(struct cpuinfo_ + + core_bits = get_count_order(c->x86_max_cores); + +- cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & ++ c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & + ((1 << core_bits) - 1); + + if (opt_cpu_info && c->x86_max_cores > 1) + printk("CPU: Processor Core ID: %d\n", +- cpu_core_id[cpu]); ++ c->cpu_core_id); + } + } + #endif +--- a/xen/arch/x86/cpu/mcheck/mce.c ++++ b/xen/arch/x86/cpu/mcheck/mce.c +@@ -1041,9 +1041,9 @@ void x86_mc_get_cpu_info(unsigned cpu, u + if (nthreads != NULL) + *nthreads = 1; + } else { +- *chipid = phys_proc_id[cpu]; ++ *chipid = c->phys_proc_id; + if (c->x86_max_cores > 1) +- *coreid = cpu_core_id[cpu]; ++ *coreid = c->cpu_core_id; + else + *coreid = 0; + *threadid = c->apicid & ((1 << (c->x86_num_siblings - 1)) - 1); +--- a/xen/arch/x86/smpboot.c ++++ b/xen/arch/x86/smpboot.c +@@ -52,12 +52,6 @@ + /* Set if we find a B stepping CPU */ + static int smp_b_stepping; + +-/* Package ID of each logical CPU */ +-int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; +- +-/* Core ID of each logical CPU */ +-int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; +- + /* representing HT siblings of each logical CPU */ + DEFINE_PER_CPU_READ_MOSTLY(cpumask_t, cpu_sibling_map); + /* representing HT and core siblings of each logical CPU */ +@@ -258,8 +252,8 @@ static void set_cpu_sibling_map(int cpu) + { + for_each_cpu_mask ( i, cpu_sibling_setup_map ) + { +- if ( (phys_proc_id[cpu] == phys_proc_id[i]) && +- (cpu_core_id[cpu] == cpu_core_id[i]) ) ++ if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && ++ (c[cpu].cpu_core_id == c[i].cpu_core_id) ) + { + cpu_set(i, per_cpu(cpu_sibling_map, cpu)); + cpu_set(cpu, per_cpu(cpu_sibling_map, i)); +@@ -282,7 +276,7 @@ static void set_cpu_sibling_map(int cpu) + + for_each_cpu_mask ( i, cpu_sibling_setup_map ) + { +- if ( phys_proc_id[cpu] == phys_proc_id[i] ) ++ if ( c[cpu].phys_proc_id == c[i].phys_proc_id ) + { + cpu_set(i, per_cpu(cpu_core_map, cpu)); + cpu_set(cpu, per_cpu(cpu_core_map, i)); +@@ -843,8 +837,8 @@ remove_siblinginfo(int cpu) + cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); + cpus_clear(per_cpu(cpu_sibling_map, cpu)); + cpus_clear(per_cpu(cpu_core_map, cpu)); +- phys_proc_id[cpu] = BAD_APICID; +- cpu_core_id[cpu] = BAD_APICID; ++ c[cpu].phys_proc_id = BAD_APICID; ++ c[cpu].cpu_core_id = BAD_APICID; + cpu_clear(cpu, cpu_sibling_setup_map); + } + +--- a/xen/include/asm-x86/processor.h ++++ b/xen/include/asm-x86/processor.h +@@ -175,6 +175,8 @@ struct cpuinfo_x86 { + __u32 x86_max_cores; /* cpuid returned max cores value */ + __u32 booted_cores; /* number of cores as seen by OS */ + __u32 x86_num_siblings; /* cpuid logical cpus per chip value */ ++ int phys_proc_id; /* package ID of each logical CPU */ ++ int cpu_core_id; /* core ID of each logical CPU*/ + __u32 apicid; + unsigned short x86_clflush_size; + } __cacheline_aligned; +@@ -194,8 +196,6 @@ extern struct cpuinfo_x86 cpu_data[]; + #endif + + extern u64 host_pat; +-extern int phys_proc_id[NR_CPUS]; +-extern int cpu_core_id[NR_CPUS]; + extern bool_t opt_cpu_info; + + /* Maximum width of physical addresses supported by the hardware */ +@@ -215,8 +215,8 @@ extern void detect_ht(struct cpuinfo_x86 + static always_inline void detect_ht(struct cpuinfo_x86 *c) {} + #endif + +-#define cpu_to_core(_cpu) (cpu_core_id[_cpu]) +-#define cpu_to_socket(_cpu) (phys_proc_id[_cpu]) ++#define cpu_to_core(_cpu) (cpu_data[_cpu].cpu_core_id) ++#define cpu_to_socket(_cpu) (cpu_data[_cpu].phys_proc_id) + + /* + * Generic CPUID function diff --git a/23611-amd-fam15-topology.patch b/23611-amd-fam15-topology.patch new file mode 100644 index 0000000..057f42c --- /dev/null +++ b/23611-amd-fam15-topology.patch @@ -0,0 +1,168 @@ +References: fate#309894 + +# HG changeset patch +# User Wei Huang +# Date 1309248833 -3600 +# Node ID c2c12b2dafb5b1d3bfcc4c05a60ca4f9051c90e7 +# Parent 87c2013c2aa2d4874f892507e6cc7b52219a3acf +x86: AMD core-pair topology detection code + +This patch is to support core-pair topology introduced by AMD CPUs, +which introduces a new concept of [core, compute unit]. There is a new +feature bit for topology extension in CPUID:0x80000001. Also a new +CPUID 0x8000001E is introduced for CPU topology enumeration. This +patch collects the sibling information from the new CPUID and will be +stored in the sibling map in Xen hypervisor. + +Signed-off-by: Wei Huang + +--- a/xen/arch/x86/cpu/amd.c ++++ b/xen/arch/x86/cpu/amd.c +@@ -344,6 +344,49 @@ static void check_syscfg_dram_mod_en(voi + wrmsrl(MSR_K8_SYSCFG, syscfg); + } + ++static void __devinit amd_get_topology(struct cpuinfo_x86 *c) ++{ ++#ifdef CONFIG_X86_HT ++ int cpu; ++ unsigned bits; ++ ++ if (c->x86_max_cores <= 1) ++ return; ++ /* ++ * On a AMD multi core setup the lower bits of the APIC id ++ * distingush the cores. ++ */ ++ cpu = smp_processor_id(); ++ bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; ++ ++ if (bits == 0) { ++ while ((1 << bits) < c->x86_max_cores) ++ bits++; ++ } ++ ++ /* Low order bits define the core id */ ++ c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; ++ /* Collect compute unit ID if available */ ++ if (cpu_has(c, X86_FEATURE_TOPOEXT)) { ++ u32 eax, ebx, ecx, edx; ++ ++ cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); ++ c->compute_unit_id = ebx & 0xFF; ++ c->x86_num_siblings = ((ebx >> 8) & 0x3) + 1; ++ } ++ ++ if (opt_cpu_info) ++ printk("CPU %d(%d) -> Processor %d, %s %d\n", ++ cpu, c->x86_max_cores, c->phys_proc_id, ++ cpu_has(c, X86_FEATURE_TOPOEXT) ? "Compute Unit" : ++ "Core", ++ cpu_has(c, X86_FEATURE_TOPOEXT) ? c->compute_unit_id : ++ c->cpu_core_id); ++#endif ++} ++ + static void __devinit init_amd(struct cpuinfo_x86 *c) + { + u32 l, h; +@@ -566,26 +609,7 @@ static void __devinit init_amd(struct cp + } + } + +-#ifdef CONFIG_X86_HT +- /* +- * On a AMD multi core setup the lower bits of the APIC id +- * distingush the cores. +- */ +- if (c->x86_max_cores > 1) { +- int cpu = smp_processor_id(); +- unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf; +- +- if (bits == 0) { +- while ((1 << bits) < c->x86_max_cores) +- bits++; +- } +- c->cpu_core_id = c->phys_proc_id & ((1<phys_proc_id >>= bits; +- if (opt_cpu_info) +- printk("CPU %d(%d) -> Core %d\n", +- cpu, c->x86_max_cores, c->cpu_core_id); +- } +-#endif ++ amd_get_topology(c); + + /* Pointless to use MWAIT on Family10 as it does not deep sleep. */ + if (c->x86 >= 0x10 && !force_mwait) +--- a/xen/arch/x86/cpu/common.c ++++ b/xen/arch/x86/cpu/common.c +@@ -364,6 +364,7 @@ void __cpuinit identify_cpu(struct cpuin + c->x86_clflush_size = 0; + c->phys_proc_id = BAD_APICID; + c->cpu_core_id = BAD_APICID; ++ c->compute_unit_id = BAD_APICID; + memset(&c->x86_capability, 0, sizeof c->x86_capability); + + if (!have_cpuid_p()) { +--- a/xen/arch/x86/smpboot.c ++++ b/xen/arch/x86/smpboot.c +@@ -241,6 +241,14 @@ static int booting_cpu; + /* CPUs for which sibling maps can be computed. */ + static cpumask_t cpu_sibling_setup_map; + ++static void link_thread_siblings(int cpu1, int cpu2) ++{ ++ cpu_set(cpu1, per_cpu(cpu_sibling_map, cpu2)); ++ cpu_set(cpu2, per_cpu(cpu_sibling_map, cpu1)); ++ cpu_set(cpu1, per_cpu(cpu_core_map, cpu2)); ++ cpu_set(cpu2, per_cpu(cpu_core_map, cpu1)); ++} ++ + static void set_cpu_sibling_map(int cpu) + { + int i; +@@ -252,13 +260,13 @@ static void set_cpu_sibling_map(int cpu) + { + for_each_cpu_mask ( i, cpu_sibling_setup_map ) + { +- if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && +- (c[cpu].cpu_core_id == c[i].cpu_core_id) ) +- { +- cpu_set(i, per_cpu(cpu_sibling_map, cpu)); +- cpu_set(cpu, per_cpu(cpu_sibling_map, i)); +- cpu_set(i, per_cpu(cpu_core_map, cpu)); +- cpu_set(cpu, per_cpu(cpu_core_map, i)); ++ if ( cpu_has(c, X86_FEATURE_TOPOEXT) ) { ++ if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && ++ (c[cpu].compute_unit_id == c[i].compute_unit_id) ) ++ link_thread_siblings(cpu, i); ++ } else if ( (c[cpu].phys_proc_id == c[i].phys_proc_id) && ++ (c[cpu].cpu_core_id == c[i].cpu_core_id) ) { ++ link_thread_siblings(cpu, i); + } + } + } +@@ -839,6 +847,7 @@ remove_siblinginfo(int cpu) + cpus_clear(per_cpu(cpu_core_map, cpu)); + c[cpu].phys_proc_id = BAD_APICID; + c[cpu].cpu_core_id = BAD_APICID; ++ c[cpu].compute_unit_id = BAD_APICID; + cpu_clear(cpu, cpu_sibling_setup_map); + } + +--- a/xen/include/asm-x86/processor.h ++++ b/xen/include/asm-x86/processor.h +@@ -175,9 +175,10 @@ struct cpuinfo_x86 { + __u32 x86_max_cores; /* cpuid returned max cores value */ + __u32 booted_cores; /* number of cores as seen by OS */ + __u32 x86_num_siblings; /* cpuid logical cpus per chip value */ ++ __u32 apicid; + int phys_proc_id; /* package ID of each logical CPU */ + int cpu_core_id; /* core ID of each logical CPU*/ +- __u32 apicid; ++ int compute_unit_id; /* AMD compute unit ID of each logical CPU */ + unsigned short x86_clflush_size; + } __cacheline_aligned; + diff --git a/23613-EFI-headers.patch b/23613-EFI-headers.patch new file mode 100644 index 0000000..1e02f66 --- /dev/null +++ b/23613-EFI-headers.patch @@ -0,0 +1,2725 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1309249070 -3600 +# Node ID b8d22c658bd213bf9da0a9d05312b63524652daf +# Parent 6c7a23e08a041a1943b60ed0c4473112aa15c91f +x86-64: EFI header files + +Taken from gnu-efi-3.0k (slightly edited). + +Signed-off-by: Jan Beulich + +--- /dev/null ++++ b/xen/include/asm-x86/efibind.h +@@ -0,0 +1,6 @@ ++#include ++#if defined(__i386__) ++# include ++#elif defined(__x86_64__) ++# include ++#endif +--- /dev/null ++++ b/xen/include/asm-x86/x86_64/efibind.h +@@ -0,0 +1,276 @@ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ efefind.h ++ ++Abstract: ++ ++ EFI to compile bindings ++ ++ ++ ++ ++Revision History ++ ++--*/ ++ ++#ifndef __GNUC__ ++#pragma pack() ++#endif ++ ++// ++// Basic int types of various widths ++// ++ ++#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) ++ ++ // No ANSI C 1999/2000 stdint.h integer width declarations ++ ++ #if defined(_MSC_EXTENSIONS) ++ ++ // Use Microsoft C compiler integer width declarations ++ ++ typedef unsigned __int64 uint64_t; ++ typedef __int64 int64_t; ++ typedef unsigned __int32 uint32_t; ++ typedef __int32 int32_t; ++ typedef unsigned short uint16_t; ++ typedef short int16_t; ++ typedef unsigned char uint8_t; ++ typedef char int8_t; ++ #elif defined(__GNUC__) ++ typedef unsigned long long uint64_t __attribute__((aligned (8))); ++ typedef long long int64_t __attribute__((aligned (8))); ++ typedef unsigned int uint32_t; ++ typedef int int32_t; ++ typedef unsigned short uint16_t; ++ typedef short int16_t; ++ typedef unsigned char uint8_t; ++ typedef char int8_t; ++ #elif defined(UNIX_LP64) ++ ++ /* Use LP64 programming model from C_FLAGS for integer width declarations */ ++ ++ typedef unsigned long uint64_t; ++ typedef long int64_t; ++ typedef unsigned int uint32_t; ++ typedef int int32_t; ++ typedef unsigned short uint16_t; ++ typedef short int16_t; ++ typedef unsigned char uint8_t; ++ typedef char int8_t; ++ #else ++ ++ /* Assume P64 programming model from C_FLAGS for integer width declarations */ ++ ++ typedef unsigned long long uint64_t __attribute__((aligned (8))); ++ typedef long long int64_t __attribute__((aligned (8))); ++ typedef unsigned int uint32_t; ++ typedef int int32_t; ++ typedef unsigned short uint16_t; ++ typedef short int16_t; ++ typedef unsigned char uint8_t; ++ typedef char int8_t; ++ #endif ++#endif ++ ++// ++// Basic EFI types of various widths ++// ++ ++#ifndef __WCHAR_TYPE__ ++# define __WCHAR_TYPE__ short ++#endif ++ ++typedef uint64_t UINT64; ++typedef int64_t INT64; ++ ++#ifndef _BASETSD_H_ ++ typedef uint32_t UINT32; ++ typedef int32_t INT32; ++#endif ++ ++typedef uint16_t UINT16; ++typedef int16_t INT16; ++typedef uint8_t UINT8; ++typedef int8_t INT8; ++typedef __WCHAR_TYPE__ WCHAR; ++ ++#undef VOID ++#define VOID void ++ ++ ++typedef int64_t INTN; ++typedef uint64_t UINTN; ++ ++#ifdef EFI_NT_EMULATOR ++ #define POST_CODE(_Data) ++#else ++ #ifdef EFI_DEBUG ++#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al ++ #else ++ #define POST_CODE(_Data) ++ #endif ++#endif ++ ++#define EFIERR(a) (0x8000000000000000 | a) ++#define EFI_ERROR_MASK 0x8000000000000000 ++#define EFIERR_OEM(a) (0xc000000000000000 | a) ++ ++ ++#define BAD_POINTER 0xFBFBFBFBFBFBFBFB ++#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF ++ ++#ifdef EFI_NT_EMULATOR ++ #define BREAKPOINT() __asm { int 3 } ++#else ++ #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 ++#endif ++ ++// ++// Pointers must be aligned to these address to function ++// ++ ++#define MIN_ALIGNMENT_SIZE 4 ++ ++#define ALIGN_VARIABLE(Value ,Adjustment) \ ++ (UINTN)Adjustment = 0; \ ++ if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ ++ (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ ++ Value = (UINTN)Value + (UINTN)Adjustment ++ ++ ++// ++// Define macros to build data structure signatures from characters. ++// ++ ++#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) ++#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) ++#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) ++// ++// To export & import functions in the EFI emulator environment ++// ++ ++#ifdef EFI_NT_EMULATOR ++ #define EXPORTAPI __declspec( dllexport ) ++#else ++ #define EXPORTAPI ++#endif ++ ++ ++// ++// EFIAPI - prototype calling convention for EFI function pointers ++// BOOTSERVICE - prototype for implementation of a boot service interface ++// RUNTIMESERVICE - prototype for implementation of a runtime service interface ++// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service ++// RUNTIME_CODE - pragma macro for declaring runtime code ++// ++ ++#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options ++ #ifdef _MSC_EXTENSIONS ++ #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler ++ #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) ++ #define EFIAPI __attribute__((__ms_abi__)) // Force Microsoft ABI ++ #else ++ #define EFIAPI // Substitute expresion to force C calling convention ++ #endif ++#endif ++ ++#define BOOTSERVICE ++//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a ++//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a ++#define RUNTIMESERVICE ++#define RUNTIMEFUNCTION ++ ++ ++#define RUNTIME_CODE(a) alloc_text("rtcode", a) ++#define BEGIN_RUNTIME_DATA() data_seg("rtdata") ++#define END_RUNTIME_DATA() data_seg("") ++ ++#define VOLATILE volatile ++ ++#define MEMORY_FENCE() ++ ++#ifdef EFI_NT_EMULATOR ++ ++// ++// To help ensure proper coding of integrated drivers, they are ++// compiled as DLLs. In NT they require a dll init entry pointer. ++// The macro puts a stub entry point into the DLL so it will load. ++// ++ ++#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ ++ UINTN \ ++ __stdcall \ ++ _DllMainCRTStartup ( \ ++ UINTN Inst, \ ++ UINTN reason_for_call, \ ++ VOID *rserved \ ++ ) \ ++ { \ ++ return 1; \ ++ } \ ++ \ ++ int \ ++ EXPORTAPI \ ++ __cdecl \ ++ InitializeDriver ( \ ++ void *ImageHandle, \ ++ void *SystemTable \ ++ ) \ ++ { \ ++ return InitFunction(ImageHandle, SystemTable); \ ++ } ++ ++ ++ #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ ++ (_if)->LoadInternal(type, name, NULL) ++ ++#else // EFI_NT_EMULATOR ++ ++// ++// When build similiar to FW, then link everything together as ++// one big module. ++// ++ ++ #define EFI_DRIVER_ENTRY_POINT(InitFunction) ++ ++ #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ ++ (_if)->LoadInternal(type, name, entry) ++ ++#endif // EFI_FW_NT ++ ++// ++// Some compilers don't support the forward reference construct: ++// typedef struct XXXXX ++// ++// The following macro provide a workaround for such cases. ++// ++#ifdef NO_INTERFACE_DECL ++#define INTERFACE_DECL(x) ++#else ++#ifdef __GNUC__ ++#define INTERFACE_DECL(x) struct x ++#else ++#define INTERFACE_DECL(x) typedef struct x ++#endif ++#endif ++ ++#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) ++#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) ++#else ++/* for x86_64, EFI_FUNCTION_WRAPPER must be defined */ ++#ifdef EFI_FUNCTION_WRAPPER ++UINTN uefi_call_wrapper(void *func, unsigned long va_num, ...); ++#else ++#error "EFI_FUNCTION_WRAPPER must be defined for x86_64 architecture" ++#endif ++#endif ++ ++#ifdef _MSC_EXTENSIONS ++#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP ++#endif ++ +--- /dev/null ++++ b/xen/include/efi/efiapi.h +@@ -0,0 +1,718 @@ ++#ifndef _EFI_API_H ++#define _EFI_API_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ efiapi.h ++ ++Abstract: ++ ++ Global EFI runtime & boot service interfaces ++ ++ ++ ++ ++Revision History ++ ++--*/ ++ ++// ++// EFI Specification Revision ++// ++ ++#define EFI_SPECIFICATION_MAJOR_REVISION 1 ++#define EFI_SPECIFICATION_MINOR_REVISION 02 ++ ++// ++// Declare forward referenced data structures ++// ++ ++INTERFACE_DECL(_EFI_SYSTEM_TABLE); ++ ++// ++// EFI Memory ++// ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_ALLOCATE_PAGES) ( ++ IN EFI_ALLOCATE_TYPE Type, ++ IN EFI_MEMORY_TYPE MemoryType, ++ IN UINTN NoPages, ++ OUT EFI_PHYSICAL_ADDRESS *Memory ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FREE_PAGES) ( ++ IN EFI_PHYSICAL_ADDRESS Memory, ++ IN UINTN NoPages ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_MEMORY_MAP) ( ++ IN OUT UINTN *MemoryMapSize, ++ IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, ++ OUT UINTN *MapKey, ++ OUT UINTN *DescriptorSize, ++ OUT UINT32 *DescriptorVersion ++ ); ++ ++#define NextMemoryDescriptor(Ptr,Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size)) ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_ALLOCATE_POOL) ( ++ IN EFI_MEMORY_TYPE PoolType, ++ IN UINTN Size, ++ OUT VOID **Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FREE_POOL) ( ++ IN VOID *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) ( ++ IN UINTN MemoryMapSize, ++ IN UINTN DescriptorSize, ++ IN UINT32 DescriptorVersion, ++ IN EFI_MEMORY_DESCRIPTOR *VirtualMap ++ ); ++ ++ ++#define EFI_OPTIONAL_PTR 0x00000001 ++#define EFI_INTERNAL_FNC 0x00000002 // Pointer to internal runtime fnc ++#define EFI_INTERNAL_PTR 0x00000004 // Pointer to internal runtime data ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CONVERT_POINTER) ( ++ IN UINTN DebugDisposition, ++ IN OUT VOID **Address ++ ); ++ ++ ++// ++// EFI Events ++// ++ ++ ++ ++#define EVT_TIMER 0x80000000 ++#define EVT_RUNTIME 0x40000000 ++#define EVT_RUNTIME_CONTEXT 0x20000000 ++ ++#define EVT_NOTIFY_WAIT 0x00000100 ++#define EVT_NOTIFY_SIGNAL 0x00000200 ++ ++#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 ++#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 ++ ++#define EVT_EFI_SIGNAL_MASK 0x000000FF ++#define EVT_EFI_SIGNAL_MAX 2 ++ ++typedef ++VOID ++(EFIAPI *EFI_EVENT_NOTIFY) ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CREATE_EVENT) ( ++ IN UINT32 Type, ++ IN EFI_TPL NotifyTpl, ++ IN EFI_EVENT_NOTIFY NotifyFunction, ++ IN VOID *NotifyContext, ++ OUT EFI_EVENT *Event ++ ); ++ ++typedef enum { ++ TimerCancel, ++ TimerPeriodic, ++ TimerRelative, ++ TimerTypeMax ++} EFI_TIMER_DELAY; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_TIMER) ( ++ IN EFI_EVENT Event, ++ IN EFI_TIMER_DELAY Type, ++ IN UINT64 TriggerTime ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SIGNAL_EVENT) ( ++ IN EFI_EVENT Event ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_WAIT_FOR_EVENT) ( ++ IN UINTN NumberOfEvents, ++ IN EFI_EVENT *Event, ++ OUT UINTN *Index ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CLOSE_EVENT) ( ++ IN EFI_EVENT Event ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_CHECK_EVENT) ( ++ IN EFI_EVENT Event ++ ); ++ ++// ++// Task priority level ++// ++ ++#define TPL_APPLICATION 4 ++#define TPL_CALLBACK 8 ++#define TPL_NOTIFY 16 ++#define TPL_HIGH_LEVEL 31 ++ ++typedef ++EFI_TPL ++(EFIAPI *EFI_RAISE_TPL) ( ++ IN EFI_TPL NewTpl ++ ); ++ ++typedef ++VOID ++(EFIAPI *EFI_RESTORE_TPL) ( ++ IN EFI_TPL OldTpl ++ ); ++ ++ ++// ++// EFI platform varibles ++// ++ ++#define EFI_GLOBAL_VARIABLE \ ++ { 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} } ++ ++// Variable attributes ++#define EFI_VARIABLE_NON_VOLATILE 0x00000001 ++#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 ++#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 ++ ++// Variable size limitation ++#define EFI_MAXIMUM_VARIABLE_SIZE 1024 ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_VARIABLE) ( ++ IN CHAR16 *VariableName, ++ IN EFI_GUID *VendorGuid, ++ OUT UINT32 *Attributes OPTIONAL, ++ IN OUT UINTN *DataSize, ++ OUT VOID *Data ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME) ( ++ IN OUT UINTN *VariableNameSize, ++ IN OUT CHAR16 *VariableName, ++ IN OUT EFI_GUID *VendorGuid ++ ); ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_VARIABLE) ( ++ IN CHAR16 *VariableName, ++ IN EFI_GUID *VendorGuid, ++ IN UINT32 Attributes, ++ IN UINTN DataSize, ++ IN VOID *Data ++ ); ++ ++ ++// ++// EFI Time ++// ++ ++typedef struct { ++ UINT32 Resolution; // 1e-6 parts per million ++ UINT32 Accuracy; // hertz ++ BOOLEAN SetsToZero; // Set clears sub-second time ++} EFI_TIME_CAPABILITIES; ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_TIME) ( ++ OUT EFI_TIME *Time, ++ OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_TIME) ( ++ IN EFI_TIME *Time ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_WAKEUP_TIME) ( ++ OUT BOOLEAN *Enabled, ++ OUT BOOLEAN *Pending, ++ OUT EFI_TIME *Time ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_WAKEUP_TIME) ( ++ IN BOOLEAN Enable, ++ IN EFI_TIME *Time OPTIONAL ++ ); ++ ++ ++// ++// Image functions ++// ++ ++ ++// PE32+ Subsystem type for EFI images ++ ++#if !defined(IMAGE_SUBSYSTEM_EFI_APPLICATION) ++#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 ++#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 ++#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 ++#endif ++ ++// PE32+ Machine type for EFI images ++ ++#if !defined(EFI_IMAGE_MACHINE_IA32) ++#define EFI_IMAGE_MACHINE_IA32 0x014c ++#endif ++ ++#if !defined(EFI_IMAGE_MACHINE_IA64) ++#define EFI_IMAGE_MACHINE_IA64 0x0200 ++#endif ++ ++// Image Entry prototype ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IMAGE_ENTRY_POINT) ( ++ IN EFI_HANDLE ImageHandle, ++ IN struct _EFI_SYSTEM_TABLE *SystemTable ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IMAGE_LOAD) ( ++ IN BOOLEAN BootPolicy, ++ IN EFI_HANDLE ParentImageHandle, ++ IN EFI_DEVICE_PATH *FilePath, ++ IN VOID *SourceBuffer OPTIONAL, ++ IN UINTN SourceSize, ++ OUT EFI_HANDLE *ImageHandle ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IMAGE_START) ( ++ IN EFI_HANDLE ImageHandle, ++ OUT UINTN *ExitDataSize, ++ OUT CHAR16 **ExitData OPTIONAL ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_EXIT) ( ++ IN EFI_HANDLE ImageHandle, ++ IN EFI_STATUS ExitStatus, ++ IN UINTN ExitDataSize, ++ IN CHAR16 *ExitData OPTIONAL ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IMAGE_UNLOAD) ( ++ IN EFI_HANDLE ImageHandle ++ ); ++ ++ ++// Image handle ++#define LOADED_IMAGE_PROTOCOL \ ++ { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } ++ ++#define EFI_IMAGE_INFORMATION_REVISION 0x1000 ++typedef struct { ++ UINT32 Revision; ++ EFI_HANDLE ParentHandle; ++ struct _EFI_SYSTEM_TABLE *SystemTable; ++ ++ // Source location of image ++ EFI_HANDLE DeviceHandle; ++ EFI_DEVICE_PATH *FilePath; ++ VOID *Reserved; ++ ++ // Images load options ++ UINT32 LoadOptionsSize; ++ VOID *LoadOptions; ++ ++ // Location of where image was loaded ++ VOID *ImageBase; ++ UINT64 ImageSize; ++ EFI_MEMORY_TYPE ImageCodeType; ++ EFI_MEMORY_TYPE ImageDataType; ++ ++ // If the driver image supports a dynamic unload request ++ EFI_IMAGE_UNLOAD Unload; ++ ++} EFI_LOADED_IMAGE; ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_EXIT_BOOT_SERVICES) ( ++ IN EFI_HANDLE ImageHandle, ++ IN UINTN MapKey ++ ); ++ ++// ++// Misc ++// ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_STALL) ( ++ IN UINTN Microseconds ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_SET_WATCHDOG_TIMER) ( ++ IN UINTN Timeout, ++ IN UINT64 WatchdogCode, ++ IN UINTN DataSize, ++ IN CHAR16 *WatchdogData OPTIONAL ++ ); ++ ++ ++typedef enum { ++ EfiResetCold, ++ EfiResetWarm, ++ EfiResetShutdown ++} EFI_RESET_TYPE; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_RESET_SYSTEM) ( ++ IN EFI_RESET_TYPE ResetType, ++ IN EFI_STATUS ResetStatus, ++ IN UINTN DataSize, ++ IN CHAR16 *ResetData OPTIONAL ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT) ( ++ OUT UINT64 *Count ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT) ( ++ OUT UINT32 *HighCount ++ ); ++ ++// ++// Protocol handler functions ++// ++ ++typedef enum { ++ EFI_NATIVE_INTERFACE, ++ EFI_PCODE_INTERFACE ++} EFI_INTERFACE_TYPE; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE) ( ++ IN OUT EFI_HANDLE *Handle, ++ IN EFI_GUID *Protocol, ++ IN EFI_INTERFACE_TYPE InterfaceType, ++ IN VOID *Interface ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE) ( ++ IN EFI_HANDLE Handle, ++ IN EFI_GUID *Protocol, ++ IN VOID *OldInterface, ++ IN VOID *NewInterface ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE) ( ++ IN EFI_HANDLE Handle, ++ IN EFI_GUID *Protocol, ++ IN VOID *Interface ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_HANDLE_PROTOCOL) ( ++ IN EFI_HANDLE Handle, ++ IN EFI_GUID *Protocol, ++ OUT VOID **Interface ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) ( ++ IN EFI_GUID *Protocol, ++ IN EFI_EVENT Event, ++ OUT VOID **Registration ++ ); ++ ++typedef enum { ++ AllHandles, ++ ByRegisterNotify, ++ ByProtocol ++} EFI_LOCATE_SEARCH_TYPE; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_LOCATE_HANDLE) ( ++ IN EFI_LOCATE_SEARCH_TYPE SearchType, ++ IN EFI_GUID *Protocol OPTIONAL, ++ IN VOID *SearchKey OPTIONAL, ++ IN OUT UINTN *BufferSize, ++ OUT EFI_HANDLE *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_LOCATE_DEVICE_PATH) ( ++ IN EFI_GUID *Protocol, ++ IN OUT EFI_DEVICE_PATH **DevicePath, ++ OUT EFI_HANDLE *Device ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE) ( ++ IN EFI_GUID *Guid, ++ IN VOID *Table ++ ); ++ ++typedef VOID *EFI_RESERVED_SERVICE; ++ ++// ++// Standard EFI table header ++// ++ ++typedef struct _EFI_TABLE_HEARDER { ++ UINT64 Signature; ++ UINT32 Revision; ++ UINT32 HeaderSize; ++ UINT32 CRC32; ++ UINT32 Reserved; ++} EFI_TABLE_HEADER; ++ ++ ++// ++// EFI Runtime Serivces Table ++// ++ ++#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 ++#define EFI_RUNTIME_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) ++ ++typedef struct { ++ EFI_TABLE_HEADER Hdr; ++ ++ // ++ // Time services ++ // ++ ++ EFI_GET_TIME GetTime; ++ EFI_SET_TIME SetTime; ++ EFI_GET_WAKEUP_TIME GetWakeupTime; ++ EFI_SET_WAKEUP_TIME SetWakeupTime; ++ ++ // ++ // Virtual memory services ++ // ++ ++ EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; ++ EFI_CONVERT_POINTER ConvertPointer; ++ ++ // ++ // Variable serviers ++ // ++ ++ EFI_GET_VARIABLE GetVariable; ++ EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; ++ EFI_SET_VARIABLE SetVariable; ++ ++ // ++ // Misc ++ // ++ ++ EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; ++ EFI_RESET_SYSTEM ResetSystem; ++ ++} EFI_RUNTIME_SERVICES; ++ ++ ++// ++// EFI Boot Services Table ++// ++ ++#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 ++#define EFI_BOOT_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) ++ ++typedef struct _EFI_BOOT_SERVICES { ++ ++ EFI_TABLE_HEADER Hdr; ++ ++ // ++ // Task priority functions ++ // ++ ++ EFI_RAISE_TPL RaiseTPL; ++ EFI_RESTORE_TPL RestoreTPL; ++ ++ // ++ // Memory functions ++ // ++ ++ EFI_ALLOCATE_PAGES AllocatePages; ++ EFI_FREE_PAGES FreePages; ++ EFI_GET_MEMORY_MAP GetMemoryMap; ++ EFI_ALLOCATE_POOL AllocatePool; ++ EFI_FREE_POOL FreePool; ++ ++ // ++ // Event & timer functions ++ // ++ ++ EFI_CREATE_EVENT CreateEvent; ++ EFI_SET_TIMER SetTimer; ++ EFI_WAIT_FOR_EVENT WaitForEvent; ++ EFI_SIGNAL_EVENT SignalEvent; ++ EFI_CLOSE_EVENT CloseEvent; ++ EFI_CHECK_EVENT CheckEvent; ++ ++ // ++ // Protocol handler functions ++ // ++ ++ EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; ++ EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; ++ EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; ++ EFI_HANDLE_PROTOCOL HandleProtocol; ++ EFI_HANDLE_PROTOCOL PCHandleProtocol; ++ EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; ++ EFI_LOCATE_HANDLE LocateHandle; ++ EFI_LOCATE_DEVICE_PATH LocateDevicePath; ++ EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; ++ ++ // ++ // Image functions ++ // ++ ++ EFI_IMAGE_LOAD LoadImage; ++ EFI_IMAGE_START StartImage; ++ EFI_EXIT Exit; ++ EFI_IMAGE_UNLOAD UnloadImage; ++ EFI_EXIT_BOOT_SERVICES ExitBootServices; ++ ++ // ++ // Misc functions ++ // ++ ++ EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; ++ EFI_STALL Stall; ++ EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; ++ ++} EFI_BOOT_SERVICES; ++ ++ ++// ++// EFI Configuration Table and GUID definitions ++// ++ ++#define MPS_TABLE_GUID \ ++ { 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++#define ACPI_TABLE_GUID \ ++ { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++#define ACPI_20_TABLE_GUID \ ++ { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } ++ ++#define SMBIOS_TABLE_GUID \ ++ { 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++#define SAL_SYSTEM_TABLE_GUID \ ++ { 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++ ++typedef struct _EFI_CONFIGURATION_TABLE { ++ EFI_GUID VendorGuid; ++ VOID *VendorTable; ++} EFI_CONFIGURATION_TABLE; ++ ++ ++// ++// EFI System Table ++// ++ ++ ++ ++ ++#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 ++#define EFI_SYSTEM_TABLE_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) ++ ++typedef struct _EFI_SYSTEM_TABLE { ++ EFI_TABLE_HEADER Hdr; ++ ++ CHAR16 *FirmwareVendor; ++ UINT32 FirmwareRevision; ++ ++ EFI_HANDLE ConsoleInHandle; ++ SIMPLE_INPUT_INTERFACE *ConIn; ++ ++ EFI_HANDLE ConsoleOutHandle; ++ SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut; ++ ++ EFI_HANDLE StandardErrorHandle; ++ SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr; ++ ++ EFI_RUNTIME_SERVICES *RuntimeServices; ++ EFI_BOOT_SERVICES *BootServices; ++ ++ UINTN NumberOfTableEntries; ++ EFI_CONFIGURATION_TABLE *ConfigurationTable; ++ ++} EFI_SYSTEM_TABLE; ++ ++#endif ++ +--- /dev/null ++++ b/xen/include/efi/eficon.h +@@ -0,0 +1,302 @@ ++#ifndef _EFI_CON_H ++#define _EFI_CON_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ eficon.h ++ ++Abstract: ++ ++ EFI console protocols ++ ++ ++ ++Revision History ++ ++--*/ ++ ++// ++// Text output protocol ++// ++ ++#define SIMPLE_TEXT_OUTPUT_PROTOCOL \ ++ { 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++INTERFACE_DECL(_SIMPLE_TEXT_OUTPUT_INTERFACE); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_RESET) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN BOOLEAN ExtendedVerification ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_OUTPUT_STRING) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN CHAR16 *String ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_TEST_STRING) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN CHAR16 *String ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_QUERY_MODE) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN UINTN ModeNumber, ++ OUT UINTN *Columns, ++ OUT UINTN *Rows ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_SET_MODE) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN UINTN ModeNumber ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_SET_ATTRIBUTE) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN UINTN Attribute ++ ); ++ ++#define EFI_BLACK 0x00 ++#define EFI_BLUE 0x01 ++#define EFI_GREEN 0x02 ++#define EFI_CYAN (EFI_BLUE | EFI_GREEN) ++#define EFI_RED 0x04 ++#define EFI_MAGENTA (EFI_BLUE | EFI_RED) ++#define EFI_BROWN (EFI_GREEN | EFI_RED) ++#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) ++#define EFI_BRIGHT 0x08 ++#define EFI_DARKGRAY (EFI_BRIGHT) ++#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) ++#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) ++#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) ++#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) ++#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) ++#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) ++#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) ++ ++#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4)) ++ ++#define EFI_BACKGROUND_BLACK 0x00 ++#define EFI_BACKGROUND_BLUE 0x10 ++#define EFI_BACKGROUND_GREEN 0x20 ++#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) ++#define EFI_BACKGROUND_RED 0x40 ++#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) ++#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) ++#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_CLEAR_SCREEN) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN UINTN Column, ++ IN UINTN Row ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_TEXT_ENABLE_CURSOR) ( ++ IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, ++ IN BOOLEAN Enable ++ ); ++ ++typedef struct { ++ INT32 MaxMode; ++ // current settings ++ INT32 Mode; ++ INT32 Attribute; ++ INT32 CursorColumn; ++ INT32 CursorRow; ++ BOOLEAN CursorVisible; ++} SIMPLE_TEXT_OUTPUT_MODE; ++ ++typedef struct _SIMPLE_TEXT_OUTPUT_INTERFACE { ++ EFI_TEXT_RESET Reset; ++ ++ EFI_TEXT_OUTPUT_STRING OutputString; ++ EFI_TEXT_TEST_STRING TestString; ++ ++ EFI_TEXT_QUERY_MODE QueryMode; ++ EFI_TEXT_SET_MODE SetMode; ++ EFI_TEXT_SET_ATTRIBUTE SetAttribute; ++ ++ EFI_TEXT_CLEAR_SCREEN ClearScreen; ++ EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; ++ EFI_TEXT_ENABLE_CURSOR EnableCursor; ++ ++ // Current mode ++ SIMPLE_TEXT_OUTPUT_MODE *Mode; ++} SIMPLE_TEXT_OUTPUT_INTERFACE; ++ ++// ++// Define's for required EFI Unicode Box Draw character ++// ++ ++#define BOXDRAW_HORIZONTAL 0x2500 ++#define BOXDRAW_VERTICAL 0x2502 ++#define BOXDRAW_DOWN_RIGHT 0x250c ++#define BOXDRAW_DOWN_LEFT 0x2510 ++#define BOXDRAW_UP_RIGHT 0x2514 ++#define BOXDRAW_UP_LEFT 0x2518 ++#define BOXDRAW_VERTICAL_RIGHT 0x251c ++#define BOXDRAW_VERTICAL_LEFT 0x2524 ++#define BOXDRAW_DOWN_HORIZONTAL 0x252c ++#define BOXDRAW_UP_HORIZONTAL 0x2534 ++#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c ++ ++#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 ++#define BOXDRAW_DOUBLE_VERTICAL 0x2551 ++#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 ++#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 ++#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 ++ ++#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 ++#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 ++#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 ++ ++#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 ++#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 ++#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a ++ ++#define BOXDRAW_UP_LEFT_DOUBLE 0x255b ++#define BOXDRAW_UP_DOUBLE_LEFT 0x255c ++#define BOXDRAW_DOUBLE_UP_LEFT 0x255d ++ ++#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e ++#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f ++#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 ++ ++#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 ++#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 ++#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 ++ ++#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 ++#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 ++#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 ++ ++#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 ++#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 ++#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 ++ ++#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a ++#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b ++#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c ++ ++// ++// EFI Required Block Elements Code Chart ++// ++ ++#define BLOCKELEMENT_FULL_BLOCK 0x2588 ++#define BLOCKELEMENT_LIGHT_SHADE 0x2591 ++// ++// EFI Required Geometric Shapes Code Chart ++// ++ ++#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 ++#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba ++#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc ++#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 ++ ++// ++// EFI Required Arrow shapes ++// ++ ++#define ARROW_UP 0x2191 ++#define ARROW_DOWN 0x2193 ++ ++// ++// Text input protocol ++// ++ ++#define SIMPLE_TEXT_INPUT_PROTOCOL \ ++ { 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++INTERFACE_DECL(_SIMPLE_INPUT_INTERFACE); ++ ++typedef struct { ++ UINT16 ScanCode; ++ CHAR16 UnicodeChar; ++} EFI_INPUT_KEY; ++ ++// ++// Baseline unicode control chars ++// ++ ++#define CHAR_NULL 0x0000 ++#define CHAR_BACKSPACE 0x0008 ++#define CHAR_TAB 0x0009 ++#define CHAR_LINEFEED 0x000A ++#define CHAR_CARRIAGE_RETURN 0x000D ++ ++// ++// Scan codes for base line keys ++// ++ ++#define SCAN_NULL 0x0000 ++#define SCAN_UP 0x0001 ++#define SCAN_DOWN 0x0002 ++#define SCAN_RIGHT 0x0003 ++#define SCAN_LEFT 0x0004 ++#define SCAN_HOME 0x0005 ++#define SCAN_END 0x0006 ++#define SCAN_INSERT 0x0007 ++#define SCAN_DELETE 0x0008 ++#define SCAN_PAGE_UP 0x0009 ++#define SCAN_PAGE_DOWN 0x000A ++#define SCAN_F1 0x000B ++#define SCAN_F2 0x000C ++#define SCAN_F3 0x000D ++#define SCAN_F4 0x000E ++#define SCAN_F5 0x000F ++#define SCAN_F6 0x0010 ++#define SCAN_F7 0x0011 ++#define SCAN_F8 0x0012 ++#define SCAN_F9 0x0013 ++#define SCAN_F10 0x0014 ++#define SCAN_ESC 0x0017 ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_INPUT_RESET) ( ++ IN struct _SIMPLE_INPUT_INTERFACE *This, ++ IN BOOLEAN ExtendedVerification ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_INPUT_READ_KEY) ( ++ IN struct _SIMPLE_INPUT_INTERFACE *This, ++ OUT EFI_INPUT_KEY *Key ++ ); ++ ++typedef struct _SIMPLE_INPUT_INTERFACE { ++ EFI_INPUT_RESET Reset; ++ EFI_INPUT_READ_KEY ReadKeyStroke; ++ EFI_EVENT WaitForKey; ++} SIMPLE_INPUT_INTERFACE; ++ ++#endif ++ +--- /dev/null ++++ b/xen/include/efi/efidef.h +@@ -0,0 +1,196 @@ ++#ifndef _EFI_DEF_H ++#define _EFI_DEF_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ efidef.h ++ ++Abstract: ++ ++ EFI definitions ++ ++ ++ ++ ++Revision History ++ ++--*/ ++ ++typedef UINT16 CHAR16; ++typedef UINT8 CHAR8; ++typedef UINT8 BOOLEAN; ++ ++#ifndef TRUE ++ #define TRUE ((BOOLEAN) 1) ++ #define FALSE ((BOOLEAN) 0) ++#endif ++ ++#ifndef NULL ++ #define NULL ((VOID *) 0) ++#endif ++ ++typedef UINTN EFI_STATUS; ++typedef UINT64 EFI_LBA; ++typedef UINTN EFI_TPL; ++typedef VOID *EFI_HANDLE; ++typedef VOID *EFI_EVENT; ++ ++ ++// ++// Prototype argument decoration for EFI parameters to indicate ++// their direction ++// ++// IN - argument is passed into the function ++// OUT - argument (pointer) is returned from the function ++// OPTIONAL - argument is optional ++// ++ ++#ifndef IN ++ #define IN ++ #define OUT ++ #define OPTIONAL ++#endif ++ ++ ++// ++// A GUID ++// ++ ++typedef struct { ++ UINT32 Data1; ++ UINT16 Data2; ++ UINT16 Data3; ++ UINT8 Data4[8]; ++} EFI_GUID; ++ ++ ++// ++// Time ++// ++ ++typedef struct { ++ UINT16 Year; // 1998 - 20XX ++ UINT8 Month; // 1 - 12 ++ UINT8 Day; // 1 - 31 ++ UINT8 Hour; // 0 - 23 ++ UINT8 Minute; // 0 - 59 ++ UINT8 Second; // 0 - 59 ++ UINT8 Pad1; ++ UINT32 Nanosecond; // 0 - 999,999,999 ++ INT16 TimeZone; // -1440 to 1440 or 2047 ++ UINT8 Daylight; ++ UINT8 Pad2; ++} EFI_TIME; ++ ++// Bit definitions for EFI_TIME.Daylight ++#define EFI_TIME_ADJUST_DAYLIGHT 0x01 ++#define EFI_TIME_IN_DAYLIGHT 0x02 ++ ++// Value definition for EFI_TIME.TimeZone ++#define EFI_UNSPECIFIED_TIMEZONE 0x07FF ++ ++ ++ ++// ++// Networking ++// ++ ++typedef struct { ++ UINT8 Addr[4]; ++} EFI_IPv4_ADDRESS; ++ ++typedef struct { ++ UINT8 Addr[16]; ++} EFI_IPv6_ADDRESS; ++ ++typedef struct { ++ UINT8 Addr[32]; ++} EFI_MAC_ADDRESS; ++ ++// ++// Memory ++// ++ ++typedef UINT64 EFI_PHYSICAL_ADDRESS; ++typedef UINT64 EFI_VIRTUAL_ADDRESS; ++ ++typedef enum { ++ AllocateAnyPages, ++ AllocateMaxAddress, ++ AllocateAddress, ++ MaxAllocateType ++} EFI_ALLOCATE_TYPE; ++ ++//Preseve the attr on any range supplied. ++//ConventialMemory must have WB,SR,SW when supplied. ++//When allocating from ConventialMemory always make it WB,SR,SW ++//When returning to ConventialMemory always make it WB,SR,SW ++//When getting the memory map, or on RT for runtime types ++ ++ ++typedef enum { ++ EfiReservedMemoryType, ++ EfiLoaderCode, ++ EfiLoaderData, ++ EfiBootServicesCode, ++ EfiBootServicesData, ++ EfiRuntimeServicesCode, ++ EfiRuntimeServicesData, ++ EfiConventionalMemory, ++ EfiUnusableMemory, ++ EfiACPIReclaimMemory, ++ EfiACPIMemoryNVS, ++ EfiMemoryMappedIO, ++ EfiMemoryMappedIOPortSpace, ++ EfiPalCode, ++ EfiMaxMemoryType ++} EFI_MEMORY_TYPE; ++ ++// possible caching types for the memory range ++#define EFI_MEMORY_UC 0x0000000000000001 ++#define EFI_MEMORY_WC 0x0000000000000002 ++#define EFI_MEMORY_WT 0x0000000000000004 ++#define EFI_MEMORY_WB 0x0000000000000008 ++#define EFI_MEMORY_UCE 0x0000000000000010 ++ ++// physical memory protection on range ++#define EFI_MEMORY_WP 0x0000000000001000 ++#define EFI_MEMORY_RP 0x0000000000002000 ++#define EFI_MEMORY_XP 0x0000000000004000 ++ ++// range requires a runtime mapping ++#define EFI_MEMORY_RUNTIME 0x8000000000000000 ++ ++#define EFI_MEMORY_DESCRIPTOR_VERSION 1 ++typedef struct { ++ UINT32 Type; // Field size is 32 bits followed by 32 bit pad ++ UINT32 Pad; ++ EFI_PHYSICAL_ADDRESS PhysicalStart; // Field size is 64 bits ++ EFI_VIRTUAL_ADDRESS VirtualStart; // Field size is 64 bits ++ UINT64 NumberOfPages; // Field size is 64 bits ++ UINT64 Attribute; // Field size is 64 bits ++} EFI_MEMORY_DESCRIPTOR; ++ ++// ++// International Language ++// ++ ++typedef UINT8 ISO_639_2; ++#define ISO_639_2_ENTRY_SIZE 3 ++ ++// ++// ++// ++ ++#define EFI_PAGE_SIZE 4096 ++#define EFI_PAGE_MASK 0xFFF ++#define EFI_PAGE_SHIFT 12 ++ ++#define EFI_SIZE_TO_PAGES(a) \ ++ ( ((a) >> EFI_PAGE_SHIFT) + ((a) & EFI_PAGE_MASK ? 1 : 0) ) ++ ++#endif +--- /dev/null ++++ b/xen/include/efi/efidevp.h +@@ -0,0 +1,402 @@ ++#ifndef _DEVPATH_H ++#define _DEVPATH_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ devpath.h ++ ++Abstract: ++ ++ Defines for parsing the EFI Device Path structures ++ ++ ++ ++Revision History ++ ++--*/ ++ ++// ++// Device Path structures - Section C ++// ++ ++typedef struct _EFI_DEVICE_PATH { ++ UINT8 Type; ++ UINT8 SubType; ++ UINT8 Length[2]; ++} EFI_DEVICE_PATH; ++ ++#define EFI_DP_TYPE_MASK 0x7F ++#define EFI_DP_TYPE_UNPACKED 0x80 ++ ++//#define END_DEVICE_PATH_TYPE 0xff ++#define END_DEVICE_PATH_TYPE 0x7f ++//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f ++ ++#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff ++#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 ++#define END_DEVICE_PATH_LENGTH (sizeof(EFI_DEVICE_PATH)) ++ ++ ++#define DP_IS_END_TYPE(a) ++#define DP_IS_END_SUBTYPE(a) ( ((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) ++ ++#define DevicePathType(a) ( ((a)->Type) & EFI_DP_TYPE_MASK ) ++#define DevicePathSubType(a) ( (a)->SubType ) ++#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) ++#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) ++//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) ++#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) ++#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) ++#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) ++#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) ++ ++ ++#define SetDevicePathNodeLength(a,l) { \ ++ (a)->Length[0] = (UINT8) (l); \ ++ (a)->Length[1] = (UINT8) ((l) >> 8); \ ++ } ++ ++#define SetDevicePathEndNode(a) { \ ++ (a)->Type = END_DEVICE_PATH_TYPE; \ ++ (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ ++ (a)->Length[0] = sizeof(EFI_DEVICE_PATH); \ ++ (a)->Length[1] = 0; \ ++ } ++ ++ ++ ++/* ++ * ++ */ ++#define HARDWARE_DEVICE_PATH 0x01 ++ ++#define HW_PCI_DP 0x01 ++typedef struct _PCI_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT8 Function; ++ UINT8 Device; ++} PCI_DEVICE_PATH; ++ ++#define HW_PCCARD_DP 0x02 ++typedef struct _PCCARD_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT8 SocketNumber; ++} PCCARD_DEVICE_PATH; ++ ++#define HW_MEMMAP_DP 0x03 ++typedef struct _MEMMAP_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 MemoryType; ++ EFI_PHYSICAL_ADDRESS StartingAddress; ++ EFI_PHYSICAL_ADDRESS EndingAddress; ++} MEMMAP_DEVICE_PATH; ++ ++#define HW_VENDOR_DP 0x04 ++typedef struct _VENDOR_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ EFI_GUID Guid; ++} VENDOR_DEVICE_PATH; ++ ++#define UNKNOWN_DEVICE_GUID \ ++ { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } ++ ++typedef struct _UKNOWN_DEVICE_VENDOR_DP { ++ VENDOR_DEVICE_PATH DevicePath; ++ UINT8 LegacyDriveLetter; ++} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; ++ ++#define HW_CONTROLLER_DP 0x05 ++typedef struct _CONTROLLER_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Controller; ++} CONTROLLER_DEVICE_PATH; ++ ++/* ++ * ++ */ ++#define ACPI_DEVICE_PATH 0x02 ++ ++#define ACPI_DP 0x01 ++typedef struct _ACPI_HID_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 HID; ++ UINT32 UID; ++} ACPI_HID_DEVICE_PATH; ++ ++#define EXPANDED_ACPI_DP 0x02 ++typedef struct _EXPANDED_ACPI_HID_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 HID; ++ UINT32 UID; ++ UINT32 CID; ++ UINT8 HidStr[1]; ++} EXPANDED_ACPI_HID_DEVICE_PATH; ++ ++// ++// EISA ID Macro ++// EISA ID Definition 32-bits ++// bits[15:0] - three character compressed ASCII EISA ID. ++// bits[31:16] - binary number ++// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' ++// ++#define PNP_EISA_ID_CONST 0x41d0 ++#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16)) ++#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) ++ ++#define PNP_EISA_ID_MASK 0xffff ++#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) ++/* ++ * ++ */ ++#define MESSAGING_DEVICE_PATH 0x03 ++ ++#define MSG_ATAPI_DP 0x01 ++typedef struct _ATAPI_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT8 PrimarySecondary; ++ UINT8 SlaveMaster; ++ UINT16 Lun; ++} ATAPI_DEVICE_PATH; ++ ++#define MSG_SCSI_DP 0x02 ++typedef struct _SCSI_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT16 Pun; ++ UINT16 Lun; ++} SCSI_DEVICE_PATH; ++ ++#define MSG_FIBRECHANNEL_DP 0x03 ++typedef struct _FIBRECHANNEL_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Reserved; ++ UINT64 WWN; ++ UINT64 Lun; ++} FIBRECHANNEL_DEVICE_PATH; ++ ++#define MSG_1394_DP 0x04 ++typedef struct _F1394_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Reserved; ++ UINT64 Guid; ++} F1394_DEVICE_PATH; ++ ++#define MSG_USB_DP 0x05 ++typedef struct _USB_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT8 Port; ++ UINT8 Endpoint; ++} USB_DEVICE_PATH; ++ ++#define MSG_USB_CLASS_DP 0x0F ++typedef struct _USB_CLASS_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT16 VendorId; ++ UINT16 ProductId; ++ UINT8 DeviceClass; ++ UINT8 DeviceSubclass; ++ UINT8 DeviceProtocol; ++} USB_CLASS_DEVICE_PATH; ++ ++#define MSG_I2O_DP 0x06 ++typedef struct _I2O_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Tid; ++} I2O_DEVICE_PATH; ++ ++#define MSG_MAC_ADDR_DP 0x0b ++typedef struct _MAC_ADDR_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ EFI_MAC_ADDRESS MacAddress; ++ UINT8 IfType; ++} MAC_ADDR_DEVICE_PATH; ++ ++#define MSG_IPv4_DP 0x0c ++typedef struct _IPv4_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ EFI_IPv4_ADDRESS LocalIpAddress; ++ EFI_IPv4_ADDRESS RemoteIpAddress; ++ UINT16 LocalPort; ++ UINT16 RemotePort; ++ UINT16 Protocol; ++ BOOLEAN StaticIpAddress; ++} IPv4_DEVICE_PATH; ++ ++#define MSG_IPv6_DP 0x0d ++typedef struct _IPv6_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ EFI_IPv6_ADDRESS LocalIpAddress; ++ EFI_IPv6_ADDRESS RemoteIpAddress; ++ UINT16 LocalPort; ++ UINT16 RemotePort; ++ UINT16 Protocol; ++ BOOLEAN StaticIpAddress; ++} IPv6_DEVICE_PATH; ++ ++#define MSG_INFINIBAND_DP 0x09 ++typedef struct _INFINIBAND_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Reserved; ++ UINT64 NodeGuid; ++ UINT64 IocGuid; ++ UINT64 DeviceId; ++} INFINIBAND_DEVICE_PATH; ++ ++#define MSG_UART_DP 0x0e ++typedef struct _UART_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 Reserved; ++ UINT64 BaudRate; ++ UINT8 DataBits; ++ UINT8 Parity; ++ UINT8 StopBits; ++} UART_DEVICE_PATH; ++ ++#define MSG_VENDOR_DP 0x0A ++/* Use VENDOR_DEVICE_PATH struct */ ++ ++#define DEVICE_PATH_MESSAGING_PC_ANSI \ ++ { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++#define DEVICE_PATH_MESSAGING_VT_100 \ ++ { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++ ++ ++#define MEDIA_DEVICE_PATH 0x04 ++ ++#define MEDIA_HARDDRIVE_DP 0x01 ++typedef struct _HARDDRIVE_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 PartitionNumber; ++ UINT64 PartitionStart; ++ UINT64 PartitionSize; ++ UINT8 Signature[16]; ++ UINT8 MBRType; ++ UINT8 SignatureType; ++} HARDDRIVE_DEVICE_PATH; ++ ++#define MBR_TYPE_PCAT 0x01 ++#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 ++ ++#define SIGNATURE_TYPE_MBR 0x01 ++#define SIGNATURE_TYPE_GUID 0x02 ++ ++#define MEDIA_CDROM_DP 0x02 ++typedef struct _CDROM_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT32 BootEntry; ++ UINT64 PartitionStart; ++ UINT64 PartitionSize; ++} CDROM_DEVICE_PATH; ++ ++#define MEDIA_VENDOR_DP 0x03 ++/* Use VENDOR_DEVICE_PATH struct */ ++ ++#define MEDIA_FILEPATH_DP 0x04 ++typedef struct _FILEPATH_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ CHAR16 PathName[1]; ++} FILEPATH_DEVICE_PATH; ++ ++#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName) ++ ++#define MEDIA_PROTOCOL_DP 0x05 ++typedef struct _MEDIA_PROTOCOL_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ EFI_GUID Protocol; ++} MEDIA_PROTOCOL_DEVICE_PATH; ++ ++ ++#define BBS_DEVICE_PATH 0x05 ++#define BBS_BBS_DP 0x01 ++typedef struct _BBS_BBS_DEVICE_PATH { ++ EFI_DEVICE_PATH Header; ++ UINT16 DeviceType; ++ UINT16 StatusFlag; ++ CHAR8 String[1]; ++} BBS_BBS_DEVICE_PATH; ++ ++/* DeviceType definitions - from BBS specification */ ++#define BBS_TYPE_FLOPPY 0x01 ++#define BBS_TYPE_HARDDRIVE 0x02 ++#define BBS_TYPE_CDROM 0x03 ++#define BBS_TYPE_PCMCIA 0x04 ++#define BBS_TYPE_USB 0x05 ++#define BBS_TYPE_EMBEDDED_NETWORK 0x06 ++#define BBS_TYPE_DEV 0x80 ++#define BBS_TYPE_UNKNOWN 0xFF ++ ++typedef union { ++ EFI_DEVICE_PATH DevPath; ++ PCI_DEVICE_PATH Pci; ++ PCCARD_DEVICE_PATH PcCard; ++ MEMMAP_DEVICE_PATH MemMap; ++ VENDOR_DEVICE_PATH Vendor; ++ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; ++ CONTROLLER_DEVICE_PATH Controller; ++ ACPI_HID_DEVICE_PATH Acpi; ++ ++ ATAPI_DEVICE_PATH Atapi; ++ SCSI_DEVICE_PATH Scsi; ++ FIBRECHANNEL_DEVICE_PATH FibreChannel; ++ ++ F1394_DEVICE_PATH F1394; ++ USB_DEVICE_PATH Usb; ++ USB_CLASS_DEVICE_PATH UsbClass; ++ I2O_DEVICE_PATH I2O; ++ MAC_ADDR_DEVICE_PATH MacAddr; ++ IPv4_DEVICE_PATH Ipv4; ++ IPv6_DEVICE_PATH Ipv6; ++ INFINIBAND_DEVICE_PATH InfiniBand; ++ UART_DEVICE_PATH Uart; ++ ++ HARDDRIVE_DEVICE_PATH HardDrive; ++ CDROM_DEVICE_PATH CD; ++ ++ FILEPATH_DEVICE_PATH FilePath; ++ MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; ++ ++ BBS_BBS_DEVICE_PATH Bbs; ++ ++} EFI_DEV_PATH; ++ ++typedef union { ++ EFI_DEVICE_PATH *DevPath; ++ PCI_DEVICE_PATH *Pci; ++ PCCARD_DEVICE_PATH *PcCard; ++ MEMMAP_DEVICE_PATH *MemMap; ++ VENDOR_DEVICE_PATH *Vendor; ++ UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownVendor; ++ CONTROLLER_DEVICE_PATH *Controller; ++ ACPI_HID_DEVICE_PATH *Acpi; ++ ++ ATAPI_DEVICE_PATH *Atapi; ++ SCSI_DEVICE_PATH *Scsi; ++ FIBRECHANNEL_DEVICE_PATH *FibreChannel; ++ ++ F1394_DEVICE_PATH *F1394; ++ USB_DEVICE_PATH *Usb; ++ USB_CLASS_DEVICE_PATH *UsbClass; ++ I2O_DEVICE_PATH *I2O; ++ MAC_ADDR_DEVICE_PATH *MacAddr; ++ IPv4_DEVICE_PATH *Ipv4; ++ IPv6_DEVICE_PATH *Ipv6; ++ INFINIBAND_DEVICE_PATH *InfiniBand; ++ UART_DEVICE_PATH *Uart; ++ ++ HARDDRIVE_DEVICE_PATH *HardDrive; ++ ++ FILEPATH_DEVICE_PATH *FilePath; ++ MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; ++ ++ CDROM_DEVICE_PATH *CD; ++ BBS_BBS_DEVICE_PATH *Bbs; ++ ++} EFI_DEV_PATH_PTR; ++ ++ ++#endif +--- /dev/null ++++ b/xen/include/efi/efierr.h +@@ -0,0 +1,60 @@ ++#ifndef _EFI_ERR_H ++#define _EFI_ERR_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ efierr.h ++ ++Abstract: ++ ++ EFI error codes ++ ++ ++ ++ ++Revision History ++ ++--*/ ++ ++ ++#define EFIWARN(a) (a) ++#define EFI_ERROR(a) (((INTN) a) < 0) ++ ++ ++#define EFI_SUCCESS 0 ++#define EFI_LOAD_ERROR EFIERR(1) ++#define EFI_INVALID_PARAMETER EFIERR(2) ++#define EFI_UNSUPPORTED EFIERR(3) ++#define EFI_BAD_BUFFER_SIZE EFIERR(4) ++#define EFI_BUFFER_TOO_SMALL EFIERR(5) ++#define EFI_NOT_READY EFIERR(6) ++#define EFI_DEVICE_ERROR EFIERR(7) ++#define EFI_WRITE_PROTECTED EFIERR(8) ++#define EFI_OUT_OF_RESOURCES EFIERR(9) ++#define EFI_VOLUME_CORRUPTED EFIERR(10) ++#define EFI_VOLUME_FULL EFIERR(11) ++#define EFI_NO_MEDIA EFIERR(12) ++#define EFI_MEDIA_CHANGED EFIERR(13) ++#define EFI_NOT_FOUND EFIERR(14) ++#define EFI_ACCESS_DENIED EFIERR(15) ++#define EFI_NO_RESPONSE EFIERR(16) ++#define EFI_NO_MAPPING EFIERR(17) ++#define EFI_TIMEOUT EFIERR(18) ++#define EFI_NOT_STARTED EFIERR(19) ++#define EFI_ALREADY_STARTED EFIERR(20) ++#define EFI_ABORTED EFIERR(21) ++#define EFI_ICMP_ERROR EFIERR(22) ++#define EFI_TFTP_ERROR EFIERR(23) ++#define EFI_PROTOCOL_ERROR EFIERR(24) ++ ++#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1) ++#define EFI_WARN_DELETE_FAILURE EFIWARN(2) ++#define EFI_WARN_WRITE_FAILURE EFIWARN(3) ++#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4) ++ ++#endif ++ +--- /dev/null ++++ b/xen/include/efi/efiprot.h +@@ -0,0 +1,728 @@ ++#ifndef _EFI_PROT_H ++#define _EFI_PROT_H ++ ++/*++ ++ ++Copyright (c) 1998 Intel Corporation ++ ++Module Name: ++ ++ efiprot.h ++ ++Abstract: ++ ++ EFI Protocols ++ ++ ++ ++Revision History ++ ++--*/ ++ ++// ++// FPSWA library protocol ++// ++#define FPSWA_PROTOCOL \ ++ { 0xc41b6531, 0x97b9, 0x11d3, {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++// ++// Device Path protocol ++// ++ ++#define DEVICE_PATH_PROTOCOL \ ++ { 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++ ++// ++// Block IO protocol ++// ++ ++#define BLOCK_IO_PROTOCOL \ ++ { 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++#define EFI_BLOCK_IO_INTERFACE_REVISION 0x00010000 ++ ++INTERFACE_DECL(_EFI_BLOCK_IO); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_BLOCK_RESET) ( ++ IN struct _EFI_BLOCK_IO *This, ++ IN BOOLEAN ExtendedVerification ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_BLOCK_READ) ( ++ IN struct _EFI_BLOCK_IO *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA LBA, ++ IN UINTN BufferSize, ++ OUT VOID *Buffer ++ ); ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_BLOCK_WRITE) ( ++ IN struct _EFI_BLOCK_IO *This, ++ IN UINT32 MediaId, ++ IN EFI_LBA LBA, ++ IN UINTN BufferSize, ++ IN VOID *Buffer ++ ); ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_BLOCK_FLUSH) ( ++ IN struct _EFI_BLOCK_IO *This ++ ); ++ ++ ++ ++typedef struct { ++ UINT32 MediaId; ++ BOOLEAN RemovableMedia; ++ BOOLEAN MediaPresent; ++ ++ BOOLEAN LogicalPartition; ++ BOOLEAN ReadOnly; ++ BOOLEAN WriteCaching; ++ ++ UINT32 BlockSize; ++ UINT32 IoAlign; ++ ++ EFI_LBA LastBlock; ++} EFI_BLOCK_IO_MEDIA; ++ ++typedef struct _EFI_BLOCK_IO { ++ UINT64 Revision; ++ ++ EFI_BLOCK_IO_MEDIA *Media; ++ ++ EFI_BLOCK_RESET Reset; ++ EFI_BLOCK_READ ReadBlocks; ++ EFI_BLOCK_WRITE WriteBlocks; ++ EFI_BLOCK_FLUSH FlushBlocks; ++ ++} EFI_BLOCK_IO; ++ ++ ++ ++// ++// Disk Block IO protocol ++// ++ ++#define DISK_IO_PROTOCOL \ ++ { 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++#define EFI_DISK_IO_INTERFACE_REVISION 0x00010000 ++ ++INTERFACE_DECL(_EFI_DISK_IO); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_DISK_READ) ( ++ IN struct _EFI_DISK_IO *This, ++ IN UINT32 MediaId, ++ IN UINT64 Offset, ++ IN UINTN BufferSize, ++ OUT VOID *Buffer ++ ); ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_DISK_WRITE) ( ++ IN struct _EFI_DISK_IO *This, ++ IN UINT32 MediaId, ++ IN UINT64 Offset, ++ IN UINTN BufferSize, ++ IN VOID *Buffer ++ ); ++ ++ ++typedef struct _EFI_DISK_IO { ++ UINT64 Revision; ++ EFI_DISK_READ ReadDisk; ++ EFI_DISK_WRITE WriteDisk; ++} EFI_DISK_IO; ++ ++ ++// ++// Simple file system protocol ++// ++ ++#define SIMPLE_FILE_SYSTEM_PROTOCOL \ ++ { 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++INTERFACE_DECL(_EFI_FILE_IO_INTERFACE); ++INTERFACE_DECL(_EFI_FILE_HANDLE); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_VOLUME_OPEN) ( ++ IN struct _EFI_FILE_IO_INTERFACE *This, ++ OUT struct _EFI_FILE_HANDLE **Root ++ ); ++ ++#define EFI_FILE_IO_INTERFACE_REVISION 0x00010000 ++ ++typedef struct _EFI_FILE_IO_INTERFACE { ++ UINT64 Revision; ++ EFI_VOLUME_OPEN OpenVolume; ++} EFI_FILE_IO_INTERFACE; ++ ++// ++// ++// ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_OPEN) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ OUT struct _EFI_FILE_HANDLE **NewHandle, ++ IN CHAR16 *FileName, ++ IN UINT64 OpenMode, ++ IN UINT64 Attributes ++ ); ++ ++// Open modes ++#define EFI_FILE_MODE_READ 0x0000000000000001 ++#define EFI_FILE_MODE_WRITE 0x0000000000000002 ++#define EFI_FILE_MODE_CREATE 0x8000000000000000 ++ ++// File attributes ++#define EFI_FILE_READ_ONLY 0x0000000000000001 ++#define EFI_FILE_HIDDEN 0x0000000000000002 ++#define EFI_FILE_SYSTEM 0x0000000000000004 ++#define EFI_FILE_RESERVIED 0x0000000000000008 ++#define EFI_FILE_DIRECTORY 0x0000000000000010 ++#define EFI_FILE_ARCHIVE 0x0000000000000020 ++#define EFI_FILE_VALID_ATTR 0x0000000000000037 ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_CLOSE) ( ++ IN struct _EFI_FILE_HANDLE *File ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_DELETE) ( ++ IN struct _EFI_FILE_HANDLE *File ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_READ) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ IN OUT UINTN *BufferSize, ++ OUT VOID *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_WRITE) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ IN OUT UINTN *BufferSize, ++ IN VOID *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_SET_POSITION) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ IN UINT64 Position ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_GET_POSITION) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ OUT UINT64 *Position ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_GET_INFO) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ IN EFI_GUID *InformationType, ++ IN OUT UINTN *BufferSize, ++ OUT VOID *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_SET_INFO) ( ++ IN struct _EFI_FILE_HANDLE *File, ++ IN EFI_GUID *InformationType, ++ IN UINTN BufferSize, ++ IN VOID *Buffer ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_FILE_FLUSH) ( ++ IN struct _EFI_FILE_HANDLE *File ++ ); ++ ++ ++ ++#define EFI_FILE_HANDLE_REVISION 0x00010000 ++typedef struct _EFI_FILE_HANDLE { ++ UINT64 Revision; ++ EFI_FILE_OPEN Open; ++ EFI_FILE_CLOSE Close; ++ EFI_FILE_DELETE Delete; ++ EFI_FILE_READ Read; ++ EFI_FILE_WRITE Write; ++ EFI_FILE_GET_POSITION GetPosition; ++ EFI_FILE_SET_POSITION SetPosition; ++ EFI_FILE_GET_INFO GetInfo; ++ EFI_FILE_SET_INFO SetInfo; ++ EFI_FILE_FLUSH Flush; ++} EFI_FILE, *EFI_FILE_HANDLE; ++ ++ ++// ++// File information types ++// ++ ++#define EFI_FILE_INFO_ID \ ++ { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++typedef struct { ++ UINT64 Size; ++ UINT64 FileSize; ++ UINT64 PhysicalSize; ++ EFI_TIME CreateTime; ++ EFI_TIME LastAccessTime; ++ EFI_TIME ModificationTime; ++ UINT64 Attribute; ++ CHAR16 FileName[1]; ++} EFI_FILE_INFO; ++ ++// ++// The FileName field of the EFI_FILE_INFO data structure is variable length. ++// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to ++// be the size of the data structure without the FileName field. The following macro ++// computes this size correctly no matter how big the FileName array is declared. ++// This is required to make the EFI_FILE_INFO data structure ANSI compilant. ++// ++ ++#define SIZE_OF_EFI_FILE_INFO EFI_FIELD_OFFSET(EFI_FILE_INFO,FileName) ++ ++#define EFI_FILE_SYSTEM_INFO_ID \ ++ { 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++typedef struct { ++ UINT64 Size; ++ BOOLEAN ReadOnly; ++ UINT64 VolumeSize; ++ UINT64 FreeSpace; ++ UINT32 BlockSize; ++ CHAR16 VolumeLabel[1]; ++} EFI_FILE_SYSTEM_INFO; ++ ++// ++// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. ++// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs ++// to be the size of the data structure without the VolumeLable field. The following macro ++// computes this size correctly no matter how big the VolumeLable array is declared. ++// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. ++// ++ ++#define SIZE_OF_EFI_FILE_SYSTEM_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_INFO,VolumeLabel) ++ ++#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID \ ++ { 0xDB47D7D3,0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } ++ ++typedef struct { ++ CHAR16 VolumeLabel[1]; ++} EFI_FILE_SYSTEM_VOLUME_LABEL_INFO; ++ ++#define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_VOLUME_LABEL_INFO,VolumeLabel) ++ ++// ++// Load file protocol ++// ++ ++ ++#define LOAD_FILE_PROTOCOL \ ++ { 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } ++ ++INTERFACE_DECL(_EFI_LOAD_FILE_INTERFACE); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_LOAD_FILE) ( ++ IN struct _EFI_LOAD_FILE_INTERFACE *This, ++ IN EFI_DEVICE_PATH *FilePath, ++ IN BOOLEAN BootPolicy, ++ IN OUT UINTN *BufferSize, ++ IN VOID *Buffer OPTIONAL ++ ); ++ ++typedef struct _EFI_LOAD_FILE_INTERFACE { ++ EFI_LOAD_FILE LoadFile; ++} EFI_LOAD_FILE_INTERFACE; ++ ++ ++// ++// Device IO protocol ++// ++ ++#define DEVICE_IO_PROTOCOL \ ++ { 0xaf6ac311, 0x84c3, 0x11d2, {0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } ++ ++INTERFACE_DECL(_EFI_DEVICE_IO_INTERFACE); ++ ++typedef enum { ++ IO_UINT8, ++ IO_UINT16, ++ IO_UINT32, ++ IO_UINT64, ++// ++// Specification Change: Copy from MMIO to MMIO vs. MMIO to buffer, buffer to MMIO ++// ++ MMIO_COPY_UINT8, ++ MMIO_COPY_UINT16, ++ MMIO_COPY_UINT32, ++ MMIO_COPY_UINT64 ++} EFI_IO_WIDTH; ++ ++#define EFI_PCI_ADDRESS(_bus,_dev,_func) \ ++ ( (UINT64) ( (((UINTN)_bus) << 24) + (((UINTN)_dev) << 16) + (((UINTN)_func) << 8) ) ) ++ ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_DEVICE_IO) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN EFI_IO_WIDTH Width, ++ IN UINT64 Address, ++ IN UINTN Count, ++ IN OUT VOID *Buffer ++ ); ++ ++typedef struct { ++ EFI_DEVICE_IO Read; ++ EFI_DEVICE_IO Write; ++} EFI_IO_ACCESS; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_PCI_DEVICE_PATH) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN UINT64 Address, ++ IN OUT EFI_DEVICE_PATH **PciDevicePath ++ ); ++ ++typedef enum { ++ EfiBusMasterRead, ++ EfiBusMasterWrite, ++ EfiBusMasterCommonBuffer ++} EFI_IO_OPERATION_TYPE; ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IO_MAP) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN EFI_IO_OPERATION_TYPE Operation, ++ IN EFI_PHYSICAL_ADDRESS *HostAddress, ++ IN OUT UINTN *NumberOfBytes, ++ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, ++ OUT VOID **Mapping ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IO_UNMAP) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN VOID *Mapping ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IO_ALLOCATE_BUFFER) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN EFI_ALLOCATE_TYPE Type, ++ IN EFI_MEMORY_TYPE MemoryType, ++ IN UINTN Pages, ++ IN OUT EFI_PHYSICAL_ADDRESS *HostAddress ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IO_FLUSH) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This ++ ); ++ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_IO_FREE_BUFFER) ( ++ IN struct _EFI_DEVICE_IO_INTERFACE *This, ++ IN UINTN Pages, ++ IN EFI_PHYSICAL_ADDRESS HostAddress ++ ); ++ ++typedef struct _EFI_DEVICE_IO_INTERFACE { ++ EFI_IO_ACCESS Mem; ++ EFI_IO_ACCESS Io; ++ EFI_IO_ACCESS Pci; ++ EFI_IO_MAP Map; ++ EFI_PCI_DEVICE_PATH PciDevicePath; ++ EFI_IO_UNMAP Unmap; ++ EFI_IO_ALLOCATE_BUFFER AllocateBuffer; ++ EFI_IO_FLUSH Flush; ++ EFI_IO_FREE_BUFFER FreeBuffer; ++} EFI_DEVICE_IO_INTERFACE; ++ ++ ++// ++// Unicode Collation protocol ++// ++ ++#define UNICODE_COLLATION_PROTOCOL \ ++ { 0x1d85cd7f, 0xf43d, 0x11d2, {0x9a, 0xc, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } ++ ++#define UNICODE_BYTE_ORDER_MARK (CHAR16)(0xfeff) ++ ++INTERFACE_DECL(_EFI_UNICODE_COLLATION_INTERFACE); ++ ++typedef ++INTN ++(EFIAPI *EFI_UNICODE_STRICOLL) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN CHAR16 *s1, ++ IN CHAR16 *s2 ++ ); ++ ++typedef ++BOOLEAN ++(EFIAPI *EFI_UNICODE_METAIMATCH) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN CHAR16 *String, ++ IN CHAR16 *Pattern ++ ); ++ ++typedef ++VOID ++(EFIAPI *EFI_UNICODE_STRLWR) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN OUT CHAR16 *Str ++ ); ++ ++typedef ++VOID ++(EFIAPI *EFI_UNICODE_STRUPR) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN OUT CHAR16 *Str ++ ); ++ ++typedef ++VOID ++(EFIAPI *EFI_UNICODE_FATTOSTR) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN UINTN FatSize, ++ IN CHAR8 *Fat, ++ OUT CHAR16 *String ++ ); ++ ++typedef ++BOOLEAN ++(EFIAPI *EFI_UNICODE_STRTOFAT) ( ++ IN struct _EFI_UNICODE_COLLATION_INTERFACE *This, ++ IN CHAR16 *String, ++ IN UINTN FatSize, ++ OUT CHAR8 *Fat ++ ); ++ ++ ++typedef struct _EFI_UNICODE_COLLATION_INTERFACE { ++ ++ // general ++ EFI_UNICODE_STRICOLL StriColl; ++ EFI_UNICODE_METAIMATCH MetaiMatch; ++ EFI_UNICODE_STRLWR StrLwr; ++ EFI_UNICODE_STRUPR StrUpr; ++ ++ // for supporting fat volumes ++ EFI_UNICODE_FATTOSTR FatToStr; ++ EFI_UNICODE_STRTOFAT StrToFat; ++ ++ CHAR8 *SupportedLanguages; ++} EFI_UNICODE_COLLATION_INTERFACE; ++ ++/* Graphics output protocol */ ++#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ ++ { \ ++ 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ ++ } ++ ++typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; ++ ++typedef struct { ++ UINT32 RedMask; ++ UINT32 GreenMask; ++ UINT32 BlueMask; ++ UINT32 ReservedMask; ++} EFI_PIXEL_BITMASK; ++ ++typedef enum { ++ PixelRedGreenBlueReserved8BitPerColor, ++ PixelBlueGreenRedReserved8BitPerColor, ++ PixelBitMask, ++ PixelBltOnly, ++ PixelFormatMax ++} EFI_GRAPHICS_PIXEL_FORMAT; ++ ++typedef struct { ++ UINT32 Version; ++ UINT32 HorizontalResolution; ++ UINT32 VerticalResolution; ++ EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; ++ EFI_PIXEL_BITMASK PixelInformation; ++ UINT32 PixelsPerScanLine; ++} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; ++ ++/** ++ Return the current video mode information. ++ ++ @param This Protocol instance pointer. ++ @param ModeNumber The mode number to return information on. ++ @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. ++ @param Info A pointer to callee allocated buffer that returns information about ModeNumber. ++ ++ @retval EFI_SUCCESS Mode information returned. ++ @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. ++ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. ++ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () ++ @retval EFI_INVALID_PARAMETER One of the input args was NULL. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( ++ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, ++ IN UINT32 ModeNumber, ++ OUT UINTN *SizeOfInfo, ++ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info ++ ) ++; ++ ++/** ++ Return the current video mode information. ++ ++ @param This Protocol instance pointer. ++ @param ModeNumber The mode number to be set. ++ ++ @retval EFI_SUCCESS Graphics mode was changed. ++ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. ++ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( ++ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, ++ IN UINT32 ModeNumber ++ ) ++; ++ ++typedef struct { ++ UINT8 Blue; ++ UINT8 Green; ++ UINT8 Red; ++ UINT8 Reserved; ++} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; ++ ++typedef union { ++ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; ++ UINT32 Raw; ++} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; ++ ++typedef enum { ++ EfiBltVideoFill, ++ EfiBltVideoToBltBuffer, ++ EfiBltBufferToVideo, ++ EfiBltVideoToVideo, ++ EfiGraphicsOutputBltOperationMax ++} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; ++ ++/** ++ The following table defines actions for BltOperations: ++ ++ EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) ++ directly to every pixel of the video display rectangle ++ (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). ++ Only one pixel will be used from the BltBuffer. Delta is NOT used. ++ ++ EfiBltVideoToBltBuffer - Read data from the video display rectangle ++ (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in ++ the BltBuffer rectangle (DestinationX, DestinationY ) ++ (DestinationX + Width, DestinationY + Height). If DestinationX or ++ DestinationY is not zero then Delta must be set to the length in bytes ++ of a row in the BltBuffer. ++ ++ EfiBltBufferToVideo - Write data from the BltBuffer rectangle ++ (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the ++ video display rectangle (DestinationX, DestinationY) ++ (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is ++ not zero then Delta must be set to the length in bytes of a row in the ++ BltBuffer. ++ ++ EfiBltVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) ++ (SourceX + Width, SourceY + Height) .to the video display rectangle ++ (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). ++ The BltBuffer and Delta are not used in this mode. ++ ++ @param This Protocol instance pointer. ++ @param BltBuffer Buffer containing data to blit into video buffer. This ++ buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) ++ @param BltOperation Operation to perform on BlitBuffer and video memory ++ @param SourceX X coordinate of source for the BltBuffer. ++ @param SourceY Y coordinate of source for the BltBuffer. ++ @param DestinationX X coordinate of destination for the BltBuffer. ++ @param DestinationY Y coordinate of destination for the BltBuffer. ++ @param Width Width of rectangle in BltBuffer in pixels. ++ @param Height Hight of rectangle in BltBuffer in pixels. ++ @param Delta OPTIONAL ++ ++ @retval EFI_SUCCESS The Blt operation completed. ++ @retval EFI_INVALID_PARAMETER BltOperation is not valid. ++ @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( ++ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, ++ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL ++ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, ++ IN UINTN SourceX, ++ IN UINTN SourceY, ++ IN UINTN DestinationX, ++ IN UINTN DestinationY, ++ IN UINTN Width, ++ IN UINTN Height, ++ IN UINTN Delta OPTIONAL ++ ); ++ ++typedef struct { ++ UINT32 MaxMode; ++ UINT32 Mode; ++ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; ++ UINTN SizeOfInfo; ++ EFI_PHYSICAL_ADDRESS FrameBufferBase; ++ UINTN FrameBufferSize; ++} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; ++ ++struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { ++ EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; ++ EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; ++ EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; ++ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; ++}; ++#endif ++ diff --git a/23614-x86_64-EFI-boot.patch b/23614-x86_64-EFI-boot.patch new file mode 100644 index 0000000..d2cb396 --- /dev/null +++ b/23614-x86_64-EFI-boot.patch @@ -0,0 +1,2485 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1309249175 -3600 +# Node ID 8b7d00f2abb21b504f6f8e1a6cc235cee8eb0858 +# Parent b8d22c658bd213bf9da0a9d05312b63524652daf +x86-64: EFI boot code + +Besides introducing the relevant code paralleling parts of what is +under xen/arch/x86/boot/, this adjusts the build logic so that with a +single compilation two images (gzip-compressed ELF and EFI +application) +can get created. The EFI part of this depends on a new enough compiler +(supposedly gcc 4.4.x and above, but so far only tested to work with +4.5.x) and a properly configured linker (must support the i386pep +emulation). If either functionality is found to not be available, the +EFI part of the build will simply be skipped. + +The patch adds all code to allow Xen and the (accordingly enabled) +Dom0 kernel to boot, but doesn't allow Dom0 to make use of EFI +runtime calls (this will be the subject of the next patch). + +Parts of the code were lifted from an earlier never published OS +project of ours - whether respective license information needs to be +added to the respective source file is unclear to me (I was told +internally that adding a GPLv2 license header can be done if needed by +the community). + +Signed-off-by: Jan Beulich + +--- a/xen/Makefile ++++ b/xen/Makefile +@@ -11,6 +11,8 @@ export XEN_DOMAIN ?= $(shell ([ -x /bin/ + + export BASEDIR := $(CURDIR) + ++EFI_MOUNTPOINT ?= /boot/efi ++ + .PHONY: default + default: build + +@@ -32,6 +34,13 @@ _install: $(TARGET).gz + ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).gz + ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET)).gz + $(INSTALL_DATA) $(TARGET)-syms $(DESTDIR)/boot/$(notdir $(TARGET))-syms-$(XEN_FULLVERSION) ++ if [ -r $(TARGET).efi -a -n "$(EFI_MOUNTPOINT)" ]; then \ ++ if [ -n '$(EFI_VENDOR)' ]; then \ ++ $(INSTALL_DATA) $(TARGET).efi $(DESTDIR)$(EFI_MOUNTPOINT)/efi/$(EFI_VENDOR)/$(notdir $(TARGET))-$(XEN_FULLVERSION).efi; \ ++ elif [ "$(DESTDIR)" = "$(patsubst $(shell cd $(XEN_ROOT) && pwd)/%,%,$(DESTDIR))" ]; then \ ++ echo 'EFI installation not done (EFI_VENDOR not set)' >&2; \ ++ fi; \ ++ fi + + .PHONY: _debug + _debug: +--- a/xen/arch/x86/Makefile ++++ b/xen/arch/x86/Makefile +@@ -61,14 +61,21 @@ obj-$(crash_debug) += gdbstub.o + + x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h + +-$(TARGET): $(TARGET)-syms boot/mkelf32 ++efi-$(x86_64) := $(shell if [ ! -r $(BASEDIR)/include/xen/compile.h -o \ ++ -O $(BASEDIR)/include/xen/compile.h ]; then \ ++ echo '$(TARGET).efi'; fi) ++ ++$(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32 + ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \ + `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` + +-ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(ALL_OBJS) ++ALL_EFI_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o efi/boot.o efi/runtime.o efi/compat.o $(ALL_OBJS) ++ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(BASEDIR)/arch/x86/efi/built_in.o $(ALL_OBJS) ++ ++$(BASEDIR)/common/symbols-dummy.o: ++ $(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o + +-$(TARGET)-syms: $(ALL_OBJS) xen.lds +- $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o ++$(TARGET)-syms: $(ALL_OBJS) xen.lds $(BASEDIR)/common/symbols-dummy.o + $(LD) $(LDFLAGS) -T xen.lds -N $(ALL_OBJS) \ + $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 + $(NM) -n $(@D)/.$(@F).0 | $(BASEDIR)/tools/symbols >$(@D)/.$(@F).0.S +@@ -81,6 +88,39 @@ $(TARGET)-syms: $(ALL_OBJS) xen.lds + $(@D)/.$(@F).1.o -o $@ + rm -f $(@D)/.$(@F).[0-9]* + ++EFI_LDFLAGS = $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10 ++EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0 --strip-debug ++EFI_LDFLAGS += --section-alignment=0x200000 --file-alignment=0x20 ++EFI_LDFLAGS += --major-image-version=$(XEN_VERSION) ++EFI_LDFLAGS += --minor-image-version=$(XEN_SUBVERSION) ++EFI_LDFLAGS += --major-os-version=2 --minor-os-version=0 ++EFI_LDFLAGS += --major-subsystem-version=2 --minor-subsystem-version=0 ++ ++$(TARGET).efi: VIRT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A VIRT_START$$,,p') ++$(TARGET).efi: ALT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A ALT_START$$,,p') ++# Don't use $(wildcard ...) here - at least make 3.80 expands this too early! ++$(TARGET).efi: guard = $(if $(shell echo efi/dis* | grep disabled),:) ++$(TARGET).efi: $(ALL_EFI_OBJS) efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbols-dummy.o efi/mkreloc ++ $(foreach base, $(VIRT_BASE) $(ALT_BASE), \ ++ $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $(ALL_EFI_OBJS) efi/relocs-dummy.o \ ++ $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).$(base).0 &&) : ++ $(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S ++ $(guard) $(NM) -n $(@D)/.$(@F).$(VIRT_BASE).0 | $(guard) $(BASEDIR)/tools/symbols >$(@D)/.$(@F).0s.S ++ $(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o ++ $(foreach base, $(VIRT_BASE) $(ALT_BASE), \ ++ $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $(ALL_EFI_OBJS) \ ++ $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o -o $(@D)/.$(@F).$(base).1 &&) : ++ $(guard) efi/mkreloc $(foreach base,$(VIRT_BASE) $(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S ++ $(guard) $(NM) -n $(@D)/.$(@F).$(VIRT_BASE).1 | $(guard) $(BASEDIR)/tools/symbols >$(@D)/.$(@F).1s.S ++ $(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o ++ $(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $(ALL_EFI_OBJS) \ ++ $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o -o $@ ++ if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi ++ rm -f $(@D)/.$(@F).[0-9]* ++ ++efi/boot.o efi/runtime.o efi/compat.o: $(BASEDIR)/arch/x86/efi/built_in.o ++efi/boot.o efi/runtime.o efi/compat.o: ; ++ + asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c + $(CC) $(CFLAGS) -S -o $@ $< + +@@ -89,11 +129,20 @@ xen.lds: xen.lds.S + sed -e 's/xen\.lds\.o:/xen\.lds:/g' <.xen.lds.d >.xen.lds.d.new + mv -f .xen.lds.d.new .xen.lds.d + ++efi.lds: xen.lds.S ++ $(CC) -P -E -Ui386 -DEFI $(AFLAGS) -o $@ $< ++ sed -e 's/efi\.lds\.o:/efi\.lds:/g' <.$(@F).d >.$(@F).d.new ++ mv -f .$(@F).d.new .$(@F).d ++ + boot/mkelf32: boot/mkelf32.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + ++efi/mkreloc: efi/mkreloc.c ++ $(HOSTCC) $(HOSTCFLAGS) -g -o $@ $< ++ + .PHONY: clean + clean:: + rm -f asm-offsets.s xen.lds boot/*.o boot/*~ boot/core boot/mkelf32 + rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d ++ rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/mkreloc + rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin +--- a/xen/arch/x86/boot/trampoline.S ++++ b/xen/arch/x86/boot/trampoline.S +@@ -38,6 +38,7 @@ trampoline_gdt: + .long 0x0000ffff | ((BOOT_TRAMPOLINE & 0x00ffff) << 16) + .long 0x00009200 | ((BOOT_TRAMPOLINE & 0xff0000) >> 16) + ++ .globl cpuid_ext_features + cpuid_ext_features: + .long 0 + +--- a/xen/arch/x86/boot/x86_64.S ++++ b/xen/arch/x86/boot/x86_64.S +@@ -84,11 +84,13 @@ multiboot_ptr: + .long 0 + + .word 0 ++ .globl gdt_descr + gdt_descr: + .word LAST_RESERVED_GDT_BYTE + .quad boot_cpu_gdt_table - FIRST_RESERVED_GDT_BYTE + + .word 0,0,0 ++ .globl idt_descr + idt_descr: + .word 256*16-1 + .quad idt_table +--- a/xen/arch/x86/dmi_scan.c ++++ b/xen/arch/x86/dmi_scan.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #define bt_ioremap(b,l) ((void *)__acpi_map_table(b,l)) + #define bt_iounmap(b,l) ((void)0) +@@ -122,11 +123,39 @@ static inline bool_t __init dmi_checksum + return sum == 0; + } + ++static u32 __initdata efi_dmi_address; ++static u32 __initdata efi_dmi_size; ++ ++/* ++ * Important: This function gets called while still in EFI ++ * (pseudo-)physical mode. ++ */ ++void __init dmi_efi_get_table(void *smbios) ++{ ++ struct smbios_eps *eps = smbios; ++ ++ if (memcmp(eps->anchor, "_SM_", 4) && ++ dmi_checksum(eps, eps->length) && ++ memcmp(eps->dmi.anchor, "_DMI_", 5) == 0 && ++ dmi_checksum(&eps->dmi, sizeof(eps->dmi))) { ++ efi_dmi_address = eps->dmi.address; ++ efi_dmi_size = eps->dmi.size; ++ } ++} ++ + int __init dmi_get_table(u32 *base, u32 *len) + { + struct dmi_eps eps; + char __iomem *p, *q; + ++ if (efi_enabled) { ++ if (!efi_dmi_size) ++ return -1; ++ *base = efi_dmi_address; ++ *len = efi_dmi_size; ++ return 0; ++ } ++ + p = maddr_to_virt(0xF0000); + for (q = p; q < p + 0x10000; q += 16) { + memcpy_fromio(&eps, q, 15); +@@ -178,6 +207,39 @@ static int __init dmi_iterate(void (*dec + return -1; + } + ++static int __init dmi_efi_iterate(void (*decode)(struct dmi_header *)) ++{ ++ struct smbios_eps eps; ++ const struct smbios_eps __iomem *p; ++ int ret = -1; ++ ++ if (efi.smbios == EFI_INVALID_TABLE_ADDR) ++ return -1; ++ ++ p = bt_ioremap(efi.smbios, sizeof(eps)); ++ if (!p) ++ return -1; ++ memcpy_fromio(&eps, p, sizeof(eps)); ++ bt_iounmap(p, sizeof(eps)); ++ ++ if (memcmp(eps.anchor, "_SM_", 4)) ++ return -1; ++ ++ p = bt_ioremap(efi.smbios, eps.length); ++ if (!p) ++ return -1; ++ if (dmi_checksum(p, eps.length) && ++ memcmp(eps.dmi.anchor, "_DMI_", 5) == 0 && ++ dmi_checksum(&eps.dmi, sizeof(eps.dmi))) { ++ printk(KERN_INFO "SMBIOS %d.%d present.\n", ++ eps.major, eps.minor); ++ ret = _dmi_iterate(&eps.dmi, p, decode); ++ } ++ bt_iounmap(p, eps.length); ++ ++ return ret; ++} ++ + static char *dmi_ident[DMI_STRING_MAX]; + + /* +@@ -468,8 +530,8 @@ static void __init dmi_decode(struct dmi + + void __init dmi_scan_machine(void) + { +- int err = dmi_iterate(dmi_decode); +- if(err == 0) ++ if ((!efi_enabled ? dmi_iterate(dmi_decode) : ++ dmi_efi_iterate(dmi_decode)) == 0) + dmi_check_system(dmi_blacklist); + else + printk(KERN_INFO "DMI not present.\n"); +--- /dev/null ++++ b/xen/arch/x86/efi/Makefile +@@ -0,0 +1,17 @@ ++CFLAGS += -fshort-wchar -mno-sse ++ ++obj-y += stub.o ++ ++create = test -e $(1) || touch -t 199901010000 $(1) ++ ++efi := $(filter y,$(x86_64)$(shell rm -f disabled)) ++efi := $(if $(efi),$(shell $(CC) -c -Werror check.c 2>disabled && echo y)) ++efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2>disabled && echo y)) ++efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.o); $(call create,runtime.o))) ++ ++extra-$(efi) += boot.o relocs-dummy.o runtime.o compat.o ++ ++stub.o: $(extra-y) ++ ++clean:: ++ rm -f disabled *.efi +--- /dev/null ++++ b/xen/arch/x86/efi/boot.c +@@ -0,0 +1,1221 @@ ++#include "efi.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if EFI_PAGE_SIZE != PAGE_SIZE ++# error Cannot use xen/pfn.h here! ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern char start[]; ++extern u32 cpuid_ext_features; ++ ++union string { ++ CHAR16 *w; ++ char *s; ++ const char *cs; ++}; ++ ++struct file { ++ UINTN size; ++ union { ++ EFI_PHYSICAL_ADDRESS addr; ++ void *ptr; ++ }; ++}; ++ ++static EFI_BOOT_SERVICES *__initdata efi_bs; ++static EFI_HANDLE __initdata efi_ih; ++ ++static SIMPLE_TEXT_OUTPUT_INTERFACE __initdata *StdOut; ++static SIMPLE_TEXT_OUTPUT_INTERFACE __initdata *StdErr; ++ ++static UINT32 __initdata mdesc_ver; ++ ++static struct file __initdata cfg; ++static struct file __initdata kernel; ++static struct file __initdata ramdisk; ++static struct file __initdata xsm; ++ ++static multiboot_info_t __initdata mbi = { ++ .flags = MBI_MODULES | MBI_LOADERNAME ++}; ++static module_t __initdata mb_modules[3]; ++ ++static CHAR16 __initdata newline[] = L"\r\n"; ++ ++#define PrintStr(s) StdOut->OutputString(StdOut, s) ++#define PrintErr(s) StdErr->OutputString(StdErr, s) ++ ++static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer) ++{ ++ if ( Val >= 10 ) ++ Buffer = FormatDec(Val / 10, Buffer); ++ *Buffer = (CHAR16)(L'0' + Val % 10); ++ return Buffer + 1; ++} ++ ++static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer) ++{ ++ if ( Width > 1 || Val >= 0x10 ) ++ Buffer = FormatHex(Val >> 4, Width ? Width - 1 : 0, Buffer); ++ *Buffer = (CHAR16)((Val &= 0xf) < 10 ? L'0' + Val : L'a' + Val - 10); ++ return Buffer + 1; ++} ++ ++static void __init DisplayUint(UINT64 Val, INTN Width) ++{ ++ CHAR16 PrintString[32], *end; ++ ++ if (Width < 0) ++ end = FormatDec(Val, PrintString); ++ else ++ { ++ PrintStr(L"0x"); ++ end = FormatHex(Val, Width, PrintString); ++ } ++ *end = 0; ++ PrintStr(PrintString); ++} ++ ++static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s) ++{ ++ CHAR16 *r = d; ++ ++ while ( (*d++ = *s++) != 0 ) ++ ; ++ return r; ++} ++ ++static int __init wstrcmp(const CHAR16 *s1, const CHAR16 *s2) ++{ ++ while ( *s1 && *s1 == *s2 ) ++ { ++ ++s1; ++ ++s2; ++ } ++ return *s1 - *s2; ++} ++ ++static int __init wstrncmp(const CHAR16 *s1, const CHAR16 *s2, UINTN n) ++{ ++ while ( n && *s1 && *s1 == *s2 ) ++ { ++ --n; ++ ++s1; ++ ++s2; ++ } ++ return n ? *s1 - *s2 : 0; ++} ++ ++static CHAR16 *__init s2w(union string *str) ++{ ++ const char *s = str->s; ++ CHAR16 *w; ++ void *ptr; ++ ++ if ( efi_bs->AllocatePool(EfiLoaderData, (strlen(s) + 1) * sizeof(*w), ++ &ptr) != EFI_SUCCESS ) ++ return NULL; ++ ++ w = str->w = ptr; ++ do { ++ *w = *s++; ++ } while ( *w++ ); ++ ++ return str->w; ++} ++ ++static char *__init w2s(const union string *str) ++{ ++ const CHAR16 *w = str->w; ++ char *s = str->s; ++ ++ do { ++ if ( *w > 0x007f ) ++ return NULL; ++ *s = *w++; ++ } while ( *s++ ); ++ ++ return str->s; ++} ++ ++static bool_t __init match_guid(const EFI_GUID *guid1, const EFI_GUID *guid2) ++{ ++ return guid1->Data1 == guid2->Data1 && ++ guid1->Data2 == guid2->Data2 && ++ guid1->Data3 == guid2->Data3 && ++ !memcmp(guid1->Data4, guid2->Data4, sizeof(guid1->Data4)); ++} ++ ++static void __init __attribute__((__noreturn__)) blexit(const CHAR16 *str) ++{ ++ if ( str ) ++ PrintStr((CHAR16 *)str); ++ PrintStr(newline); ++ ++ if ( cfg.addr ) ++ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); ++ if ( kernel.addr ) ++ efi_bs->FreePages(kernel.addr, PFN_UP(kernel.size)); ++ if ( ramdisk.addr ) ++ efi_bs->FreePages(ramdisk.addr, PFN_UP(ramdisk.size)); ++ if ( xsm.addr ) ++ efi_bs->FreePages(xsm.addr, PFN_UP(xsm.size)); ++ ++ efi_bs->Exit(efi_ih, EFI_SUCCESS, 0, NULL); ++ for( ; ; ); /* not reached */ ++} ++ ++/* generic routine for printing error messages */ ++static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode) ++{ ++ StdOut = StdErr; ++ PrintErr((CHAR16 *)mesg); ++ PrintErr(L": "); ++ ++ switch (ErrCode) ++ { ++ case EFI_NOT_FOUND: ++ mesg = L"Not found"; ++ break; ++ case EFI_NO_MEDIA: ++ mesg = L"The device has no media"; ++ break; ++ case EFI_MEDIA_CHANGED: ++ mesg = L"Media changed"; ++ break; ++ case EFI_DEVICE_ERROR: ++ mesg = L"Device error"; ++ break; ++ case EFI_VOLUME_CORRUPTED: ++ mesg = L"Volume corrupted"; ++ break; ++ case EFI_ACCESS_DENIED: ++ mesg = L"Access denied"; ++ break; ++ case EFI_OUT_OF_RESOURCES: ++ mesg = L"Out of resources"; ++ break; ++ case EFI_VOLUME_FULL: ++ mesg = L"Volume is full"; ++ break; ++ default: ++ PrintErr(L"ErrCode: "); ++ DisplayUint(ErrCode, 0); ++ mesg = NULL; ++ break; ++ } ++ blexit(mesg); ++} ++ ++static void __init place_string(u32 *addr, const char *s) ++{ ++ static char *__initdata alloc = start; ++ ++ if ( s && *s ) ++ { ++ size_t len1 = strlen(s) + 1; ++ const char *old = (char *)(long)*addr; ++ size_t len2 = *addr ? strlen(old) + 1 : 0; ++ ++ alloc -= len1 + len2; ++ /* ++ * Insert new string before already existing one. This is needed ++ * for options passed on the command line to override options from ++ * the configuration file. ++ */ ++ memcpy(alloc, s, len1); ++ if ( *addr ) ++ { ++ alloc[len1 - 1] = ' '; ++ memcpy(alloc + len1, old, len2); ++ } ++ } ++ *addr = (long)alloc; ++} ++ ++static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, ++ CHAR16 *cmdline, UINTN cmdsize) ++{ ++ CHAR16 *ptr = (CHAR16 *)(argv + argc + 1), *prev = NULL; ++ bool_t prev_sep = TRUE; ++ ++ for ( ; cmdsize > sizeof(*cmdline) && *cmdline; ++ cmdsize -= sizeof(*cmdline), ++cmdline ) ++ { ++ bool_t cur_sep = *cmdline == L' ' || *cmdline == L'\t'; ++ ++ if ( !prev_sep ) ++ { ++ if ( cur_sep ) ++ ++ptr; ++ else if ( argv ) ++ { ++ *ptr = *cmdline; ++ *++ptr = 0; ++ } ++ } ++ else if ( !cur_sep ) ++ { ++ if ( !argv ) ++ ++argc; ++ else if ( prev && wstrcmp(prev, L"--") == 0 ) ++ { ++ union string rest = { .w = cmdline }; ++ ++ --argv; ++ place_string(&mbi.cmdline, w2s(&rest)); ++ break; ++ } ++ else ++ { ++ *argv++ = prev = ptr; ++ *ptr = *cmdline; ++ *++ptr = 0; ++ } ++ } ++ prev_sep = cur_sep; ++ } ++ if ( argv ) ++ *argv = NULL; ++ return argc; ++} ++ ++static EFI_FILE_HANDLE __init get_parent_handle(EFI_LOADED_IMAGE *loaded_image, ++ CHAR16 **leaf) ++{ ++ static EFI_GUID __initdata fs_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL; ++ EFI_FILE_HANDLE dir_handle; ++ EFI_DEVICE_PATH *dp; ++ CHAR16 *pathend, *ptr; ++ EFI_STATUS ret; ++ ++ do { ++ EFI_FILE_IO_INTERFACE *fio; ++ ++ /* Get the file system interface. */ ++ ret = efi_bs->HandleProtocol(loaded_image->DeviceHandle, ++ &fs_protocol, (void **)&fio); ++ if ( EFI_ERROR(ret) ) ++ blexit(L"Couldn't obtain the File System Protocol Interface"); ++ ret = fio->OpenVolume(fio, &dir_handle); ++ } while ( ret == EFI_MEDIA_CHANGED ); ++ if ( ret != EFI_SUCCESS ) ++ blexit(L"OpenVolume failure"); ++ ++#define buffer ((CHAR16 *)keyhandler_scratch) ++#define BUFFERSIZE sizeof(keyhandler_scratch) ++ for ( dp = loaded_image->FilePath, *buffer = 0; ++ DevicePathType(dp) != END_DEVICE_PATH_TYPE; ++ dp = (void *)dp + DevicePathNodeLength(dp) ) ++ { ++ FILEPATH_DEVICE_PATH *fp; ++ ++ if ( DevicePathType(dp) != MEDIA_DEVICE_PATH || ++ DevicePathSubType(dp) != MEDIA_FILEPATH_DP ) ++ blexit(L"Unsupported device path component"); ++ ++ if ( *buffer ) ++ { ++ EFI_FILE_HANDLE new_handle; ++ ++ ret = dir_handle->Open(dir_handle, &new_handle, buffer, ++ EFI_FILE_MODE_READ, 0); ++ if ( ret != EFI_SUCCESS ) ++ { ++ PrintErr(L"Open failed for "); ++ PrintErrMesg(buffer, ret); ++ } ++ dir_handle->Close(dir_handle); ++ dir_handle = new_handle; ++ } ++ fp = (void *)dp; ++ if ( BUFFERSIZE < DevicePathNodeLength(dp) - ++ sizeof(*dp) + sizeof(*buffer) ) ++ blexit(L"Increase BUFFERSIZE"); ++ memcpy(buffer, fp->PathName, DevicePathNodeLength(dp) - sizeof(*dp)); ++ buffer[(DevicePathNodeLength(dp) - sizeof(*dp)) / sizeof(*buffer)] = 0; ++ } ++ for ( ptr = buffer, pathend = NULL; *ptr; ++ptr ) ++ if ( *ptr == L'\\' ) ++ pathend = ptr; ++ if ( pathend ) ++ { ++ *pathend = 0; ++ *leaf = pathend + 1; ++ if ( *buffer ) ++ { ++ EFI_FILE_HANDLE new_handle; ++ ++ ret = dir_handle->Open(dir_handle, &new_handle, buffer, ++ EFI_FILE_MODE_READ, 0); ++ if ( ret != EFI_SUCCESS ) { ++ PrintErr(L"Open failed for "); ++ PrintErrMesg(buffer, ret); ++ } ++ dir_handle->Close(dir_handle); ++ dir_handle = new_handle; ++ } ++ } ++ else ++ *leaf = buffer; ++#undef BUFFERSIZE ++#undef buffer ++ ++ return dir_handle; ++} ++ ++static CHAR16 *__init point_tail(CHAR16 *fn) ++{ ++ CHAR16 *tail = NULL; ++ ++ for ( ; ; ++fn ) ++ switch ( *fn ) ++ { ++ case 0: ++ return tail; ++ case L'.': ++ case L'-': ++ case L'_': ++ tail = fn; ++ break; ++ } ++} ++ ++static bool_t __init read_file(EFI_FILE_HANDLE dir_handle, CHAR16 *name, ++ struct file *file) ++{ ++ EFI_FILE_HANDLE FileHandle = NULL; ++ UINT64 size; ++ EFI_STATUS ret; ++ CHAR16 *what = NULL; ++ ++ if ( !name ) ++ PrintErrMesg(L"No filename", EFI_OUT_OF_RESOURCES); ++ ret = dir_handle->Open(dir_handle, &FileHandle, name, ++ EFI_FILE_MODE_READ, 0); ++ if ( file == &cfg && ret == EFI_NOT_FOUND ) ++ return 0; ++ if ( EFI_ERROR(ret) ) ++ what = L"Open"; ++ else ++ ret = FileHandle->SetPosition(FileHandle, -1); ++ if ( EFI_ERROR(ret) ) ++ what = what ?: L"Seek"; ++ else ++ ret = FileHandle->GetPosition(FileHandle, &size); ++ if ( EFI_ERROR(ret) ) ++ what = what ?: L"Get size"; ++ else ++ ret = FileHandle->SetPosition(FileHandle, 0); ++ if ( EFI_ERROR(ret) ) ++ what = what ?: L"Seek"; ++ else ++ { ++ file->addr = (EFI_PHYSICAL_ADDRESS)1 << (32 + PAGE_SHIFT); ++ ret = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData, ++ PFN_UP(size), &file->addr); ++ } ++ if ( EFI_ERROR(ret) ) ++ { ++ file->addr = 0; ++ what = what ?: L"Allocation"; ++ } ++ else ++ { ++ if ( file != &cfg ) ++ { ++ PrintStr(name); ++ PrintStr(L": "); ++ DisplayUint(file->addr, 2 * sizeof(file->addr)); ++ PrintStr(L"-"); ++ DisplayUint(file->addr + size, 2 * sizeof(file->addr)); ++ PrintStr(newline); ++ mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT; ++ mb_modules[mbi.mods_count].mod_end = size; ++ ++mbi.mods_count; ++ } ++ ++ file->size = size; ++ ret = FileHandle->Read(FileHandle, &file->size, file->ptr); ++ if ( !EFI_ERROR(ret) && file->size != size ) ++ ret = EFI_ABORTED; ++ if ( EFI_ERROR(ret) ) ++ what = L"Read"; ++ } ++ ++ if ( FileHandle ) ++ FileHandle->Close(FileHandle); ++ ++ if ( what ) ++ { ++ PrintErr(what); ++ PrintErr(L" failed for "); ++ PrintErrMesg(name, ret); ++ } ++ ++ return 1; ++} ++ ++static void __init pre_parse(const struct file *cfg) ++{ ++ char *ptr = cfg->ptr, *end = ptr + cfg->size; ++ bool_t start = 1, comment = 0; ++ ++ for ( ; ptr < end; ++ptr ) ++ { ++ if ( iscntrl(*ptr) ) ++ { ++ comment = 0; ++ start = 1; ++ *ptr = 0; ++ } ++ else if ( comment || (start && isspace(*ptr)) ) ++ *ptr = 0; ++ else if ( *ptr == '#' || (start && *ptr == ';') ) ++ { ++ comment = 1; ++ *ptr = 0; ++ } ++ else ++ start = 0; ++ } ++ if ( cfg->size && end[-1] ) ++ PrintStr(L"No newline at end of config file," ++ " last line will be ignored.\r\n"); ++} ++ ++static char *__init get_value(const struct file *cfg, const char *section, ++ const char *item) ++{ ++ char *ptr = cfg->ptr, *end = ptr + cfg->size; ++ size_t slen = section ? strlen(section) : 0, ilen = strlen(item); ++ bool_t match = !slen; ++ ++ for ( ; ptr < end; ++ptr ) ++ { ++ switch ( *ptr ) ++ { ++ case 0: ++ continue; ++ case '[': ++ if ( !slen ) ++ break; ++ if ( match ) ++ return NULL; ++ match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']'; ++ break; ++ default: ++ if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' ) ++ return ptr + ilen + 1; ++ break; ++ } ++ ptr += strlen(ptr); ++ } ++ return NULL; ++} ++ ++static void __init split_value(char *s) ++{ ++ while ( *s && isspace(*s) ) ++ ++s; ++ place_string(&mb_modules[mbi.mods_count].string, s); ++ while ( *s && !isspace(*s) ) ++ ++s; ++ *s = 0; ++} ++ ++static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz) ++{ ++ if ( bpp < 0 ) ++ return bpp; ++ if ( !mask ) ++ return -EINVAL; ++ for ( *pos = 0; !(mask & 1); ++*pos ) ++ mask >>= 1; ++ for ( *sz = 0; mask & 1; ++sz) ++ mask >>= 1; ++ if ( mask ) ++ return -EINVAL; ++ return max(*pos + *sz, bpp); ++} ++ ++#define PE_BASE_RELOC_ABS 0 ++#define PE_BASE_RELOC_HIGHLOW 3 ++#define PE_BASE_RELOC_DIR64 10 ++ ++extern const struct pe_base_relocs { ++ u32 rva; ++ u32 size; ++ u16 entries[]; ++} __base_relocs_start[], __base_relocs_end[]; ++ ++static void __init relocate_image(unsigned long delta) ++{ ++ const struct pe_base_relocs *base_relocs; ++ ++ for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; ) ++ { ++ unsigned int i, n; ++ ++ n = (base_relocs->size - sizeof(*base_relocs)) / ++ sizeof(*base_relocs->entries); ++ for ( i = 0; i < n; ++i ) ++ { ++ unsigned long addr = xen_phys_start + base_relocs->rva + ++ (base_relocs->entries[i] & 0xfff); ++ ++ switch ( base_relocs->entries[i] >> 12 ) ++ { ++ case PE_BASE_RELOC_ABS: ++ break; ++ case PE_BASE_RELOC_HIGHLOW: ++ if ( delta ) ++ *(u32 *)addr += delta; ++ break; ++ case PE_BASE_RELOC_DIR64: ++ if ( delta ) ++ *(u64 *)addr += delta; ++ break; ++ default: ++ blexit(L"Unsupported relocation type\r\n"); ++ } ++ } ++ base_relocs = (const void *)(base_relocs->entries + i + (i & 1)); ++ } ++} ++ ++void EFIAPI __init __attribute__((__noreturn__)) ++efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) ++{ ++ static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL; ++ static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; ++ EFI_LOADED_IMAGE *loaded_image; ++ EFI_STATUS status; ++ unsigned int i, argc; ++ CHAR16 **argv, *file_name, *cfg_file_name = NULL; ++ UINTN cols, rows, depth, size, map_key, info_size, gop_mode = ~0; ++ EFI_HANDLE *handles = NULL; ++ EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; ++ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; ++ EFI_FILE_HANDLE dir_handle; ++ union string section = { NULL }, name; ++ struct e820entry *e; ++ u64 efer; ++ bool_t base_video = 0, trampoline_okay = 0; ++ ++ efi_ih = ImageHandle; ++ efi_bs = SystemTable->BootServices; ++ efi_rs = SystemTable->RuntimeServices; ++ efi_ct = SystemTable->ConfigurationTable; ++ efi_num_ct = SystemTable->NumberOfTableEntries; ++ efi_version = SystemTable->Hdr.Revision; ++ efi_fw_vendor = SystemTable->FirmwareVendor; ++ efi_fw_revision = SystemTable->FirmwareRevision; ++ ++ StdOut = SystemTable->ConOut; ++ StdErr = SystemTable->StdErr ?: StdOut; ++ ++ status = efi_bs->HandleProtocol(ImageHandle, &loaded_image_guid, ++ (void **)&loaded_image); ++ if ( status != EFI_SUCCESS ) ++ PrintErrMesg(L"No Loaded Image Protocol", status); ++ ++ xen_phys_start = (UINTN)loaded_image->ImageBase; ++ if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 ) ++ blexit(L"Xen must be loaded below 4Gb.\r\n"); ++ if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) ) ++ blexit(L"Xen must be loaded at a 2Mb boundary.\r\n"); ++ trampoline_xen_phys_start = xen_phys_start; ++ ++ /* Get the file system interface. */ ++ dir_handle = get_parent_handle(loaded_image, &file_name); ++ ++ argc = get_argv(0, NULL, loaded_image->LoadOptions, ++ loaded_image->LoadOptionsSize); ++ if ( argc > 0 && ++ efi_bs->AllocatePool(EfiLoaderData, ++ (argc + 1) * sizeof(*argv) + ++ loaded_image->LoadOptionsSize, ++ (void **)&argv) == EFI_SUCCESS ) ++ get_argv(argc, argv, loaded_image->LoadOptions, ++ loaded_image->LoadOptionsSize); ++ else ++ argc = 0; ++ for ( i = 1; i < argc; ++i ) ++ { ++ CHAR16 *ptr = argv[i]; ++ ++ if ( !ptr ) ++ break; ++ if ( *ptr == L'/' || *ptr == L'-' ) ++ { ++ if ( wstrcmp(ptr + 1, L"basevideo") == 0 ) ++ base_video = 1; ++ else if ( wstrncmp(ptr + 1, L"cfg=", 4) == 0 ) ++ cfg_file_name = ptr + 5; ++ else if ( i + 1 < argc && wstrcmp(ptr + 1, L"cfg") == 0 ) ++ cfg_file_name = argv[++i]; ++ else if ( wstrcmp(ptr + 1, L"help") == 0 || ++ (ptr[1] == L'?' && !ptr[2]) ) ++ { ++ PrintStr(L"Xen EFI Loader options:\r\n"); ++ PrintStr(L"-basevideo retain current video mode\r\n"); ++ PrintStr(L"-cfg= specify configuration file\r\n"); ++ PrintStr(L"-help, -? display this help\r\n"); ++ blexit(NULL); ++ } ++ else ++ { ++ PrintStr(L"WARNING: Unknown command line option '"); ++ PrintStr(ptr); ++ PrintStr(L"' ignored\r\n"); ++ } ++ } ++ else ++ section.w = ptr; ++ } ++ ++ if ( !base_video ) ++ { ++ unsigned int best; ++ ++ for ( i = 0, size = 0, best = StdOut->Mode->Mode; ++ i < StdOut->Mode->MaxMode; ++i ) ++ { ++ if ( StdOut->QueryMode(StdOut, i, &cols, &rows) == EFI_SUCCESS && ++ cols * rows > size ) ++ { ++ size = cols * rows; ++ best = i; ++ } ++ } ++ if ( best != StdOut->Mode->Mode ) ++ StdOut->SetMode(StdOut, best); ++ } ++ ++ PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION) ++ XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n"); ++ ++ relocate_image(0); ++ ++ if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode, ++ &cols, &rows) == EFI_SUCCESS ) ++ { ++ vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3; ++ vga_console_info.u.text_mode_3.columns = cols; ++ vga_console_info.u.text_mode_3.rows = rows; ++ vga_console_info.u.text_mode_3.font_height = 16; ++ } ++ ++ size = 0; ++ status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, NULL); ++ if ( status == EFI_BUFFER_TOO_SMALL ) ++ status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles); ++ if ( !EFI_ERROR(status) ) ++ status = efi_bs->LocateHandle(ByProtocol, &gop_guid, NULL, &size, ++ handles); ++ if ( EFI_ERROR(status) ) ++ size = 0; ++ for ( i = 0; i < size / sizeof(*handles); ++i ) ++ { ++ status = efi_bs->HandleProtocol(handles[i], &gop_guid, (void **)&gop); ++ if ( EFI_ERROR(status) ) ++ continue; ++ status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info); ++ if ( !EFI_ERROR(status) ) ++ break; ++ } ++ if ( handles ) ++ efi_bs->FreePool(handles); ++ if ( EFI_ERROR(status) ) ++ gop = NULL; ++ ++ /* Read and parse the config file. */ ++ if ( !cfg_file_name ) ++ { ++ CHAR16 *tail; ++ ++ while ( (tail = point_tail(file_name)) != NULL ) ++ { ++ wstrcpy(tail, L".cfg"); ++ if ( read_file(dir_handle, file_name, &cfg) ) ++ break; ++ *tail = 0; ++ } ++ if ( !tail ) ++ blexit(L"No configuration file found\r\n"); ++ PrintStr(L"Using configuration file '"); ++ PrintStr(file_name); ++ PrintStr(L"'\r\n"); ++ } ++ else if ( !read_file(dir_handle, cfg_file_name, &cfg) ) ++ blexit(L"Configuration file not found\r\n"); ++ pre_parse(&cfg); ++ ++ if ( section.w ) ++ w2s(§ion); ++ else ++ section.s = get_value(&cfg, "global", "default"); ++ ++ name.s = get_value(&cfg, section.s, "kernel"); ++ if ( !name.s ) ++ blexit(L"No Dom0 kernel image specified\r\n"); ++ split_value(name.s); ++ read_file(dir_handle, s2w(&name), &kernel); ++ efi_bs->FreePool(name.w); ++ ++ name.s = get_value(&cfg, section.s, "ramdisk"); ++ if ( name.s ) ++ { ++ split_value(name.s); ++ read_file(dir_handle, s2w(&name), &ramdisk); ++ efi_bs->FreePool(name.w); ++ } ++ ++ name.s = get_value(&cfg, section.s, "xsm"); ++ if ( name.s ) ++ { ++ split_value(name.s); ++ read_file(dir_handle, s2w(&name), &xsm); ++ efi_bs->FreePool(name.w); ++ } ++ ++ name.s = get_value(&cfg, section.s, "options"); ++ if ( name.s ) ++ place_string(&mbi.cmdline, name.s); ++ /* Insert image name last, as it gets prefixed to the other options. */ ++ if ( argc ) ++ { ++ name.w = *argv; ++ w2s(&name); ++ } ++ else ++ name.s = "xen"; ++ place_string(&mbi.cmdline, name.s); ++ ++ cols = rows = depth = 0; ++ if ( !base_video ) ++ { ++ name.cs = get_value(&cfg, section.s, "video"); ++ if ( !name.cs ) ++ name.cs = get_value(&cfg, "global", "video"); ++ if ( name.cs && !strncmp(name.cs, "gfx-", 4) ) ++ { ++ cols = simple_strtoul(name.cs + 4, &name.cs, 10); ++ if ( *name.cs == 'x' ) ++ rows = simple_strtoul(name.cs + 1, &name.cs, 10); ++ if ( *name.cs == 'x' ) ++ depth = simple_strtoul(name.cs + 1, &name.cs, 10); ++ if ( *name.cs ) ++ cols = rows = depth = 0; ++ } ++ } ++ ++ efi_bs->FreePages(cfg.addr, PFN_UP(cfg.size)); ++ cfg.addr = 0; ++ ++ dir_handle->Close(dir_handle); ++ ++ if ( gop && !base_video ) ++ { ++ for ( i = size = 0; i < gop->Mode->MaxMode; ++i ) ++ { ++ unsigned int bpp = 0; ++ ++ status = gop->QueryMode(gop, i, &info_size, &mode_info); ++ if ( EFI_ERROR(status) ) ++ continue; ++ switch ( mode_info->PixelFormat ) ++ { ++ case PixelBitMask: ++ bpp = hweight32(mode_info->PixelInformation.RedMask | ++ mode_info->PixelInformation.GreenMask | ++ mode_info->PixelInformation.BlueMask); ++ break; ++ case PixelRedGreenBlueReserved8BitPerColor: ++ case PixelBlueGreenRedReserved8BitPerColor: ++ bpp = 24; ++ break; ++ default: ++ continue; ++ } ++ if ( cols == mode_info->HorizontalResolution && ++ rows == mode_info->VerticalResolution && ++ (!depth || bpp == depth) ) ++ { ++ gop_mode = i; ++ break; ++ } ++ if ( !cols && !rows && ++ mode_info->HorizontalResolution * ++ mode_info->VerticalResolution > size ) ++ { ++ size = mode_info->HorizontalResolution * ++ mode_info->VerticalResolution; ++ gop_mode = i; ++ } ++ } ++ } ++ ++ if ( mbi.cmdline ) ++ mbi.flags |= MBI_CMDLINE; ++ /* ++ * These must not be initialized statically, since the value must ++ * not get relocated when processing base relocations below. ++ */ ++ mbi.boot_loader_name = (long)"EFI"; ++ mbi.mods_addr = (long)mb_modules; ++ ++ place_string(&mbi.mem_upper, NULL); ++ ++ /* XXX Collect EDD info. */ ++ /* XXX Collect EDID info. */ ++ ++ if ( cpuid_eax(0x80000000) > 0x80000000 ) ++ { ++ cpuid_ext_features = cpuid_edx(0x80000001); ++ boot_cpu_data.x86_capability[1] = cpuid_ext_features; ++ } ++ ++ /* Obtain basic table pointers. */ ++ for ( i = 0; i < efi_num_ct; ++i ) ++ { ++ static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID; ++ static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID; ++ static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID; ++ ++ if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) ) ++ efi.acpi20 = (long)efi_ct[i].VendorTable; ++ if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) ) ++ efi.acpi = (long)efi_ct[i].VendorTable; ++ if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) ) ++ efi.smbios = (long)efi_ct[i].VendorTable; ++ } ++ ++ if (efi.smbios != EFI_INVALID_TABLE_ADDR) ++ dmi_efi_get_table((void *)(long)efi.smbios); ++ ++ /* Allocate space for trampoline (in first Mb). */ ++ cfg.addr = BOOT_TRAMPOLINE; ++ cfg.size = trampoline_end - trampoline_start; ++ status = efi_bs->AllocatePages(AllocateAddress, EfiLoaderData, ++ PFN_UP(cfg.size), &cfg.addr); ++ if ( EFI_ERROR(status) ) ++ { ++ cfg.addr = 0; ++ PrintErr(L"Note: Trampoline area is in use\r\n"); ++ } ++ ++ /* Initialise L2 identity-map and xen page table entries (16MB). */ ++ for ( i = 0; i < 8; ++i ) ++ { ++ unsigned int slot = (xen_phys_start >> L2_PAGETABLE_SHIFT) + i; ++ paddr_t addr = slot << L2_PAGETABLE_SHIFT; ++ ++ l2_identmap[i] = l2e_from_paddr(i << L2_PAGETABLE_SHIFT, ++ PAGE_HYPERVISOR|_PAGE_PSE); ++ l2_identmap[slot] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE); ++ l2_xenmap[i] = l2e_from_paddr(addr, PAGE_HYPERVISOR|_PAGE_PSE); ++ slot &= L2_PAGETABLE_ENTRIES - 1; ++ l2_bootmap[slot] = l2e_from_paddr(addr, __PAGE_HYPERVISOR|_PAGE_PSE); ++ } ++ /* Initialise L3 identity-map page directory entries. */ ++ for ( i = 0; i < ARRAY_SIZE(l2_identmap) / L2_PAGETABLE_ENTRIES; ++i ) ++ l3_identmap[i] = l3e_from_paddr((UINTN)(l2_identmap + ++ i * L2_PAGETABLE_ENTRIES), ++ __PAGE_HYPERVISOR); ++ /* Initialise L3 xen-map page directory entry. */ ++ l3_xenmap[l3_table_offset(XEN_VIRT_START)] = ++ l3e_from_paddr((UINTN)l2_xenmap, __PAGE_HYPERVISOR); ++ /* Initialise L3 boot-map page directory entries. */ ++ l3_bootmap[l3_table_offset(xen_phys_start)] = ++ l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); ++ l3_bootmap[l3_table_offset(xen_phys_start + (8 << L2_PAGETABLE_SHIFT) - 1)] = ++ l3e_from_paddr((UINTN)l2_bootmap, __PAGE_HYPERVISOR); ++ /* Hook identity-map, xen-map, and boot-map L3 tables into PML4. */ ++ idle_pg_table[0] = l4e_from_paddr((UINTN)l3_bootmap, __PAGE_HYPERVISOR); ++ idle_pg_table[l4_table_offset(DIRECTMAP_VIRT_START)] = ++ l4e_from_paddr((UINTN)l3_identmap, __PAGE_HYPERVISOR); ++ idle_pg_table[l4_table_offset(XEN_VIRT_START)] = ++ l4e_from_paddr((UINTN)l3_xenmap, __PAGE_HYPERVISOR); ++ /* Initialize 4kB mappings of first 2MB of memory. */ ++ for ( i = 0; i < L1_PAGETABLE_ENTRIES; ++i ) ++ { ++ unsigned int attr = PAGE_HYPERVISOR|MAP_SMALL_PAGES; ++ ++ /* VGA hole (0xa0000-0xc0000) should be mapped UC. */ ++ if ( i >= 0xa0 && i < 0xc0 ) ++ attr |= _PAGE_PCD; ++ l1_identmap[i] = l1e_from_pfn(i, attr); ++ } ++ l2_identmap[0] = l2e_from_paddr((UINTN)l1_identmap, __PAGE_HYPERVISOR); ++ ++ if ( gop ) ++ { ++ int bpp = 0; ++ ++ /* Set graphics mode. */ ++ if ( gop_mode < gop->Mode->MaxMode && gop_mode != gop->Mode->Mode ) ++ gop->SetMode(gop, gop_mode); ++ ++ /* Get graphics and frame buffer info. */ ++ status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info); ++ if ( !EFI_ERROR(status) ) ++ switch ( mode_info->PixelFormat ) ++ { ++ case PixelRedGreenBlueReserved8BitPerColor: ++ vga_console_info.u.vesa_lfb.red_pos = 0; ++ vga_console_info.u.vesa_lfb.red_size = 8; ++ vga_console_info.u.vesa_lfb.green_pos = 8; ++ vga_console_info.u.vesa_lfb.green_size = 8; ++ vga_console_info.u.vesa_lfb.blue_pos = 16; ++ vga_console_info.u.vesa_lfb.blue_size = 8; ++ vga_console_info.u.vesa_lfb.rsvd_pos = 24; ++ vga_console_info.u.vesa_lfb.rsvd_size = 8; ++ bpp = 32; ++ break; ++ case PixelBlueGreenRedReserved8BitPerColor: ++ vga_console_info.u.vesa_lfb.red_pos = 16; ++ vga_console_info.u.vesa_lfb.red_size = 8; ++ vga_console_info.u.vesa_lfb.green_pos = 8; ++ vga_console_info.u.vesa_lfb.green_size = 8; ++ vga_console_info.u.vesa_lfb.blue_pos = 0; ++ vga_console_info.u.vesa_lfb.blue_size = 8; ++ vga_console_info.u.vesa_lfb.rsvd_pos = 24; ++ vga_console_info.u.vesa_lfb.rsvd_size = 8; ++ bpp = 32; ++ break; ++ case PixelBitMask: ++ bpp = set_color(mode_info->PixelInformation.RedMask, bpp, ++ &vga_console_info.u.vesa_lfb.red_pos, ++ &vga_console_info.u.vesa_lfb.red_size); ++ bpp = set_color(mode_info->PixelInformation.GreenMask, bpp, ++ &vga_console_info.u.vesa_lfb.green_pos, ++ &vga_console_info.u.vesa_lfb.green_size); ++ bpp = set_color(mode_info->PixelInformation.BlueMask, bpp, ++ &vga_console_info.u.vesa_lfb.blue_pos, ++ &vga_console_info.u.vesa_lfb.blue_size); ++ bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp, ++ &vga_console_info.u.vesa_lfb.rsvd_pos, ++ &vga_console_info.u.vesa_lfb.rsvd_size); ++ if ( bpp > 0 ) ++ break; ++ /* fall through */ ++ default: ++ PrintErr(L"Current graphics mode is unsupported!"); ++ status = EFI_UNSUPPORTED; ++ break; ++ } ++ if ( !EFI_ERROR(status) ) ++ { ++ vga_console_info.video_type = XEN_VGATYPE_EFI_LFB; ++ vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */ ++ vga_console_info.u.vesa_lfb.width = ++ mode_info->HorizontalResolution; ++ vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution; ++ vga_console_info.u.vesa_lfb.bits_per_pixel = bpp; ++ vga_console_info.u.vesa_lfb.bytes_per_line = ++ (mode_info->PixelsPerScanLine * bpp + 7) >> 3; ++ vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase; ++ vga_console_info.u.vesa_lfb.lfb_size = ++ (gop->Mode->FrameBufferSize + 0xffff) >> 16; ++ } ++ } ++ ++ status = efi_bs->GetMemoryMap(&efi_memmap_size, NULL, &map_key, ++ &efi_mdesc_size, &mdesc_ver); ++ mbi.mem_upper -= efi_memmap_size; ++ mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR); ++ if ( mbi.mem_upper < xen_phys_start ) ++ blexit(L"Out of static memory\r\n"); ++ efi_memmap = (void *)(long)mbi.mem_upper; ++ status = efi_bs->GetMemoryMap(&efi_memmap_size, efi_memmap, &map_key, ++ &efi_mdesc_size, &mdesc_ver); ++ if ( EFI_ERROR(status) ) ++ blexit(L"Cannot obtain memory map\r\n"); ++ ++ /* Populate E820 table and check trampoline area availability. */ ++ e = e820map - 1; ++ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) ++ { ++ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; ++ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; ++ u32 type; ++ ++ switch ( desc->Type ) ++ { ++ default: ++ type = E820_RESERVED; ++ break; ++ case EfiConventionalMemory: ++ case EfiLoaderCode: ++ case EfiLoaderData: ++ case EfiBootServicesCode: ++ case EfiBootServicesData: ++ if ( desc->Attribute & EFI_MEMORY_WB ) ++ type = E820_RAM; ++ else ++ case EfiUnusableMemory: ++ type = E820_UNUSABLE; ++ break; ++ case EfiACPIReclaimMemory: ++ type = E820_ACPI; ++ break; ++ case EfiACPIMemoryNVS: ++ type = E820_NVS; ++ break; ++ } ++ if ( e820nr && type == e->type && ++ desc->PhysicalStart == e->addr + e->size ) ++ e->size += len; ++ else if ( !len || e820nr >= E820MAX ) ++ continue; ++ else ++ { ++ ++e; ++ e->addr = desc->PhysicalStart; ++ e->size = len; ++ e->type = type; ++ ++e820nr; ++ } ++ if ( type == E820_RAM && e->addr <= BOOT_TRAMPOLINE && ++ e->addr + e->size >= BOOT_TRAMPOLINE + cfg.size ) ++ trampoline_okay = 1; ++ } ++ ++ if ( !trampoline_okay ) ++ blexit(L"Trampoline area unavailable\r\n"); ++ ++ status = efi_bs->ExitBootServices(ImageHandle, map_key); ++ if ( EFI_ERROR(status) ) ++ PrintErrMesg(L"Cannot exit boot services", status); ++ ++ /* Adjust pointers into EFI. */ ++ efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START; ++#if 0 /* Only needed when using virtual mode (see efi_init_memory()). */ ++ efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START; ++#endif ++ efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; ++ efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; ++ ++ relocate_image(__XEN_VIRT_START - xen_phys_start); ++ memcpy((void *)(long)BOOT_TRAMPOLINE, trampoline_start, cfg.size); ++ ++ /* Set system registers and transfer control. */ ++ asm volatile("pushq $0\n\tpopfq"); ++ rdmsrl(MSR_EFER, efer); ++ efer |= EFER_SCE; ++ if ( cpuid_ext_features & (1 << (X86_FEATURE_NX & 0x1f)) ) ++ efer |= EFER_NX; ++ wrmsrl(MSR_EFER, efer); ++ write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | ++ X86_CR0_AM | X86_CR0_PG); ++ asm volatile ( "mov %[cr4], %%cr4\n\t" ++ "mov %[cr3], %%cr3\n\t" ++ "movabs $__start_xen, %[rip]\n\t" ++ "lidt idt_descr(%%rip)\n\t" ++ "lgdt gdt_descr(%%rip)\n\t" ++ "mov stack_start(%%rip), %%rsp\n\t" ++ "mov %[ds], %%ss\n\t" ++ "mov %[ds], %%ds\n\t" ++ "mov %[ds], %%es\n\t" ++ "mov %[ds], %%fs\n\t" ++ "mov %[ds], %%gs\n\t" ++ "movl %[cs], 8(%%rsp)\n\t" ++ "mov %[rip], (%%rsp)\n\t" ++ "lretq %[stkoff]-16" ++ : [rip] "=&r" (efer/* any dead 64-bit variable */) ++ : [cr3] "r" (idle_pg_table), ++ [cr4] "r" (mmu_cr4_features), ++ [cs] "ir" (__HYPERVISOR_CS), ++ [ds] "r" (__HYPERVISOR_DS), ++ [stkoff] "i" (STACK_SIZE - sizeof(struct cpu_info)), ++ "D" (&mbi) ++ : "memory" ); ++ for( ; ; ); /* not reached */ ++} ++ ++void __init efi_init_memory(void) ++{ ++ unsigned int i; ++ ++ printk(XENLOG_INFO "EFI memory map:\n"); ++ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) ++ { ++ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; ++ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; ++ unsigned long smfn, emfn; ++ unsigned int prot = PAGE_HYPERVISOR; ++ ++ printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64 ++ " type=%u attr=%016" PRIx64 "\n", ++ desc->PhysicalStart, desc->PhysicalStart + len - 1, ++ desc->Type, desc->Attribute); ++ ++ if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) ) ++ continue; ++ ++ smfn = PFN_DOWN(desc->PhysicalStart); ++ emfn = PFN_UP(desc->PhysicalStart + len); ++ ++ desc->VirtualStart = 0xBAAADUL << (EFI_PAGE_SHIFT + BITS_PER_LONG - 32); ++ ++ if ( desc->Attribute & EFI_MEMORY_WB ) ++ /* nothing */; ++ else if ( desc->Attribute & EFI_MEMORY_WT ) ++ prot |= _PAGE_PWT | MAP_SMALL_PAGES; ++ else if ( desc->Attribute & EFI_MEMORY_WC ) ++ prot |= _PAGE_PAT | MAP_SMALL_PAGES; ++ else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) ) ++ prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES; ++ else ++ { ++ printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n", ++ smfn, emfn - 1); ++ continue; ++ } ++ ++ if ( desc->Attribute & EFI_MEMORY_WP ) ++ prot &= _PAGE_RW; ++ if ( desc->Attribute & EFI_MEMORY_XP ) ++ prot |= _PAGE_NX_BIT; ++ ++ if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) && ++ !(smfn & pfn_hole_mask) && ++ !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) ) ++ { ++ if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn), ++ smfn, emfn - smfn, prot) == 0 ) ++ desc->VirtualStart = ++ (unsigned long)maddr_to_virt(desc->PhysicalStart); ++ else ++ printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n", ++ smfn, emfn - 1); ++ } ++ else ++ { ++ /* XXX allocate e.g. down from FIXADDR_START */ ++ printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n", ++ smfn, emfn - 1); ++ } ++ } ++ ++#if 0 /* Incompatible with kexec. */ ++ efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size, ++ mdesc_ver, efi_memmap); ++#endif ++} +--- /dev/null ++++ b/xen/arch/x86/efi/check.c +@@ -0,0 +1,4 @@ ++int __attribute__((__ms_abi__)) test(int i) ++{ ++ return i; ++} +--- /dev/null ++++ b/xen/arch/x86/efi/compat.c +@@ -0,0 +1,16 @@ ++#include ++#include ++ ++#define efi_get_info efi_compat_get_info ++#define xenpf_efi_info compat_pf_efi_info ++ ++#define COMPAT ++#undef DEFINE_XEN_GUEST_HANDLE ++#define DEFINE_XEN_GUEST_HANDLE DEFINE_COMPAT_HANDLE ++#undef guest_handle_okay ++#define guest_handle_okay compat_handle_okay ++#undef guest_handle_cast ++#define guest_handle_cast compat_handle_cast ++#undef __copy_to_guest_offset ++#define __copy_to_guest_offset __copy_to_compat_offset ++#include "runtime.c" +--- /dev/null ++++ b/xen/arch/x86/efi/efi.h +@@ -0,0 +1,18 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern unsigned int efi_num_ct; ++extern EFI_CONFIGURATION_TABLE *efi_ct; ++ ++extern unsigned int efi_version, efi_fw_revision; ++extern const CHAR16 *efi_fw_vendor; ++ ++extern EFI_RUNTIME_SERVICES *efi_rs; ++ ++extern UINTN efi_memmap_size, efi_mdesc_size; ++extern void *efi_memmap; +--- /dev/null ++++ b/xen/arch/x86/efi/mkreloc.c +@@ -0,0 +1,377 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct mz_hdr { ++ uint16_t signature; ++#define MZ_SIGNATURE 0x5a4d ++ uint16_t last_page_size; ++ uint16_t page_count; ++ uint16_t relocation_count; ++ uint16_t header_paras; ++ uint16_t min_paras; ++ uint16_t max_paras; ++ uint16_t entry_ss; ++ uint16_t entry_sp; ++ uint16_t checksum; ++ uint16_t entry_ip; ++ uint16_t entry_cs; ++ uint16_t relocations; ++ uint16_t overlay; ++ uint8_t reserved[32]; ++ uint32_t extended_header_base; ++}; ++ ++struct pe_hdr { ++ uint32_t signature; ++#define PE_SIGNATURE 0x00004550 ++ uint16_t cpu; ++ uint16_t section_count; ++ int32_t timestamp; ++ uint32_t symbols_file_offset; ++ uint32_t symbol_count; ++ uint16_t opt_hdr_size; ++ uint16_t flags; ++ struct { ++ uint16_t magic; ++#define PE_MAGIC_EXE32 0x010b ++#define PE_MAGIC_EXE32PLUS 0x020b ++ uint8_t linker_major, linker_minor; ++ uint32_t code_size, data_size, bss_size; ++ uint32_t entry_rva, code_rva, data_rva; ++ } opt_hdr; ++}; ++ ++#define PE_PAGE_SIZE 0x1000 ++ ++#define PE_BASE_RELOC_ABS 0 ++#define PE_BASE_RELOC_HIGHLOW 3 ++#define PE_BASE_RELOC_DIR64 10 ++ ++struct coff_section { ++ char name[8]; ++ uint32_t size; ++ uint32_t rva; ++ uint32_t file_size; ++ uint32_t file_offset; ++ uint32_t relocation_file_offset; ++ uint32_t line_number_file_offset; ++ uint16_t relocation_count; ++ uint16_t line_number_count; ++ uint32_t flags; ++#define COFF_SECTION_BSS 0x00000080 ++#define COFF_SECTION_DISCARDABLE 0x02000000 ++}; ++ ++static void usage(const char *cmd, int rc) ++{ ++ fprintf(rc ? stderr : stdout, ++ "Usage: %s \n", ++ cmd); ++ exit(rc); ++} ++ ++static unsigned int load(const char *name, int *handle, ++ struct coff_section **sections, ++ uint_fast64_t *image_base, ++ uint32_t *image_size, ++ unsigned int *width) ++{ ++ int in = open(name, O_RDONLY); ++ struct mz_hdr mz_hdr; ++ struct pe_hdr pe_hdr; ++ uint32_t base; ++ ++ if ( in < 0 || ++ read(in, &mz_hdr, sizeof(mz_hdr)) != sizeof(mz_hdr) ) ++ { ++ perror(name); ++ exit(2); ++ } ++ if ( mz_hdr.signature != MZ_SIGNATURE || ++ mz_hdr.relocations < sizeof(mz_hdr) || ++ !mz_hdr.extended_header_base ) ++ { ++ fprintf(stderr, "%s: Wrong DOS file format\n", name); ++ exit(2); ++ } ++ ++ if ( lseek(in, mz_hdr.extended_header_base, SEEK_SET) < 0 || ++ read(in, &pe_hdr, sizeof(pe_hdr)) != sizeof(pe_hdr) || ++ read(in, &base, sizeof(base)) != sizeof(base) || ++ /* ++ * Luckily the image size field lives at the ++ * same offset for both formats. ++ */ ++ lseek(in, 24, SEEK_CUR) < 0 || ++ read(in, image_size, sizeof(*image_size)) != sizeof(*image_size) ) ++ { ++ perror(name); ++ exit(3); ++ } ++ switch ( (pe_hdr.signature == PE_SIGNATURE && ++ pe_hdr.opt_hdr_size > sizeof(pe_hdr.opt_hdr)) * ++ pe_hdr.opt_hdr.magic ) ++ { ++ case PE_MAGIC_EXE32: ++ *width = 32; ++ *image_base = base; ++ break; ++ case PE_MAGIC_EXE32PLUS: ++ *width = 64; ++ *image_base = ((uint64_t)base << 32) | pe_hdr.opt_hdr.data_rva; ++ break; ++ default: ++ fprintf(stderr, "%s: Wrong PE file format\n", name); ++ exit(3); ++ } ++ ++ *sections = malloc(pe_hdr.section_count * sizeof(**sections)); ++ if ( !*sections ) ++ { ++ perror(NULL); ++ exit(4); ++ } ++ if ( lseek(in, ++ mz_hdr.extended_header_base + offsetof(struct pe_hdr, opt_hdr) + ++ pe_hdr.opt_hdr_size, ++ SEEK_SET) < 0 || ++ read(in, *sections, pe_hdr.section_count * sizeof(**sections)) != ++ pe_hdr.section_count * sizeof(**sections) ) ++ { ++ perror(name); ++ exit(4); ++ } ++ ++ *handle = in; ++ ++ return pe_hdr.section_count; ++} ++ ++static long page_size; ++ ++static const void *map_section(const struct coff_section *sec, int in, ++ const char *name) ++{ ++ const char *ptr; ++ unsigned long offs; ++ ++ if ( !page_size ) ++ page_size = sysconf(_SC_PAGESIZE); ++ offs = sec->file_offset & (page_size - 1); ++ ++ ptr = mmap(0, offs + sec->file_size, PROT_READ, MAP_PRIVATE, in, ++ sec->file_offset - offs); ++ if ( ptr == MAP_FAILED ) ++ { ++ perror(name); ++ exit(6); ++ } ++ ++ return ptr + offs; ++} ++ ++static void unmap_section(const void *ptr, const struct coff_section *sec) ++{ ++ unsigned long offs = sec->file_offset & (page_size - 1); ++ ++ munmap((char *)ptr - offs, offs + sec->file_size); ++} ++ ++static void diff_sections(const unsigned char *ptr1, const unsigned char *ptr2, ++ const struct coff_section *sec, ++ int_fast64_t diff, unsigned int width, ++ uint_fast64_t base, uint_fast64_t end) ++{ ++ static uint_fast32_t cur_rva, reloc_size; ++ unsigned int disp = 0; ++ uint_fast32_t i; ++ ++ if ( !sec ) ++ { ++ reloc_size += reloc_size & 2; ++ if ( reloc_size ) ++ printf("\t.balign 4\n" ++ "\t.equ rva_%08" PRIxFAST32 "_relocs, %#08" PRIxFAST32 "\n", ++ cur_rva, reloc_size); ++ return; ++ } ++ ++ while ( !(diff & (((int_fast64_t)1 << ((disp + 1) * CHAR_BIT)) - 1)) ) ++ ++disp; ++ ++ for ( i = 0; i < sec->file_size; ++i ) ++ { ++ uint_fast32_t rva; ++ union { ++ uint32_t u32; ++ uint64_t u64; ++ } val1, val2; ++ int_fast64_t delta; ++ unsigned int reloc = (width == 4 ? PE_BASE_RELOC_HIGHLOW : ++ PE_BASE_RELOC_DIR64); ++ ++ if ( ptr1[i] == ptr2[i] ) ++ continue; ++ ++ if ( i < disp || i + width - disp > sec->file_size ) ++ { ++ fprintf(stderr, ++ "Bogus difference at %s:%08" PRIxFAST32 "\n", ++ sec->name, i); ++ exit(3); ++ } ++ ++ memcpy(&val1, ptr1 + i - disp, width); ++ memcpy(&val2, ptr2 + i - disp, width); ++ delta = width == 4 ? val2.u32 - val1.u32 : val2.u64 - val1.u64; ++ if ( delta != diff ) ++ { ++ fprintf(stderr, ++ "Difference at %s:%08" PRIxFAST32 " is %#" PRIxFAST64 ++ " (expected %#" PRIxFAST64 ")\n", ++ sec->name, i, delta, diff); ++ continue; ++ } ++ if ( width == 8 && (val1.u64 < base || val1.u64 > end) ) ++ reloc = PE_BASE_RELOC_HIGHLOW; ++ ++ rva = (sec->rva + i - disp) & ~(PE_PAGE_SIZE - 1); ++ if ( rva > cur_rva ) ++ { ++ reloc_size += reloc_size & 2; ++ if ( reloc_size ) ++ printf("\t.equ rva_%08" PRIxFAST32 "_relocs," ++ " %#08" PRIxFAST32 "\n", ++ cur_rva, reloc_size); ++ printf("\t.balign 4\n" ++ "\t.long %#08" PRIxFAST32 "," ++ " rva_%08" PRIxFAST32 "_relocs\n", ++ rva, rva); ++ cur_rva = rva; ++ reloc_size = 8; ++ } ++ else if ( rva != cur_rva ) ++ { ++ fprintf(stderr, ++ "Cannot handle decreasing RVA (at %s:%08" PRIxFAST32 ")\n", ++ sec->name, i); ++ exit(3); ++ } ++ ++ printf("\t.word (%u << 12) | 0x%03" PRIxFAST32 "\n", ++ reloc, sec->rva + i - disp - rva); ++ reloc_size += 2; ++ i += width - disp - 1; ++ } ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int in1, in2; ++ unsigned int i, nsec, width1, width2; ++ uint_fast64_t base1, base2; ++ uint32_t size1, size2; ++ struct coff_section *sec1, *sec2; ++ ++ if ( argc == 1 || ++ !strcmp(argv[1], "-?") || ++ !strcmp(argv[1], "-h") || ++ !strcmp(argv[1], "--help") ) ++ usage(*argv, argc == 1); ++ ++ if ( argc != 3 ) ++ usage(*argv, 1); ++ ++ nsec = load(argv[1], &in1, &sec1, &base1, &size1, &width1); ++ if ( nsec != load(argv[2], &in2, &sec2, &base2, &size2, &width2) ) ++ { ++ fputs("Mismatched section counts\n", stderr); ++ return 5; ++ } ++ if ( width1 != width2 ) ++ { ++ fputs("Mismatched image types\n", stderr); ++ return 5; ++ } ++ width1 >>= 3; ++ if ( base1 == base2 ) ++ { ++ fputs("Images must have different base addresses\n", stderr); ++ return 5; ++ } ++ if ( size1 != size2 ) ++ { ++ fputs("Images must have identical sizes\n", stderr); ++ return 5; ++ } ++ ++ puts("\t.section .reloc, \"a\", @progbits\n" ++ "\t.balign 4\n" ++ "\t.globl __base_relocs_start, __base_relocs_end\n" ++ "__base_relocs_start:"); ++ ++ for ( i = 0; i < nsec; ++i ) ++ { ++ const void *ptr1, *ptr2; ++ ++ if ( memcmp(sec1[i].name, sec2[i].name, sizeof(sec1[i].name)) || ++ sec1[i].rva != sec2[i].rva || ++ sec1[i].size != sec2[i].size || ++ sec1[i].file_size != sec2[i].file_size || ++ sec1[i].flags != sec2[i].flags ) ++ { ++ fprintf(stderr, "Mismatched section %u parameters\n", i); ++ return 5; ++ } ++ ++ if ( !sec1[i].size || ++ (sec1[i].flags & (COFF_SECTION_DISCARDABLE|COFF_SECTION_BSS)) ) ++ continue; ++ ++ /* ++ * Don't generate relocations for sections that definitely ++ * aren't used by the boot loader code. ++ */ ++ if ( memcmp(sec1[i].name, ".initcal", sizeof(sec1[i].name)) == 0 || ++ memcmp(sec1[i].name, ".init.se", sizeof(sec1[i].name)) == 0 || ++ memcmp(sec1[i].name, ".lockpro", sizeof(sec1[i].name)) == 0 ) ++ continue; ++ ++ if ( !sec1[i].rva ) ++ { ++ fprintf(stderr, "Can't handle section %u with zero RVA\n", i); ++ return 3; ++ } ++ ++ if ( sec1[i].file_size > sec1[i].size ) ++ { ++ sec1[i].file_size = sec1[i].size; ++ sec2[i].file_size = sec2[i].size; ++ } ++ ptr1 = map_section(sec1 + i, in1, argv[1]); ++ ptr2 = map_section(sec2 + i, in2, argv[2]); ++ ++ diff_sections(ptr1, ptr2, sec1 + i, base2 - base1, width1, ++ base1, base1 + size1); ++ ++ unmap_section(ptr1, sec1 + i); ++ unmap_section(ptr2, sec2 + i); ++ } ++ ++ diff_sections(NULL, NULL, NULL, 0, 0, 0, 0); ++ ++ puts("__base_relocs_end:"); ++ ++ close(in1); ++ close(in2); ++ ++ return 0; ++} +--- /dev/null ++++ b/xen/arch/x86/efi/relocs-dummy.S +@@ -0,0 +1,13 @@ ++#include ++ ++ .section .reloc, "a", @progbits ++ .balign 4 ++ .globl __base_relocs_start, __base_relocs_end ++__base_relocs_start: ++ .long 0 ++ .long 8 ++__base_relocs_end: ++ ++ .globl VIRT_START, ALT_START ++ .equ VIRT_START, XEN_VIRT_START ++ .equ ALT_START, XEN_VIRT_END +--- /dev/null ++++ b/xen/arch/x86/efi/runtime.c +@@ -0,0 +1,88 @@ ++#include "efi.h" ++#include ++#include ++#include ++ ++DEFINE_XEN_GUEST_HANDLE(CHAR16); ++ ++#ifndef COMPAT ++ ++# include ++ ++const bool_t efi_enabled = 1; ++ ++unsigned int __read_mostly efi_num_ct; ++EFI_CONFIGURATION_TABLE *__read_mostly efi_ct; ++ ++unsigned int __read_mostly efi_version; ++unsigned int __read_mostly efi_fw_revision; ++const CHAR16 *__read_mostly efi_fw_vendor; ++ ++EFI_RUNTIME_SERVICES *__read_mostly efi_rs; ++ ++UINTN __read_mostly efi_memmap_size; ++UINTN __read_mostly efi_mdesc_size; ++void *__read_mostly efi_memmap; ++ ++struct efi __read_mostly efi = { ++ .acpi = EFI_INVALID_TABLE_ADDR, ++ .acpi20 = EFI_INVALID_TABLE_ADDR, ++ .smbios = EFI_INVALID_TABLE_ADDR, ++}; ++ ++#endif ++ ++int efi_get_info(uint32_t idx, union xenpf_efi_info *info) ++{ ++ unsigned int i, n; ++ ++ switch ( idx ) ++ { ++ case XEN_FW_EFI_VERSION: ++ info->version = efi_version; ++ break; ++ case XEN_FW_EFI_CONFIG_TABLE: ++ info->cfg.addr = __pa(efi_ct); ++ info->cfg.nent = efi_num_ct; ++ break; ++ case XEN_FW_EFI_VENDOR: ++ info->vendor.revision = efi_fw_revision; ++ n = info->vendor.bufsz / sizeof(*efi_fw_vendor); ++ if ( !guest_handle_okay(guest_handle_cast(info->vendor.name, ++ CHAR16), n) ) ++ return -EFAULT; ++ for ( i = 0; i < n; ++i ) ++ { ++ if ( __copy_to_guest_offset(info->vendor.name, i, ++ efi_fw_vendor + i, 1) ) ++ return -EFAULT; ++ if ( !efi_fw_vendor[i] ) ++ break; ++ } ++ break; ++ case XEN_FW_EFI_MEM_INFO: ++ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) ++ { ++ EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; ++ u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; ++ ++ if ( info->mem.addr >= desc->PhysicalStart && ++ info->mem.addr < desc->PhysicalStart + len ) ++ { ++ info->mem.type = desc->Type; ++ info->mem.attr = desc->Attribute; ++ if ( info->mem.addr + info->mem.size < info->mem.addr || ++ info->mem.addr + info->mem.size > ++ desc->PhysicalStart + len ) ++ info->mem.size = desc->PhysicalStart + len - ++ info->mem.addr; ++ return 0; ++ } ++ } ++ return -ESRCH; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/xen/arch/x86/efi/stub.c +@@ -0,0 +1,17 @@ ++#include ++#include ++#include ++ ++#ifndef efi_enabled ++const bool_t efi_enabled = 0; ++#endif ++ ++void __init efi_init_memory(void) { } ++ ++int efi_get_info(uint32_t idx, union xenpf_efi_info *info) ++{ ++ return -ENOSYS; ++} ++ ++int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *) ++ __attribute__((__alias__("efi_get_info"))); +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -100,6 +100,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -353,6 +354,8 @@ void __init arch_init_memory(void) + + subarch_init_memory(); + ++ efi_init_memory(); ++ + mem_sharing_init(); + } + +--- a/xen/arch/x86/platform_hypercall.c ++++ b/xen/arch/x86/platform_hypercall.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -294,6 +295,14 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe + bootsym(boot_edid_info), 128) ) + ret = -EFAULT; + break; ++ case XEN_FW_EFI_INFO: ++ ret = efi_get_info(op->u.firmware_info.index, ++ &op->u.firmware_info.u.efi_info); ++ if ( ret == 0 && ++ copy_field_to_guest(u_xenpf_op, op, ++ u.firmware_info.u.efi_info) ) ++ ret = -EFAULT; ++ break; + default: + ret = -EINVAL; + break; +--- a/xen/arch/x86/setup.c ++++ b/xen/arch/x86/setup.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -448,6 +449,10 @@ static void __init parse_video_info(void + { + struct boot_video_info *bvi = &bootsym(boot_vid_info); + ++ /* The EFI loader fills vga_console_info directly. */ ++ if ( efi_enabled ) ++ return; ++ + if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) ) + { + vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3; +@@ -619,6 +624,7 @@ void __init __start_xen(unsigned long mb + vga_console_info.u.text_mode_3.font_height); + break; + case XEN_VGATYPE_VESA_LFB: ++ case XEN_VGATYPE_EFI_LFB: + printk(" VGA is graphics mode %dx%d, %d bpp\n", + vga_console_info.u.vesa_lfb.width, + vga_console_info.u.vesa_lfb.height, +@@ -664,7 +670,24 @@ void __init __start_xen(unsigned long mb + if ( ((unsigned long)cpu0_stack & (STACK_SIZE-1)) != 0 ) + EARLY_FAIL("Misaligned CPU0 stack.\n"); + +- if ( e820_raw_nr != 0 ) ++ if ( efi_enabled ) ++ { ++ set_pdx_range(xen_phys_start >> PAGE_SHIFT, ++ (xen_phys_start + BOOTSTRAP_MAP_BASE) >> PAGE_SHIFT); ++ ++ /* Clean up boot loader identity mappings. */ ++ destroy_xen_mappings(xen_phys_start, ++ xen_phys_start + BOOTSTRAP_MAP_BASE); ++ ++#ifdef CONFIG_X86_64 ++ /* Make boot page tables match non-EFI boot. */ ++ l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] = ++ l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR); ++#endif ++ ++ memmap_type = loader; ++ } ++ else if ( e820_raw_nr != 0 ) + { + memmap_type = "Xen-e820"; + } +@@ -762,7 +785,7 @@ void __init __start_xen(unsigned long mb + * we can relocate the dom0 kernel and other multiboot modules. Also, on + * x86/64, we relocate Xen to higher memory. + */ +- for ( i = 0; i < mbi->mods_count; i++ ) ++ for ( i = 0; !efi_enabled && i < mbi->mods_count; i++ ) + { + if ( mod[i].mod_start & (PAGE_SIZE - 1) ) + EARLY_FAIL("Bootloader didn't honor module alignment request.\n"); +@@ -811,7 +834,6 @@ void __init __start_xen(unsigned long mb + end = 0; + if ( end > s ) + { +- extern l2_pgentry_t l2_xenmap[]; + l4_pgentry_t *pl4e; + l3_pgentry_t *pl3e; + l2_pgentry_t *pl2e; +@@ -951,7 +973,8 @@ void __init __start_xen(unsigned long mb + #else + if ( !xen_phys_start ) + EARLY_FAIL("Not enough memory to relocate Xen.\n"); +- reserve_e820_ram(&boot_e820, __pa(&_start), __pa(&_end)); ++ reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start), ++ __pa(&_end)); + #endif + + /* Late kexec reservation (dynamic start address). */ +--- a/xen/arch/x86/x86_32/mm.c ++++ b/xen/arch/x86/x86_32/mm.c +@@ -34,8 +34,6 @@ + l2_pgentry_t __attribute__ ((__section__ (".bss.page_aligned"))) + idle_pg_table_l2[4 * L2_PAGETABLE_ENTRIES]; + +-extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES]; +- + unsigned int __read_mostly PAGE_HYPERVISOR = __PAGE_HYPERVISOR; + unsigned int __read_mostly PAGE_HYPERVISOR_NOCACHE = __PAGE_HYPERVISOR_NOCACHE; + +--- a/xen/arch/x86/x86_64/mm.c ++++ b/xen/arch/x86/x86_64/mm.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -828,7 +829,8 @@ void __init zap_low_mappings(void) + + /* Replace with mapping of the boot trampoline only. */ + map_pages_to_xen(BOOT_TRAMPOLINE, BOOT_TRAMPOLINE >> PAGE_SHIFT, +- 0x10, __PAGE_HYPERVISOR); ++ PFN_UP(trampoline_end - trampoline_start), ++ __PAGE_HYPERVISOR); + } + + void *compat_arg_xlat_virt_base(void) +--- a/xen/arch/x86/x86_64/platform_hypercall.c ++++ b/xen/arch/x86/x86_64/platform_hypercall.c +@@ -11,6 +11,8 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_ + #define xen_platform_op_t compat_platform_op_t + #define do_platform_op(x) compat_platform_op(_##x) + ++#define efi_get_info efi_compat_get_info ++ + #define xen_processor_px compat_processor_px + #define xen_processor_px_t compat_processor_px_t + #define xen_processor_performance compat_processor_performance +--- a/xen/arch/x86/xen.lds.S ++++ b/xen/arch/x86/xen.lds.S +@@ -8,15 +8,34 @@ + #undef ENTRY + #undef ALIGN + ++#ifdef EFI ++ ++#define FORMAT "pei-x86-64" ++#undef __XEN_VIRT_START ++#define __XEN_VIRT_START __image_base__ ++ ++ENTRY(efi_start) ++ ++#else /* !EFI */ ++ ++#ifdef __x86_64__ ++#define FORMAT "elf64-x86-64" ++#else ++#define FORMAT "elf32-i386" ++#endif ++ ++ENTRY(start) ++ ++#endif /* EFI */ ++ ++OUTPUT_FORMAT(FORMAT, FORMAT, FORMAT) ++ + #ifdef __x86_64__ +-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") + OUTPUT_ARCH(i386:x86-64) + #else +-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") + OUTPUT_ARCH(i386) + #endif + +-ENTRY(start) + PHDRS + { + text PT_LOAD ; +@@ -122,12 +141,29 @@ SECTIONS + } :text + _end = . ; + ++#ifdef EFI ++ . = ALIGN(4); ++ .reloc : { ++ *(.reloc) ++ } :text ++ /* Trick the linker into setting the image size to exactly 16Mb. */ ++ . = ALIGN(__section_alignment__); ++ .pad : { ++ . = ALIGN(0x1000000); ++ } :text ++#else ++ efi = .; ++#endif ++ + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + *(.eh_frame) ++#ifdef EFI ++ *(.comment) ++#endif + } + + /* Stabs debugging sections. */ +--- a/xen/drivers/acpi/osl.c ++++ b/xen/drivers/acpi/osl.c +@@ -37,9 +37,7 @@ + #include + #include + #include +-#ifdef __ia64__ +-#include +-#endif ++#include + + #define _COMPONENT ACPI_OS_SERVICES + ACPI_MODULE_NAME("osl") +@@ -82,7 +80,6 @@ void acpi_os_vprintf(const char *fmt, va + + acpi_physical_address __init acpi_os_get_root_pointer(void) + { +-#ifdef __ia64__ + if (efi_enabled) { + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + return efi.acpi20; +@@ -93,9 +90,7 @@ acpi_physical_address __init acpi_os_get + "System description tables not found\n"); + return 0; + } +- } else +-#endif +- { ++ } else { + acpi_physical_address pa = 0; + + acpi_find_root_pointer(&pa); +--- a/xen/drivers/video/vga.c ++++ b/xen/drivers/video/vga.c +@@ -89,6 +89,7 @@ void __init vga_init(void) + vga_puts = vga_text_puts; + break; + case XEN_VGATYPE_VESA_LFB: ++ case XEN_VGATYPE_EFI_LFB: + vesa_early_init(); + break; + default: +@@ -115,6 +116,7 @@ void __init vga_endboot(void) + memset(video, 0, columns * lines * 2); + break; + case XEN_VGATYPE_VESA_LFB: ++ case XEN_VGATYPE_EFI_LFB: + vesa_endboot(vgacon_keep); + break; + default: +--- a/xen/include/asm-x86/page.h ++++ b/xen/include/asm-x86/page.h +@@ -301,8 +301,14 @@ extern l2_pgentry_t idle_pg_table_l2[ + #elif CONFIG_PAGING_LEVELS == 4 + extern l2_pgentry_t *compat_idle_pg_table_l2; + extern unsigned int m2p_compat_vstart; ++extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES], ++ l2_bootmap[L2_PAGETABLE_ENTRIES]; ++extern l3_pgentry_t l3_xenmap[L3_PAGETABLE_ENTRIES], ++ l3_identmap[L3_PAGETABLE_ENTRIES], ++ l3_bootmap[L3_PAGETABLE_ENTRIES]; + #endif + extern l2_pgentry_t l2_identmap[4*L2_PAGETABLE_ENTRIES]; ++extern l1_pgentry_t l1_identmap[L1_PAGETABLE_ENTRIES]; + void paging_init(void); + void setup_idle_pagetable(void); + #endif /* !defined(__ASSEMBLY__) */ +--- a/xen/include/public/platform.h ++++ b/xen/include/public/platform.h +@@ -118,6 +118,11 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_platform_q + #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 + struct xenpf_firmware_info { + /* IN variables. */ + uint32_t type; +@@ -148,6 +153,24 @@ struct xenpf_firmware_info { + /* must refer to 128-byte buffer */ + XEN_GUEST_HANDLE(uint8) 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 */ ++ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ ++ } vendor; ++ struct { ++ uint64_t addr; ++ uint64_t size; ++ uint64_t attr; ++ uint32_t type; ++ } mem; ++ } efi_info; /* XEN_FW_EFI_INFO */ + } u; + }; + typedef struct xenpf_firmware_info xenpf_firmware_info_t; +--- a/xen/include/public/xen.h ++++ b/xen/include/public/xen.h +@@ -638,6 +638,7 @@ typedef struct dom0_vga_console_info { + uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */ + #define XEN_VGATYPE_TEXT_MODE_3 0x03 + #define XEN_VGATYPE_VESA_LFB 0x23 ++#define XEN_VGATYPE_EFI_LFB 0x70 + + union { + struct { +--- a/xen/include/xen/compat.h ++++ b/xen/include/xen/compat.h +@@ -34,7 +34,7 @@ + /* Cast a compat handle to the specified type of handle. */ + #define compat_handle_cast(chnd, type) ({ \ + type *_x = (__typeof__(**(chnd)._) *)(full_ptr_t)(chnd).c; \ +- (XEN_GUEST_HANDLE(type)) { _x }; \ ++ (COMPAT_HANDLE(type)) { (full_ptr_t)_x }; \ + }) + + #define guest_from_compat_handle(ghnd, chnd) \ +--- a/xen/include/xen/dmi.h ++++ b/xen/include/xen/dmi.h +@@ -36,5 +36,6 @@ extern int dmi_check_system(struct dmi_s + extern char * dmi_get_system_info(int field); + extern void dmi_scan_machine(void); + extern int dmi_get_table(u32 *base, u32 *len); ++extern void dmi_efi_get_table(void *); + + #endif /* __DMI_H__ */ +--- /dev/null ++++ b/xen/include/xen/efi.h +@@ -0,0 +1,38 @@ ++#ifndef __XEN_EFI_H__ ++#define __XEN_EFI_H__ ++ ++#include ++ ++#if defined(__ia64__) ++# #include ++#else ++ ++# if defined(__i386__) ++# define efi_enabled 0 ++# else ++extern const bool_t efi_enabled; ++# endif ++ ++#define EFI_INVALID_TABLE_ADDR (~0UL) ++ ++/* Add fields here only if they need to be referenced from non-EFI code. */ ++struct efi { ++ unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ ++ unsigned long acpi20; /* ACPI table (ACPI 2.0) */ ++ unsigned long smbios; /* SM BIOS table */ ++}; ++ ++extern struct efi efi; ++ ++#endif ++ ++union xenpf_efi_info; ++union compat_pf_efi_info; ++ ++void efi_init_memory(void); ++#ifndef COMPAT ++int efi_get_info(uint32_t idx, union xenpf_efi_info *); ++#endif ++int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *); ++ ++#endif /* __XEN_EFI_H__ */ diff --git a/23615-x86_64-EFI-runtime.patch b/23615-x86_64-EFI-runtime.patch new file mode 100644 index 0000000..5c0023c --- /dev/null +++ b/23615-x86_64-EFI-runtime.patch @@ -0,0 +1,787 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1309249249 -3600 +# Node ID d19e778442673050bba8ea8cf61585902ff81162 +# Parent 8b7d00f2abb21b504f6f8e1a6cc235cee8eb0858 +x86-64: EFI runtime code + +This allows Dom0 access to all suitable EFI runtime services. The +actual calls into EFI are done in "physical" mode, as entering virtual +mode has been determined to be incompatible with kexec (EFI's +SetVirtualAddressMap() can be called only once, and hence the +secondary kernel can't establish its mappings). ("Physical" mode here +being quoted because this is a mode with paging enabled [otherwise +64-bit mode wouldn't work] but all mappings being 1:1.) + +Signed-off-by: Jan Beulich + +--- a/xen/arch/x86/efi/boot.c ++++ b/xen/arch/x86/efi/boot.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -1149,6 +1150,53 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY + for( ; ; ); /* not reached */ + } + ++static __init void copy_mapping(unsigned long mfn, unsigned long end, ++ bool_t (*is_valid)(unsigned long smfn, ++ unsigned long emfn)) ++{ ++ unsigned long next; ++ ++ for ( ; mfn < end; mfn = next ) ++ { ++ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)]; ++ l3_pgentry_t *l3src, *l3dst; ++ unsigned long va = (unsigned long)mfn_to_virt(mfn); ++ ++ next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)); ++ if ( !is_valid(mfn, min(next, end)) ) ++ continue; ++ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) ++ { ++ l3dst = alloc_xen_pagetable(); ++ BUG_ON(!l3dst); ++ clear_page(l3dst); ++ efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] = ++ l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR); ++ } ++ else ++ l3dst = l4e_to_l3e(l4e); ++ l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]); ++ l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)]; ++ } ++} ++ ++static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn) ++{ ++ unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1; ++ ++ return !(smfn & pfn_hole_mask) && ++ find_next_bit(pdx_group_valid, sz, ++ pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz; ++} ++ ++static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn) ++{ ++ return 1; ++} ++ ++#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \ ++ (EFI_PAGE_SHIFT + BITS_PER_LONG - 32)) ++ + void __init efi_init_memory(void) + { + unsigned int i; +@@ -1169,11 +1217,11 @@ void __init efi_init_memory(void) + if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) ) + continue; + ++ desc->VirtualStart = INVALID_VIRTUAL_ADDRESS; ++ + smfn = PFN_DOWN(desc->PhysicalStart); + emfn = PFN_UP(desc->PhysicalStart + len); + +- desc->VirtualStart = 0xBAAADUL << (EFI_PAGE_SHIFT + BITS_PER_LONG - 32); +- + if ( desc->Attribute & EFI_MEMORY_WB ) + /* nothing */; + else if ( desc->Attribute & EFI_MEMORY_WT ) +@@ -1217,5 +1265,34 @@ void __init efi_init_memory(void) + #if 0 /* Incompatible with kexec. */ + efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size, + mdesc_ver, efi_memmap); ++#else ++ /* Set up 1:1 page tables to do runtime calls in "physical" mode. */ ++ efi_l4_pgtable = alloc_xen_pagetable(); ++ BUG_ON(!efi_l4_pgtable); ++ clear_page(efi_l4_pgtable); ++ ++ copy_mapping(0, max_page, ram_range_valid); ++ ++ /* Insert non-RAM runtime mappings. */ ++ for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) ++ { ++ const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; ++ ++ if ( desc->Attribute & EFI_MEMORY_RUNTIME ) ++ { ++ if ( desc->VirtualStart != INVALID_VIRTUAL_ADDRESS ) ++ copy_mapping(PFN_DOWN(desc->PhysicalStart), ++ PFN_UP(desc->PhysicalStart + ++ (desc->NumberOfPages << EFI_PAGE_SHIFT)), ++ rt_range_valid); ++ else ++ /* XXX */; ++ } ++ } ++ ++ /* Insert Xen mappings. */ ++ for ( i = l4_table_offset(HYPERVISOR_VIRT_START); ++ i < l4_table_offset(HYPERVISOR_VIRT_END); ++i ) ++ efi_l4_pgtable[i] = idle_pg_table[i]; + #endif + } +--- a/xen/arch/x86/efi/compat.c ++++ b/xen/arch/x86/efi/compat.c +@@ -4,13 +4,27 @@ + #define efi_get_info efi_compat_get_info + #define xenpf_efi_info compat_pf_efi_info + ++#define efi_runtime_call efi_compat_runtime_call ++#define xenpf_efi_runtime_call compat_pf_efi_runtime_call ++ ++#define xenpf_efi_guid compat_pf_efi_guid ++#define xenpf_efi_time compat_pf_efi_time ++ + #define COMPAT + #undef DEFINE_XEN_GUEST_HANDLE + #define DEFINE_XEN_GUEST_HANDLE DEFINE_COMPAT_HANDLE ++#undef XEN_GUEST_HANDLE ++#define XEN_GUEST_HANDLE COMPAT_HANDLE + #undef guest_handle_okay + #define guest_handle_okay compat_handle_okay + #undef guest_handle_cast + #define guest_handle_cast compat_handle_cast ++#undef __copy_from_guest ++#define __copy_from_guest __copy_from_compat ++#undef copy_from_guest_offset ++#define copy_from_guest_offset copy_from_compat_offset ++#undef copy_to_guest ++#define copy_to_guest copy_to_compat + #undef __copy_to_guest_offset + #define __copy_to_guest_offset __copy_to_compat_offset + #include "runtime.c" +--- a/xen/arch/x86/efi/efi.h ++++ b/xen/arch/x86/efi/efi.h +@@ -5,6 +5,8 @@ + #include + #include + #include ++#include ++#include + + extern unsigned int efi_num_ct; + extern EFI_CONFIGURATION_TABLE *efi_ct; +@@ -16,3 +18,8 @@ extern EFI_RUNTIME_SERVICES *efi_rs; + + extern UINTN efi_memmap_size, efi_mdesc_size; + extern void *efi_memmap; ++ ++extern l4_pgentry_t *efi_l4_pgtable; ++ ++unsigned long efi_rs_enter(void); ++void efi_rs_leave(unsigned long); +--- a/xen/arch/x86/efi/runtime.c ++++ b/xen/arch/x86/efi/runtime.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + + DEFINE_XEN_GUEST_HANDLE(CHAR16); + +@@ -19,6 +20,7 @@ unsigned int __read_mostly efi_fw_revisi + const CHAR16 *__read_mostly efi_fw_vendor; + + EFI_RUNTIME_SERVICES *__read_mostly efi_rs; ++static DEFINE_SPINLOCK(efi_rs_lock); + + UINTN __read_mostly efi_memmap_size; + UINTN __read_mostly efi_mdesc_size; +@@ -30,6 +32,68 @@ struct efi __read_mostly efi = { + .smbios = EFI_INVALID_TABLE_ADDR, + }; + ++l4_pgentry_t *__read_mostly efi_l4_pgtable; ++ ++unsigned long efi_rs_enter(void) ++{ ++ unsigned long cr3 = read_cr3(); ++ ++ spin_lock(&efi_rs_lock); ++ ++ /* prevent fixup_page_fault() from doing anything */ ++ irq_enter(); ++ ++ write_cr3(virt_to_maddr(efi_l4_pgtable)); ++ ++ return cr3; ++} ++ ++void efi_rs_leave(unsigned long cr3) ++{ ++ write_cr3(cr3); ++ irq_exit(); ++ spin_unlock(&efi_rs_lock); ++} ++ ++unsigned long efi_get_time(void) ++{ ++ EFI_TIME time; ++ EFI_STATUS status; ++ unsigned long cr3 = efi_rs_enter(); ++ ++ status = efi_rs->GetTime(&time, NULL); ++ efi_rs_leave(cr3); ++ ++ if ( EFI_ERROR(status) ) ++ return 0; ++ ++ return mktime(time.Year, time.Month, time.Day, ++ time.Hour, time.Minute, time.Second); ++} ++ ++void efi_halt_system(void) ++{ ++ EFI_STATUS status; ++ unsigned long cr3 = efi_rs_enter(); ++ ++ status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); ++ efi_rs_leave(cr3); ++ ++ printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status); ++} ++ ++void efi_reset_system(bool_t warm) ++{ ++ EFI_STATUS status; ++ unsigned long cr3 = efi_rs_enter(); ++ ++ status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold, ++ EFI_SUCCESS, 0, NULL); ++ efi_rs_leave(cr3); ++ ++ printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status); ++} ++ + #endif + + int efi_get_info(uint32_t idx, union xenpf_efi_info *info) +@@ -86,3 +150,267 @@ int efi_get_info(uint32_t idx, union xen + + return 0; + } ++ ++static long gwstrlen(XEN_GUEST_HANDLE(CHAR16) str) ++{ ++ unsigned long len; ++ ++ for ( len = 0; ; ++len ) ++ { ++ CHAR16 c; ++ ++ if ( copy_from_guest_offset(&c, str, len, 1) ) ++ return -EFAULT; ++ if ( !c ) ++ break; ++ } ++ ++ return len; ++} ++ ++static inline EFI_TIME *cast_time(struct xenpf_efi_time *time) ++{ ++#define chk_fld(F, f) \ ++ BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \ ++ offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f)) ++ chk_fld(Year, year); ++ chk_fld(Month, month); ++ chk_fld(Day, day); ++ chk_fld(Hour, hour); ++ chk_fld(Minute, min); ++ chk_fld(Second, sec); ++ chk_fld(Nanosecond, ns); ++ chk_fld(TimeZone, tz); ++ chk_fld(Daylight, daylight); ++#undef chk_fld ++ return (void *)time; ++} ++ ++static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid) ++{ ++#define chk_fld(n) \ ++ BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \ ++ offsetof(EFI_GUID, Data##n) != \ ++ offsetof(struct xenpf_efi_guid, data##n)) ++ chk_fld(1); ++ chk_fld(2); ++ chk_fld(3); ++ chk_fld(4); ++#undef chk_fld ++ return (void *)guid; ++} ++ ++int efi_runtime_call(struct xenpf_efi_runtime_call *op) ++{ ++ unsigned long cr3; ++ EFI_STATUS status = EFI_NOT_STARTED; ++ int rc = 0; ++ ++ switch ( op->function ) ++ { ++ case XEN_EFI_get_time: ++ { ++ EFI_TIME_CAPABILITIES caps; ++ ++ if ( op->misc ) ++ return -EINVAL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps); ++ efi_rs_leave(cr3); ++ ++ if ( !EFI_ERROR(status) ) ++ { ++ op->u.get_time.resolution = caps.Resolution; ++ op->u.get_time.accuracy = caps.Accuracy; ++ if ( caps.SetsToZero ) ++ op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS; ++ } ++ } ++ break; ++ ++ case XEN_EFI_set_time: ++ if ( op->misc ) ++ return -EINVAL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->SetTime(cast_time(&op->u.set_time)); ++ efi_rs_leave(cr3); ++ break; ++ ++ case XEN_EFI_get_wakeup_time: ++ { ++ BOOLEAN enabled, pending; ++ ++ if ( op->misc ) ++ return -EINVAL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->GetWakeupTime(&enabled, &pending, ++ cast_time(&op->u.get_wakeup_time)); ++ efi_rs_leave(cr3); ++ ++ if ( !EFI_ERROR(status) ) ++ { ++ if ( enabled ) ++ op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED; ++ if ( pending ) ++ op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING; ++ } ++ } ++ break; ++ ++ case XEN_EFI_set_wakeup_time: ++ if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE | ++ XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ) ++ return -EINVAL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->SetWakeupTime(!!(op->misc & ++ XEN_EFI_SET_WAKEUP_TIME_ENABLE), ++ (op->misc & ++ XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ? ++ NULL : ++ cast_time(&op->u.set_wakeup_time)); ++ efi_rs_leave(cr3); ++ ++ op->misc = 0; ++ break; ++ ++ case XEN_EFI_get_next_high_monotonic_count: ++ if ( op->misc ) ++ return -EINVAL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->GetNextHighMonotonicCount(&op->misc); ++ efi_rs_leave(cr3); ++ break; ++ ++ case XEN_EFI_get_variable: ++ { ++ CHAR16 *name; ++ long len; ++ unsigned char *data; ++ UINTN size; ++ ++ if ( op->misc ) ++ return -EINVAL; ++ ++ len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16)); ++ if ( len < 0 ) ++ return len; ++ name = xmalloc_array(CHAR16, ++len); ++ if ( !name ) ++ return -ENOMEM; ++ __copy_from_guest(name, op->u.get_variable.name, len); ++ ++ size = op->u.get_variable.size; ++ if ( size ) ++ { ++ data = xmalloc_bytes(size); ++ if ( !data ) ++ { ++ xfree(name); ++ return -ENOMEM; ++ } ++ } ++ else ++ data = NULL; ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->GetVariable( ++ name, cast_guid(&op->u.get_variable.vendor_guid), ++ &op->misc, &size, data); ++ efi_rs_leave(cr3); ++ ++ if ( !EFI_ERROR(status) && ++ copy_to_guest(op->u.get_variable.data, data, size) ) ++ rc = -EFAULT; ++ op->u.get_variable.size = size; ++ ++ xfree(data); ++ xfree(name); ++ } ++ break; ++ ++ case XEN_EFI_set_variable: ++ { ++ CHAR16 *name; ++ long len; ++ unsigned char *data; ++ ++ if ( op->misc ) ++ return -EINVAL; ++ ++ len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16)); ++ if ( len < 0 ) ++ return len; ++ name = xmalloc_array(CHAR16, ++len); ++ if ( !name ) ++ return -ENOMEM; ++ __copy_from_guest(name, op->u.set_variable.name, len); ++ ++ data = xmalloc_bytes(op->u.set_variable.size); ++ if ( !data ) ++ rc = -ENOMEM; ++ else if ( copy_from_guest(data, op->u.set_variable.data, ++ op->u.set_variable.size) ) ++ rc = -EFAULT; ++ else ++ { ++ cr3 = efi_rs_enter(); ++ status = efi_rs->SetVariable( ++ name, cast_guid(&op->u.set_variable.vendor_guid), ++ op->misc, op->u.set_variable.size, data); ++ efi_rs_leave(cr3); ++ } ++ ++ xfree(data); ++ xfree(name); ++ } ++ break; ++ ++ case XEN_EFI_get_next_variable_name: ++ { ++ union { ++ CHAR16 *str; ++ unsigned char *raw; ++ } name; ++ UINTN size; ++ ++ if ( op->misc ) ++ return -EINVAL; ++ ++ size = op->u.get_next_variable_name.size; ++ name.raw = xmalloc_bytes(size); ++ if ( !name.raw ) ++ return -ENOMEM; ++ copy_from_guest(name.raw, op->u.get_next_variable_name.name, size); ++ ++ cr3 = efi_rs_enter(); ++ status = efi_rs->GetNextVariableName( ++ &size, name.str, ++ cast_guid(&op->u.get_next_variable_name.vendor_guid)); ++ efi_rs_leave(cr3); ++ ++ if ( !EFI_ERROR(status) && ++ copy_to_guest(op->u.get_next_variable_name.name, name.raw, size) ) ++ rc = -EFAULT; ++ op->u.get_next_variable_name.size = size; ++ ++ xfree(name.raw); ++ } ++ break; ++ ++ default: ++ return -ENOSYS; ++ } ++ ++#ifndef COMPAT ++ op->status = status; ++#else ++ op->status = (status & 0x3fffffff) | (status >> 62); ++#endif ++ ++ return rc; ++} +--- a/xen/arch/x86/efi/stub.c ++++ b/xen/arch/x86/efi/stub.c +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + + #ifndef efi_enabled + const bool_t efi_enabled = 0; +@@ -8,6 +9,15 @@ const bool_t efi_enabled = 0; + + void __init efi_init_memory(void) { } + ++unsigned long efi_get_time(void) ++{ ++ BUG(); ++ return 0; ++} ++ ++void efi_halt_system(void) { } ++void efi_reset_system(bool_t warm) { } ++ + int efi_get_info(uint32_t idx, union xenpf_efi_info *info) + { + return -ENOSYS; +@@ -15,3 +25,11 @@ int efi_get_info(uint32_t idx, union xen + + int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *) + __attribute__((__alias__("efi_get_info"))); ++ ++int efi_runtime_call(struct xenpf_efi_runtime_call *op) ++{ ++ return -ENOSYS; ++} ++ ++int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *) ++ __attribute__((__alias__("efi_runtime_call"))); +--- a/xen/arch/x86/platform_hypercall.c ++++ b/xen/arch/x86/platform_hypercall.c +@@ -309,6 +309,17 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe + } + break; + ++ case XENPF_efi_runtime_call: ++ ret = xsm_efi_runtime_call(); ++ if ( ret ) ++ break; ++ ++ ret = efi_runtime_call(&op->u.efi_runtime_call); ++ if ( ret == 0 && ++ copy_field_to_guest(u_xenpf_op, op, u.efi_runtime_call) ) ++ ret = -EFAULT; ++ break; ++ + case XENPF_enter_acpi_sleep: + ret = xsm_acpi_sleep(); + if ( ret ) +--- a/xen/arch/x86/shutdown.c ++++ b/xen/arch/x86/shutdown.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -95,6 +96,7 @@ void machine_halt(void) + watchdog_disable(); + console_start_sync(); + local_irq_enable(); ++ efi_halt_system(); + smp_call_function(__machine_halt, NULL, 0); + __machine_halt(NULL); + } +@@ -337,6 +339,8 @@ void machine_restart(unsigned int delay_ + if ( tboot_in_measured_env() ) + tboot_shutdown(TB_SHUTDOWN_REBOOT); + ++ efi_reset_system(reboot_mode != 0); ++ + /* Rebooting needs to touch the page at absolute address 0. */ + *((unsigned short *)__va(0x472)) = reboot_mode; + +--- a/xen/arch/x86/time.c ++++ b/xen/arch/x86/time.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -756,6 +757,13 @@ static unsigned long get_cmos_time(void) + unsigned long res, flags; + int i; + ++ if ( efi_enabled ) ++ { ++ res = efi_get_time(); ++ if ( res ) ++ return res; ++ } ++ + spin_lock_irqsave(&rtc_lock, flags); + + /* read RTC exactly on falling edge of update flag */ +--- a/xen/arch/x86/x86_64/platform_hypercall.c ++++ b/xen/arch/x86/x86_64/platform_hypercall.c +@@ -12,6 +12,7 @@ DEFINE_XEN_GUEST_HANDLE(compat_platform_ + #define do_platform_op(x) compat_platform_op(_##x) + + #define efi_get_info efi_compat_get_info ++#define efi_runtime_call(x) efi_compat_runtime_call(x) + + #define xen_processor_px compat_processor_px + #define xen_processor_px_t compat_processor_px_t +--- a/xen/include/public/platform.h ++++ b/xen/include/public/platform.h +@@ -114,6 +114,77 @@ struct xenpf_platform_quirk { + typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; + DEFINE_XEN_GUEST_HANDLE(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 ++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 { ++ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ ++ unsigned long size; ++ XEN_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; ++ XEN_GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */ ++ struct xenpf_efi_guid vendor_guid; ++ } get_next_variable_name; ++ } u; ++}; ++typedef struct xenpf_efi_runtime_call xenpf_efi_runtime_call_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtime_call_t); ++ + #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 */ +@@ -388,6 +459,7 @@ struct xen_platform_op { + 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; +--- a/xen/include/xen/efi.h ++++ b/xen/include/xen/efi.h +@@ -29,10 +29,18 @@ extern struct efi efi; + union xenpf_efi_info; + union compat_pf_efi_info; + ++struct xenpf_efi_runtime_call; ++struct compat_pf_efi_runtime_call; ++ + void efi_init_memory(void); ++unsigned long efi_get_time(void); ++void efi_halt_system(void); ++void efi_reset_system(bool_t warm); + #ifndef COMPAT + int efi_get_info(uint32_t idx, union xenpf_efi_info *); ++int efi_runtime_call(struct xenpf_efi_runtime_call *); + #endif + int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *); ++int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *); + + #endif /* __XEN_EFI_H__ */ +--- a/xen/include/xsm/xsm.h ++++ b/xen/include/xsm/xsm.h +@@ -131,6 +131,7 @@ struct xsm_operations { + int (*physinfo) (void); + int (*platform_quirk) (uint32_t); + int (*firmware_info) (void); ++ int (*efi_runtime_call) (void); + int (*acpi_sleep) (void); + int (*change_freq) (void); + int (*getidletime) (void); +@@ -546,6 +547,11 @@ static inline int xsm_firmware_info (voi + return xsm_call(firmware_info()); + } + ++static inline int xsm_efi_runtime_call (void) ++{ ++ return xsm_call(efi_runtime_call()); ++} ++ + static inline int xsm_acpi_sleep (void) + { + return xsm_call(acpi_sleep()); diff --git a/23616-x86_64-EFI-MPS.patch b/23616-x86_64-EFI-MPS.patch new file mode 100644 index 0000000..1ea3742 --- /dev/null +++ b/23616-x86_64-EFI-MPS.patch @@ -0,0 +1,150 @@ +References: fate#311376, fate#311529, bnc#578927, bnc#628554 + +# HG changeset patch +# User Jan Beulich +# Date 1309249288 -3600 +# Node ID dffcd8b4c197b58d2acb914d0e07a100e340f7ae +# Parent d19e778442673050bba8ea8cf61585902ff81162 +x86-64: EFI MPS support + +It's not clear this is needed - Linux doesn't use the MPS table even +if available, and no system having one was seen so far. + +Signed-off-by: Jan Beulich + +# HG changeset patch +# User Keir Fraser +# Date 1309268736 -3600 +# Node ID d22b64ccf088db8bfce1d6c4830f08e3e834ec84 +# Parent 6d404796a8e587eb648a66f2859991d385b65eb6 +x86_32: Fix build after EFI MPS patch. + +Signed-off-by: Keir Fraser + +--- a/xen/arch/x86/efi/boot.c ++++ b/xen/arch/x86/efi/boot.c +@@ -897,12 +897,15 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY + { + static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID; + static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID; ++ static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID; + static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID; + + if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) ) + efi.acpi20 = (long)efi_ct[i].VendorTable; + if ( match_guid(&acpi_guid, &efi_ct[i].VendorGuid) ) + efi.acpi = (long)efi_ct[i].VendorTable; ++ if ( match_guid(&mps_guid, &efi_ct[i].VendorGuid) ) ++ efi.mps = (long)efi_ct[i].VendorTable; + if ( match_guid(&smbios_guid, &efi_ct[i].VendorGuid) ) + efi.smbios = (long)efi_ct[i].VendorTable; + } +--- a/xen/arch/x86/efi/runtime.c ++++ b/xen/arch/x86/efi/runtime.c +@@ -29,6 +29,7 @@ void *__read_mostly efi_memmap; + struct efi __read_mostly efi = { + .acpi = EFI_INVALID_TABLE_ADDR, + .acpi20 = EFI_INVALID_TABLE_ADDR, ++ .mps = EFI_INVALID_TABLE_ADDR, + .smbios = EFI_INVALID_TABLE_ADDR, + }; + +--- a/xen/arch/x86/mpparse.c ++++ b/xen/arch/x86/mpparse.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + #include + + #include +@@ -655,6 +657,14 @@ static inline void __init construct_defa + } + } + ++#define FIX_EFI_MPF FIX_KEXEC_BASE_0 ++ ++static __init void efi_unmap_mpf(void) ++{ ++ if (efi_enabled) ++ __set_fixmap(FIX_EFI_MPF, 0, 0); ++} ++ + static struct intel_mp_floating *mpf_found; + + /* +@@ -669,6 +679,7 @@ void __init get_smp_config (void) + * processors, where MPS only supports physical. + */ + if (acpi_lapic && acpi_ioapic) { ++ efi_unmap_mpf(); + printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); + return; + } +@@ -699,6 +709,7 @@ void __init get_smp_config (void) + * override the defaults. + */ + if (!smp_read_mpc((void *)(unsigned long)mpf->mpf_physptr)) { ++ efi_unmap_mpf(); + smp_found_config = 0; + printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); + printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); +@@ -725,6 +737,8 @@ void __init get_smp_config (void) + } else + BUG(); + ++ efi_unmap_mpf(); ++ + printk(KERN_INFO "Processors: %d\n", num_processors); + /* + * Only use the first configuration found. +@@ -779,10 +793,37 @@ static int __init smp_scan_config (unsig + return 0; + } + ++static void __init efi_check_config(void) ++{ ++ struct intel_mp_floating *mpf; ++ ++ if (efi.mps == EFI_INVALID_TABLE_ADDR) ++ return; ++ ++ __set_fixmap(FIX_EFI_MPF, PFN_DOWN(efi.mps), __PAGE_HYPERVISOR); ++ mpf = (void *)fix_to_virt(FIX_EFI_MPF) + ((long)efi.mps & (PAGE_SIZE-1)); ++ ++ if (memcmp(mpf->mpf_signature, "_MP_", 4) == 0 && ++ mpf->mpf_length == 1 && ++ mpf_checksum((void *)mpf, 16) && ++ (mpf->mpf_specification == 1 || mpf->mpf_specification == 4)) { ++ smp_found_config = 1; ++ printk(KERN_INFO "SMP MP-table at %08lx\n", efi.mps); ++ mpf_found = mpf; ++ } ++ else ++ efi_unmap_mpf(); ++} ++ + void __init find_smp_config (void) + { + unsigned int address; + ++ if (efi_enabled) { ++ efi_check_config(); ++ return; ++ } ++ + /* + * FIXME: Linux assumes you have 640K of base ram.. + * this continues the error... +--- a/xen/include/xen/efi.h ++++ b/xen/include/xen/efi.h +@@ -17,6 +17,7 @@ extern const bool_t efi_enabled; + + /* Add fields here only if they need to be referenced from non-EFI code. */ + struct efi { ++ unsigned long mps; /* MPS table */ + unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ + unsigned long acpi20; /* ACPI table (ACPI 2.0) */ + unsigned long smbios; /* SM BIOS table */ diff --git a/32on64-extra-mem.patch b/32on64-extra-mem.patch index 78ac89c..0b652fb 100644 --- a/32on64-extra-mem.patch +++ b/32on64-extra-mem.patch @@ -2,7 +2,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-4.1.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py -@@ -2913,7 +2913,7 @@ class XendDomainInfo: +@@ -2927,7 +2927,7 @@ class XendDomainInfo: self.guest_bitsize = self.image.getBitSize() # Make sure there's enough RAM available for the domain diff --git a/change-vnc-passwd.patch b/change-vnc-passwd.patch new file mode 100644 index 0000000..b59efba --- /dev/null +++ b/change-vnc-passwd.patch @@ -0,0 +1,157 @@ +Add support of change-vnc-password while vm is running. + +Signed-off-by: Chunyan Liu + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/vl.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +@@ -200,7 +200,7 @@ DriveInfo drives_table[MAX_DRIVES+1]; + int nb_drives; + enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; + int vga_ram_size; +-static DisplayState *display_state; ++DisplayState *display_state; + int nographic; + static int curses; + static int sdl; +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/vnc.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/vnc.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/vnc.c +@@ -2591,6 +2591,7 @@ int vnc_display_password(DisplayState *d + if (password && password[0]) { + if (!(vs->password = qemu_strdup(password))) + return -1; ++ vs->auth = VNC_AUTH_VNC; + } + + return 0; +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/xenstore.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/xenstore.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/xenstore.c +@@ -25,6 +25,7 @@ + #include "qemu-timer.h" + #include "qemu-xen.h" + ++extern DisplayState *display_state; + struct xs_handle *xsh = NULL; + static char *media_filename[MAX_DRIVES+1]; + static QEMUTimer *insert_timer = NULL; +@@ -1006,6 +1007,19 @@ static void xenstore_process_dm_command_ + } else if (!strncmp(command, "continue", len)) { + fprintf(logfile, "dm-command: continue after state save\n"); + xen_pause_requested = 0; ++ } else if (!strncmp(command, "chgvncpasswd", len)) { ++ fprintf(logfile, "dm-command: change vnc passwd\n"); ++ if (pasprintf(&path, ++ "/local/domain/0/backend/vfb/%u/0/vncpasswd", domid) == -1) { ++ fprintf(logfile, "out of memory reading dm command parameter\n"); ++ goto out; ++ } ++ par = xs_read(xsh, XBT_NULL, path, &len); ++ if (!par) ++ goto out; ++ if (vnc_display_password(display_state, par) == 0) ++ xenstore_record_dm_state("vncpasswdchged"); ++ free(par); + } else if (!strncmp(command, "usb-add", len)) { + fprintf(logfile, "dm-command: usb-add a usb device\n"); + if (pasprintf(&path, +Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py ++++ xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py +@@ -1489,6 +1489,20 @@ class XendDomainInfo: + target = max_target + self.setMemoryTarget(target) + ++ def chgvncpasswd(self, passwd): ++ if self._stateGet() != DOM_STATE_HALTED: ++ path = '/local/domain/0/backend/vfb/%u/0/' % self.getDomid() ++ xstransact.Write(path, 'vncpasswd', passwd) ++ self.image.signalDeviceModel("chgvncpasswd", "vncpasswdchged") ++ ++ for dev_uuid, (dev_type, dev_info) in self.info['devices'].items(): ++ if dev_type == 'vfb': ++ dev_info['vncpasswd'] = passwd ++ dev_info['other_config']['vncpasswd'] = passwd ++ self.info.device_update(dev_uuid, cfg_xenapi = dev_info) ++ break ++ xen.xend.XendDomain.instance().managed_config_save(self) ++ + def setMemoryTarget(self, target): + """Set the memory target of this domain. + @param target: In MiB. +Index: xen-4.1.1-testing/tools/python/xen/xend/server/XMLRPCServer.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xend/server/XMLRPCServer.py ++++ xen-4.1.1-testing/tools/python/xen/xend/server/XMLRPCServer.py +@@ -95,7 +95,7 @@ methods = ['device_create', 'device_conf + 'destroyDevice','getDeviceSxprs', + 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown', + 'send_sysrq', 'getVCPUInfo', 'waitForDevices', +- 'getRestartCount', 'getBlockDeviceClass'] ++ 'getRestartCount', 'getBlockDeviceClass', 'chgvncpasswd'] + + exclude = ['domain_create', 'domain_restore'] + +Index: xen-4.1.1-testing/tools/python/xen/xm/main.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xm/main.py ++++ xen-4.1.1-testing/tools/python/xen/xm/main.py +@@ -21,6 +21,7 @@ + + """Grand unified management application for Xen. + """ ++import getpass + import atexit + import cmd + import os +@@ -289,6 +290,9 @@ SUBCOMMAND_HELP = { + 'getenforce' : ('', 'Returns the current enforcing mode for the Flask XSM module (Enforcing,Permissive)'), + 'setenforce' : ('[ (Enforcing|1) | (Permissive|0) ]', + 'Modifies the current enforcing mode for the Flask XSM module'), ++ #change vnc password ++ 'change-vnc-passwd' : ('',\ ++ 'Change vnc password'), + } + + SUBCOMMAND_OPTIONS = { +@@ -421,6 +425,7 @@ common_commands = [ + "usb-del", + "domstate", + "vcpu-set", ++ "change-vnc-passwd", + ] + + domain_commands = [ +@@ -462,6 +467,7 @@ domain_commands = [ + "vcpu-list", + "vcpu-pin", + "vcpu-set", ++ "change-vnc-passwd", + ] + + host_commands = [ +@@ -3881,6 +3887,10 @@ def xm_cpupool_migrate(args): + else: + server.xend.cpu_pool.migrate(domname, poolname) + ++def xm_chgvncpasswd(args): ++ arg_check(args, "change-vnc-passwd", 1) ++ pwd = getpass.getpass("Enter new password: ") ++ server.xend.domain.chgvncpasswd(args[0], pwd) + + commands = { + "shell": xm_shell, +@@ -3993,6 +4003,8 @@ commands = { + "usb-del": xm_usb_del, + #domstate + "domstate": xm_domstate, ++ #change vnc password: ++ "change-vnc-passwd": xm_chgvncpasswd, + } + + ## The commands supported by a separate argument parser in xend.xm. diff --git a/disable_emulated_device.diff b/disable_emulated_device.diff index 9074e6e..fde88f6 100644 --- a/disable_emulated_device.diff +++ b/disable_emulated_device.diff @@ -2,7 +2,7 @@ Index: xen-4.1.1-testing/unmodified_drivers/linux-2.6/platform-pci/platform-pci. =================================================================== --- xen-4.1.1-testing.orig/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ xen-4.1.1-testing/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c -@@ -425,6 +425,11 @@ static int __devinit platform_pci_init(s +@@ -426,6 +426,11 @@ static int __devinit platform_pci_init(s platform_mmio = mmio_addr; platform_mmiolen = mmio_len; diff --git a/hv_extid_compatibility.patch b/hv_extid_compatibility.patch index f4826fc..f833e34 100644 --- a/hv_extid_compatibility.patch +++ b/hv_extid_compatibility.patch @@ -10,7 +10,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendConfig.py 'rtc_timeoffset': int, 'parallel': str, 'serial': str, -@@ -515,6 +516,8 @@ class XendConfig(dict): +@@ -517,6 +518,8 @@ class XendConfig(dict): if self.is_hvm(): if 'timer_mode' not in self['platform']: self['platform']['timer_mode'] = 1 @@ -46,16 +46,16 @@ Index: xen-4.1.1-testing/tools/python/xen/xm/create.py gopts.var('acpi', val='ACPI', fn=set_int, default=1, use="Disable or enable ACPI of HVM domain.") -@@ -1091,7 +1095,7 @@ def configure_hvm(config_image, vals): +@@ -1106,7 +1110,7 @@ def configure_hvm(config_image, vals): 'timer_mode', 'usb', 'usbdevice', 'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten', - 'vncunused', 'viridian', 'vpt_align', + 'vncunused', 'vpt_align', + 'watchdog', 'watchdog_action', 'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci', 'memory_sharing' ] - -@@ -1100,6 +1104,10 @@ def configure_hvm(config_image, vals): +@@ -1116,6 +1120,10 @@ def configure_hvm(config_image, vals): config_image.append([a, vals.__dict__[a]]) if vals.vncpasswd is not None: config_image.append(['vncpasswd', vals.vncpasswd]) diff --git a/ioemu-disable-emulated-ide-if-pv.patch b/ioemu-disable-emulated-ide-if-pv.patch index cde361f..4714c8f 100644 --- a/ioemu-disable-emulated-ide-if-pv.patch +++ b/ioemu-disable-emulated-ide-if-pv.patch @@ -24,7 +24,7 @@ Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c =================================================================== --- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/vl.c +++ xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c -@@ -5830,9 +5830,9 @@ int main(int argc, char **argv, char **e +@@ -5852,9 +5852,9 @@ int main(int argc, char **argv, char **e if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s))) fprintf(stderr,"Can not read our own domid: %s\n", msg); else @@ -40,7 +40,7 @@ Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/xenstore.c =================================================================== --- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/xenstore.c +++ xen-4.1.1-testing/tools/ioemu-qemu-xen/xenstore.c -@@ -447,7 +447,7 @@ void xenstore_init(void) +@@ -448,7 +448,7 @@ void xenstore_init(void) } } @@ -49,7 +49,7 @@ Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/xenstore.c { char **e_danger = NULL; char *buf = NULL; -@@ -760,15 +760,19 @@ void xenstore_parse_domain_config(int hv +@@ -761,15 +761,19 @@ void xenstore_parse_domain_config(int hv #endif diff --git a/ioemu-watchdog-ib700-timer.patch b/ioemu-watchdog-ib700-timer.patch new file mode 100644 index 0000000..ea4b46f --- /dev/null +++ b/ioemu-watchdog-ib700-timer.patch @@ -0,0 +1,34 @@ + +Subject: qdev: convert watchdogs +From: Markus Armbruster armbru@redhat.com Fri Aug 21 10:31:34 2009 +0200 +Date: Thu Aug 27 20:35:24 2009 -0500: +Git: 09aaa1602f9381c0e0fb539390b1793e51bdfc7b + +* THIS IS ONLY THE BUG FIX PART OF THE UPSTREAM PATCH * + +Fixes ib700 not to use vm_clock before it is initialized: in +wdt_ib700_init(), called from register_watchdogs(), which runs before +init_timers(). The bug made ib700_write_enable_reg() crash in +qemu_del_timer(). + +Signed-off-by: Markus Armbruster +Signed-off-by: Anthony Liguori + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_ib700.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/wdt_ib700.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_ib700.c +@@ -93,6 +93,7 @@ static int ib700_load(QEMUFile *f, void + /* Create and initialize a virtual IB700 during PC creation. */ + static void ib700_pc_init(PCIBus *unused) + { ++ timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL); + register_savevm("ib700_wdt", -1, 0, ib700_save, ib700_load, NULL); + + register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, NULL); +@@ -108,5 +109,4 @@ static WatchdogTimerModel model = { + void wdt_ib700_init(void) + { + watchdog_add_model(&model); +- timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL); + } diff --git a/ioemu-watchdog-linkage.patch b/ioemu-watchdog-linkage.patch new file mode 100644 index 0000000..aa1831c --- /dev/null +++ b/ioemu-watchdog-linkage.patch @@ -0,0 +1,72 @@ + +Subject: Move watchdog, watchdog_action, give them internal linkage +From: Markus Armbruster armbru@redhat.com Fri Aug 21 10:31:32 2009 +0200 +Date: Thu Aug 27 20:30:23 2009 -0500: +Git: 88b3be201acf64e0bd19782bebd533901c951c87 + +Signed-off-by: Markus Armbruster +Signed-off-by: Anthony Liguori + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/watchdog.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.c +@@ -26,6 +26,16 @@ + #include "sysemu.h" + #include "hw/watchdog.h" + ++/* Possible values for action parameter. */ ++#define WDT_RESET 1 /* Hard reset. */ ++#define WDT_SHUTDOWN 2 /* Shutdown. */ ++#define WDT_POWEROFF 3 /* Quit. */ ++#define WDT_PAUSE 4 /* Pause. */ ++#define WDT_DEBUG 5 /* Prints a message and continues running. */ ++#define WDT_NONE 6 /* Do nothing. */ ++ ++static WatchdogTimerModel *watchdog; ++static int watchdog_action = WDT_RESET; + static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list; + + void watchdog_add_model(WatchdogTimerModel *model) +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.h +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/watchdog.h ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.h +@@ -27,13 +27,6 @@ + extern void wdt_i6300esb_init(void); + extern void wdt_ib700_init(void); + +-/* Possible values for action parameter. */ +-#define WDT_RESET 1 /* Hard reset. */ +-#define WDT_SHUTDOWN 2 /* Shutdown. */ +-#define WDT_POWEROFF 3 /* Quit. */ +-#define WDT_PAUSE 4 /* Pause. */ +-#define WDT_DEBUG 5 /* Prints a message and continues running. */ +-#define WDT_NONE 6 /* Do nothing. */ + + struct WatchdogTimerModel { + LIST_ENTRY(WatchdogTimerModel) entry; +@@ -50,10 +43,6 @@ struct WatchdogTimerModel { + }; + typedef struct WatchdogTimerModel WatchdogTimerModel; + +-/* in vl.c */ +-extern WatchdogTimerModel *watchdog; +-extern int watchdog_action; +- + /* in hw/watchdog.c */ + extern int select_watchdog(const char *p); + extern int select_watchdog_action(const char *action); +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/vl.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +@@ -250,8 +250,6 @@ int no_shutdown = 0; + int cursor_hide = 1; + int graphic_rotate = 0; + int daemonize = 0; +-WatchdogTimerModel *watchdog = NULL; +-int watchdog_action = WDT_RESET; + const char *option_rom[MAX_OPTION_ROMS]; + int nb_option_roms; + int semihosting_enabled = 0; diff --git a/ioemu-watchdog-support.patch b/ioemu-watchdog-support.patch new file mode 100644 index 0000000..12129bd --- /dev/null +++ b/ioemu-watchdog-support.patch @@ -0,0 +1,963 @@ + +Subject: Hardware watchdog +From: Richard W.M. Jones rjones@redhat.com Sat Apr 25 13:56:19 2009 +0100 +Date: Fri May 1 09:44:11 2009 -0500: +Git: 9dd986ccf68f142aaafe543d80cf877716d91d4e + +Here is an updated hardware watchdog patch, which should fix +everything that was raised about the previous version ... + +Signed-off-by: Richard W.M. Jones +Signed-off-by: Anthony Liguori + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/Makefile.target +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/Makefile.target ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/Makefile.target +@@ -580,6 +580,10 @@ OBJS += e1000.o + # Serial mouse + OBJS += msmouse.o + ++# Generic watchdog support and some watchdog devices ++OBJS += watchdog.o ++OBJS += wdt_ib700.o wdt_i6300esb.o ++ + ifeq ($(TARGET_BASE_ARCH), i386) + # Hardware support + ifdef CONFIG_AUDIO +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/pc.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c +@@ -41,6 +41,7 @@ + #include "virtio-balloon.h" + #include "virtio-console.h" + #include "hpet_emul.h" ++#include "watchdog.h" + + #ifdef CONFIG_PASSTHROUGH + #include "pass-through.h" +@@ -1050,6 +1051,8 @@ vga_bios_error: + } + } + ++ watchdog_pc_init(pci_bus); ++ + for(i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.c +=================================================================== +--- /dev/null ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.c +@@ -0,0 +1,136 @@ ++/* ++ * Virtual hardware watchdog. ++ * ++ * Copyright (C) 2009 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ++ * USA. ++ * ++ * By Richard W.M. Jones (rjones@redhat.com). ++ */ ++ ++#include "qemu-common.h" ++#include "sys-queue.h" ++#include "sysemu.h" ++#include "hw/watchdog.h" ++ ++static LIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list; ++ ++void watchdog_add_model(WatchdogTimerModel *model) ++{ ++ LIST_INSERT_HEAD(&watchdog_list, model, entry); ++} ++ ++/* Returns: ++ * 0 = continue ++ * 1 = exit program with error ++ * 2 = exit program without error ++ */ ++int select_watchdog(const char *p) ++{ ++ WatchdogTimerModel *model; ++ ++ if (watchdog) { ++ fprintf(stderr, ++ "qemu: only one watchdog option may be given\n"); ++ return 1; ++ } ++ ++ /* -watchdog ? lists available devices and exits cleanly. */ ++ if (strcmp(p, "?") == 0) { ++ LIST_FOREACH(model, &watchdog_list, entry) { ++ fprintf(stderr, "\t%s\t%s\n", ++ model->wdt_name, model->wdt_description); ++ } ++ return 2; ++ } ++ ++ LIST_FOREACH(model, &watchdog_list, entry) { ++ if (strcasecmp(model->wdt_name, p) == 0) { ++ watchdog = model; ++ return 0; ++ } ++ } ++ ++ fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n"); ++ LIST_FOREACH(model, &watchdog_list, entry) { ++ fprintf(stderr, "\t%s\t%s\n", ++ model->wdt_name, model->wdt_description); ++ } ++ return 1; ++} ++ ++int select_watchdog_action(const char *p) ++{ ++ if (strcasecmp(p, "reset") == 0) ++ watchdog_action = WDT_RESET; ++ else if (strcasecmp(p, "shutdown") == 0) ++ watchdog_action = WDT_SHUTDOWN; ++ else if (strcasecmp(p, "poweroff") == 0) ++ watchdog_action = WDT_POWEROFF; ++ else if (strcasecmp(p, "pause") == 0) ++ watchdog_action = WDT_PAUSE; ++ else if (strcasecmp(p, "debug") == 0) ++ watchdog_action = WDT_DEBUG; ++ else if (strcasecmp(p, "none") == 0) ++ watchdog_action = WDT_NONE; ++ else ++ return -1; ++ ++ return 0; ++} ++ ++/* This actually performs the "action" once a watchdog has expired, ++ * ie. reboot, shutdown, exit, etc. ++ */ ++void watchdog_perform_action(void) ++{ ++ switch(watchdog_action) { ++ case WDT_RESET: /* same as 'system_reset' in monitor */ ++ qemu_system_reset_request(); ++ break; ++ ++ case WDT_SHUTDOWN: /* same as 'system_powerdown' in monitor */ ++ qemu_system_powerdown_request(); ++ break; ++ ++ case WDT_POWEROFF: /* same as 'quit' command in monitor */ ++ exit(0); ++ break; ++ ++ case WDT_PAUSE: /* same as 'stop' command in monitor */ ++ vm_stop(0); ++ break; ++ ++ case WDT_DEBUG: ++ fprintf(stderr, "watchdog: timer fired\n"); ++ break; ++ ++ case WDT_NONE: ++ break; ++ } ++} ++ ++void watchdog_pc_init(PCIBus *pci_bus) ++{ ++ if (watchdog) ++ watchdog->wdt_pc_init(pci_bus); ++} ++ ++void register_watchdogs(void) ++{ ++ wdt_ib700_init(); ++ wdt_i6300esb_init(); ++} +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.h +=================================================================== +--- /dev/null ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/watchdog.h +@@ -0,0 +1,65 @@ ++/* ++ * Virtual hardware watchdog. ++ * ++ * Copyright (C) 2009 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ++ * USA. ++ * ++ * By Richard W.M. Jones (rjones@redhat.com). ++ */ ++ ++#ifndef QEMU_WATCHDOG_H ++#define QEMU_WATCHDOG_H ++ ++extern void wdt_i6300esb_init(void); ++extern void wdt_ib700_init(void); ++ ++/* Possible values for action parameter. */ ++#define WDT_RESET 1 /* Hard reset. */ ++#define WDT_SHUTDOWN 2 /* Shutdown. */ ++#define WDT_POWEROFF 3 /* Quit. */ ++#define WDT_PAUSE 4 /* Pause. */ ++#define WDT_DEBUG 5 /* Prints a message and continues running. */ ++#define WDT_NONE 6 /* Do nothing. */ ++ ++struct WatchdogTimerModel { ++ LIST_ENTRY(WatchdogTimerModel) entry; ++ ++ /* Short name of the device - used to select it on the command line. */ ++ const char *wdt_name; ++ /* Longer description (eg. manufacturer and full model number). */ ++ const char *wdt_description; ++ ++ /* This callback should create/register the device. It is called ++ * indirectly from hw/pc.c when the virtual PC is being set up. ++ */ ++ void (*wdt_pc_init)(PCIBus *pci_bus); ++}; ++typedef struct WatchdogTimerModel WatchdogTimerModel; ++ ++/* in vl.c */ ++extern WatchdogTimerModel *watchdog; ++extern int watchdog_action; ++ ++/* in hw/watchdog.c */ ++extern int select_watchdog(const char *p); ++extern int select_watchdog_action(const char *action); ++extern void watchdog_add_model(WatchdogTimerModel *model); ++extern void watchdog_perform_action(void); ++extern void watchdog_pc_init(PCIBus *pci_bus); ++extern void register_watchdogs(void); ++ ++#endif /* QEMU_WATCHDOG_H */ +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_i6300esb.c +=================================================================== +--- /dev/null ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_i6300esb.c +@@ -0,0 +1,470 @@ ++/* ++ * Virtual hardware watchdog. ++ * ++ * Copyright (C) 2009 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ++ * USA. ++ * ++ * By Richard W.M. Jones (rjones@redhat.com). ++ */ ++ ++#include ++ ++#include "qemu-common.h" ++#include "qemu-timer.h" ++#include "watchdog.h" ++#include "hw.h" ++#include "isa.h" ++#include "pc.h" ++#include "pci.h" ++ ++/*#define I6300ESB_DEBUG 1*/ ++ ++#ifdef I6300ESB_DEBUG ++#define i6300esb_debug(fs,...) \ ++ fprintf(stderr,"i6300esb: %s: "fs,__func__,##__VA_ARGS__) ++#else ++#define i6300esb_debug(fs,...) ++#endif ++ ++#ifndef PCI_DEVICE_ID_INTEL_ESB_9 ++#define PCI_DEVICE_ID_INTEL_ESB_9 0x25ab ++#endif ++ ++/* PCI configuration registers */ ++#define ESB_CONFIG_REG 0x60 /* Config register */ ++#define ESB_LOCK_REG 0x68 /* WDT lock register */ ++ ++/* Memory mapped registers (offset from base address) */ ++#define ESB_TIMER1_REG 0x00 /* Timer1 value after each reset */ ++#define ESB_TIMER2_REG 0x04 /* Timer2 value after each reset */ ++#define ESB_GINTSR_REG 0x08 /* General Interrupt Status Register */ ++#define ESB_RELOAD_REG 0x0c /* Reload register */ ++ ++/* Lock register bits */ ++#define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ ++#define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */ ++#define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */ ++ ++/* Config register bits */ ++#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ ++#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ ++#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ ++ ++/* Reload register bits */ ++#define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ ++ ++/* Magic constants */ ++#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ ++#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */ ++ ++/* Device state. */ ++struct I6300State { ++ PCIDevice dev; /* PCI device state, must be first field. */ ++ ++ int reboot_enabled; /* "Reboot" on timer expiry. The real action ++ * performed depends on the -watchdog-action ++ * param passed on QEMU command line. ++ */ ++ int clock_scale; /* Clock scale. */ ++#define CLOCK_SCALE_1KHZ 0 ++#define CLOCK_SCALE_1MHZ 1 ++ ++ int int_type; /* Interrupt type generated. */ ++#define INT_TYPE_IRQ 0 /* APIC 1, INT 10 */ ++#define INT_TYPE_SMI 2 ++#define INT_TYPE_DISABLED 3 ++ ++ int free_run; /* If true, reload timer on expiry. */ ++ int locked; /* If true, enabled field cannot be changed. */ ++ int enabled; /* If true, watchdog is enabled. */ ++ ++ QEMUTimer *timer; /* The actual watchdog timer. */ ++ ++ uint32_t timer1_preload; /* Values preloaded into timer1, timer2. */ ++ uint32_t timer2_preload; ++ int stage; /* Stage (1 or 2). */ ++ ++ int unlock_state; /* Guest writes 0x80, 0x86 to unlock the ++ * registers, and we transition through ++ * states 0 -> 1 -> 2 when this happens. ++ */ ++ ++ int previous_reboot_flag; /* If the watchdog caused the previous ++ * reboot, this flag will be set. ++ */ ++}; ++ ++typedef struct I6300State I6300State; ++ ++/* This function is called when the watchdog has either been enabled ++ * (hence it starts counting down) or has been keep-alived. ++ */ ++static void i6300esb_restart_timer(I6300State *d, int stage) ++{ ++ int64_t timeout; ++ ++ if (!d->enabled) ++ return; ++ ++ d->stage = stage; ++ ++ if (d->stage <= 1) ++ timeout = d->timer1_preload; ++ else ++ timeout = d->timer2_preload; ++ ++ if (d->clock_scale == CLOCK_SCALE_1KHZ) ++ timeout <<= 15; ++ else ++ timeout <<= 5; ++ ++ /* Get the timeout in units of ticks_per_sec. */ ++ timeout = ticks_per_sec * timeout / 33000000; ++ ++ i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout); ++ ++ qemu_mod_timer(d->timer, qemu_get_clock(vm_clock) + timeout); ++} ++ ++/* This is called when the guest disables the watchdog. */ ++static void i6300esb_disable_timer(I6300State *d) ++{ ++ i6300esb_debug("timer disabled\n"); ++ ++ qemu_del_timer(d->timer); ++} ++ ++static void i6300esb_reset(I6300State *d) ++{ ++ /* XXX We should probably reset other parts of the state here, ++ * but we should also reset our state on general machine reset ++ * too. For now just disable the timer so it doesn't fire ++ * again after the reboot. ++ */ ++ i6300esb_disable_timer(d); ++} ++ ++/* This function is called when the watchdog expires. Note that ++ * the hardware has two timers, and so expiry happens in two stages. ++ * If d->stage == 1 then we perform the first stage action (usually, ++ * sending an interrupt) and then restart the timer again for the ++ * second stage. If the second stage expires then the watchdog ++ * really has run out. ++ */ ++static void i6300esb_timer_expired(void *vp) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ i6300esb_debug("stage %d\n", d->stage); ++ ++ if (d->stage == 1) { ++ /* What to do at the end of stage 1? */ ++ switch (d->int_type) { ++ case INT_TYPE_IRQ: ++ fprintf(stderr, "i6300esb_timer_expired: I would send APIC 1 INT 10 here if I knew how (XXX)\n"); ++ break; ++ case INT_TYPE_SMI: ++ fprintf(stderr, "i6300esb_timer_expired: I would send SMI here if I knew how (XXX)\n"); ++ break; ++ } ++ ++ /* Start the second stage. */ ++ i6300esb_restart_timer(d, 2); ++ } else { ++ /* Second stage expired, reboot for real. */ ++ if (d->reboot_enabled) { ++ d->previous_reboot_flag = 1; ++ watchdog_perform_action(); /* This reboots, exits, etc */ ++ i6300esb_reset(d); ++ } ++ ++ /* In "free running mode" we start stage 1 again. */ ++ if (d->free_run) ++ i6300esb_restart_timer(d, 1); ++ } ++} ++ ++static void i6300esb_config_write(PCIDevice *dev, uint32_t addr, ++ uint32_t data, int len) ++{ ++ I6300State *d = (I6300State *) dev; ++ int old; ++ ++ i6300esb_debug("addr = %x, data = %x, len = %d\n", addr, data, len); ++ ++ if (addr == ESB_CONFIG_REG && len == 2) { ++ d->reboot_enabled = (data & ESB_WDT_REBOOT) == 0; ++ d->clock_scale = ++ (data & ESB_WDT_FREQ) != 0 ? CLOCK_SCALE_1MHZ : CLOCK_SCALE_1KHZ; ++ d->int_type = (data & ESB_WDT_INTTYPE); ++ } else if (addr == ESB_LOCK_REG && len == 1) { ++ if (!d->locked) { ++ d->locked = (data & ESB_WDT_LOCK) != 0; ++ d->free_run = (data & ESB_WDT_FUNC) != 0; ++ old = d->enabled; ++ d->enabled = (data & ESB_WDT_ENABLE) != 0; ++ if (!old && d->enabled) /* Enabled transitioned from 0 -> 1 */ ++ i6300esb_restart_timer(d, 1); ++ else if (!d->enabled) ++ i6300esb_disable_timer(d); ++ } ++ } else { ++ pci_default_write_config(dev, addr, data, len); ++ } ++} ++ ++static uint32_t i6300esb_config_read(PCIDevice *dev, uint32_t addr, int len) ++{ ++ I6300State *d = (I6300State *) dev; ++ uint32_t data; ++ ++ i6300esb_debug ("addr = %x, len = %d\n", addr, len); ++ ++ if (addr == ESB_CONFIG_REG && len == 2) { ++ data = ++ (d->reboot_enabled ? 0 : ESB_WDT_REBOOT) | ++ (d->clock_scale == CLOCK_SCALE_1MHZ ? ESB_WDT_FREQ : 0) | ++ d->int_type; ++ return data; ++ } else if (addr == ESB_LOCK_REG && len == 1) { ++ data = ++ (d->free_run ? ESB_WDT_FUNC : 0) | ++ (d->locked ? ESB_WDT_LOCK : 0) | ++ (d->enabled ? ESB_WDT_ENABLE : 0); ++ return data; ++ } else { ++ return pci_default_read_config(dev, addr, len); ++ } ++} ++ ++static uint32_t i6300esb_mem_readb(void *vp, target_phys_addr_t addr) ++{ ++ i6300esb_debug ("addr = %x\n", (int) addr); ++ ++ return 0; ++} ++ ++static uint32_t i6300esb_mem_readw(void *vp, target_phys_addr_t addr) ++{ ++ uint32_t data = 0; ++ I6300State *d = (I6300State *) vp; ++ ++ i6300esb_debug("addr = %x\n", (int) addr); ++ ++ if (addr == 0xc) { ++ /* The previous reboot flag is really bit 9, but there is ++ * a bug in the Linux driver where it thinks it's bit 12. ++ * Set both. ++ */ ++ data = d->previous_reboot_flag ? 0x1200 : 0; ++ } ++ ++ return data; ++} ++ ++static uint32_t i6300esb_mem_readl(void *vp, target_phys_addr_t addr) ++{ ++ i6300esb_debug("addr = %x\n", (int) addr); ++ ++ return 0; ++} ++ ++static void i6300esb_mem_writeb(void *vp, target_phys_addr_t addr, uint32_t val) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ i6300esb_debug("addr = %x, val = %x\n", (int) addr, val); ++ ++ if (addr == 0xc && val == 0x80) ++ d->unlock_state = 1; ++ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1) ++ d->unlock_state = 2; ++} ++ ++static void i6300esb_mem_writew(void *vp, target_phys_addr_t addr, uint32_t val) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ i6300esb_debug("addr = %x, val = %x\n", (int) addr, val); ++ ++ if (addr == 0xc && val == 0x80) ++ d->unlock_state = 1; ++ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1) ++ d->unlock_state = 2; ++ else { ++ if (d->unlock_state == 2) { ++ if (addr == 0xc) { ++ if ((val & 0x100) != 0) ++ /* This is the "ping" from the userspace watchdog in ++ * the guest ... ++ */ ++ i6300esb_restart_timer(d, 1); ++ ++ /* Setting bit 9 resets the previous reboot flag. ++ * There's a bug in the Linux driver where it sets ++ * bit 12 instead. ++ */ ++ if ((val & 0x200) != 0 || (val & 0x1000) != 0) { ++ d->previous_reboot_flag = 0; ++ } ++ } ++ ++ d->unlock_state = 0; ++ } ++ } ++} ++ ++static void i6300esb_mem_writel(void *vp, target_phys_addr_t addr, uint32_t val) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ i6300esb_debug ("addr = %x, val = %x\n", (int) addr, val); ++ ++ if (addr == 0xc && val == 0x80) ++ d->unlock_state = 1; ++ else if (addr == 0xc && val == 0x86 && d->unlock_state == 1) ++ d->unlock_state = 2; ++ else { ++ if (d->unlock_state == 2) { ++ if (addr == 0) ++ d->timer1_preload = val & 0xfffff; ++ else if (addr == 4) ++ d->timer2_preload = val & 0xfffff; ++ ++ d->unlock_state = 0; ++ } ++ } ++} ++ ++static void i6300esb_map(PCIDevice *dev, int region_num, ++ uint32_t addr, uint32_t size, int type) ++{ ++ static CPUReadMemoryFunc *mem_read[3] = { ++ i6300esb_mem_readb, ++ i6300esb_mem_readw, ++ i6300esb_mem_readl, ++ }; ++ static CPUWriteMemoryFunc *mem_write[3] = { ++ i6300esb_mem_writeb, ++ i6300esb_mem_writew, ++ i6300esb_mem_writel, ++ }; ++ I6300State *d = (I6300State *) dev; ++ int io_mem; ++ ++ i6300esb_debug("addr = %x, size = %x, type = %d\n", addr, size, type); ++ ++ io_mem = cpu_register_io_memory (0, mem_read, mem_write, d); ++ cpu_register_physical_memory (addr, 0x10, io_mem); ++ /* qemu_register_coalesced_mmio (addr, 0x10); ? */ ++} ++ ++static void i6300esb_save(QEMUFile *f, void *vp) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ pci_device_save(&d->dev, f); ++ qemu_put_be32(f, d->reboot_enabled); ++ qemu_put_be32(f, d->clock_scale); ++ qemu_put_be32(f, d->int_type); ++ qemu_put_be32(f, d->free_run); ++ qemu_put_be32(f, d->locked); ++ qemu_put_be32(f, d->enabled); ++ qemu_put_timer(f, d->timer); ++ qemu_put_be32(f, d->timer1_preload); ++ qemu_put_be32(f, d->timer2_preload); ++ qemu_put_be32(f, d->stage); ++ qemu_put_be32(f, d->unlock_state); ++ qemu_put_be32(f, d->previous_reboot_flag); ++} ++ ++static int i6300esb_load(QEMUFile *f, void *vp, int version) ++{ ++ I6300State *d = (I6300State *) vp; ++ ++ if (version != sizeof (I6300State)) ++ return -EINVAL; ++ ++ pci_device_load(&d->dev, f); ++ d->reboot_enabled = qemu_get_be32(f); ++ d->clock_scale = qemu_get_be32(f); ++ d->int_type = qemu_get_be32(f); ++ d->free_run = qemu_get_be32(f); ++ d->locked = qemu_get_be32(f); ++ d->enabled = qemu_get_be32(f); ++ qemu_get_timer(f, d->timer); ++ d->timer1_preload = qemu_get_be32(f); ++ d->timer2_preload = qemu_get_be32(f); ++ d->stage = qemu_get_be32(f); ++ d->unlock_state = qemu_get_be32(f); ++ d->previous_reboot_flag = qemu_get_be32(f); ++ ++ return 0; ++} ++ ++/* Create and initialize a virtual Intel 6300ESB during PC creation. */ ++static void i6300esb_pc_init(PCIBus *pci_bus) ++{ ++ I6300State *d; ++ uint8_t *pci_conf; ++ ++ if (!pci_bus) { ++ fprintf(stderr, "wdt_i6300esb: no PCI bus in this machine\n"); ++ return; ++ } ++ ++ d = (I6300State *) ++ pci_register_device (pci_bus, "i6300esb_wdt", sizeof (I6300State), ++ -1, ++ i6300esb_config_read, i6300esb_config_write); ++ ++ d->reboot_enabled = 1; ++ d->clock_scale = CLOCK_SCALE_1KHZ; ++ d->int_type = INT_TYPE_IRQ; ++ d->free_run = 0; ++ d->locked = 0; ++ d->enabled = 0; ++ d->timer = qemu_new_timer(vm_clock, i6300esb_timer_expired, d); ++ d->timer1_preload = 0xfffff; ++ d->timer2_preload = 0xfffff; ++ d->stage = 1; ++ d->unlock_state = 0; ++ d->previous_reboot_flag = 0; ++ ++ pci_conf = d->dev.config; ++ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL); ++ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_ESB_9); ++ pci_config_set_class(pci_conf, PCI_CLASS_SYSTEM_OTHER); ++ pci_conf[0x0e] = 0x00; ++ ++ pci_register_io_region(&d->dev, 0, 0x10, ++ PCI_ADDRESS_SPACE_MEM, i6300esb_map); ++ ++ register_savevm("i6300esb_wdt", -1, sizeof(I6300State), ++ i6300esb_save, i6300esb_load, d); ++} ++ ++static WatchdogTimerModel model = { ++ .wdt_name = "i6300esb", ++ .wdt_description = "Intel 6300ESB", ++ .wdt_pc_init = i6300esb_pc_init, ++}; ++ ++void wdt_i6300esb_init(void) ++{ ++ watchdog_add_model(&model); ++} +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_ib700.c +=================================================================== +--- /dev/null ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/wdt_ib700.c +@@ -0,0 +1,112 @@ ++/* ++ * Virtual hardware watchdog. ++ * ++ * Copyright (C) 2009 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ++ * USA. ++ * ++ * By Richard W.M. Jones (rjones@redhat.com). ++ */ ++ ++#include "qemu-common.h" ++#include "qemu-timer.h" ++#include "watchdog.h" ++#include "hw.h" ++#include "isa.h" ++#include "pc.h" ++ ++/*#define IB700_DEBUG 1*/ ++ ++#ifdef IB700_DEBUG ++#define ib700_debug(fs,...) \ ++ fprintf(stderr,"ib700: %s: "fs,__func__,##__VA_ARGS__) ++#else ++#define ib700_debug(fs,...) ++#endif ++ ++/* This is the timer. We use a global here because the watchdog ++ * code ensures there is only one watchdog (it is located at a fixed, ++ * unchangable IO port, so there could only ever be one anyway). ++ */ ++static QEMUTimer *timer = NULL; ++ ++/* A write to this register enables the timer. */ ++static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data) ++{ ++ static int time_map[] = { ++ 30, 28, 26, 24, 22, 20, 18, 16, ++ 14, 12, 10, 8, 6, 4, 2, 0 ++ }; ++ int64 timeout; ++ ++ ib700_debug("addr = %x, data = %x\n", addr, data); ++ ++ timeout = (int64_t) time_map[data & 0xF] * ticks_per_sec; ++ qemu_mod_timer(timer, qemu_get_clock (vm_clock) + timeout); ++} ++ ++/* A write (of any value) to this register disables the timer. */ ++static void ib700_write_disable_reg(void *vp, uint32_t addr, uint32_t data) ++{ ++ ib700_debug("addr = %x, data = %x\n", addr, data); ++ ++ qemu_del_timer(timer); ++} ++ ++/* This is called when the watchdog expires. */ ++static void ib700_timer_expired(void *vp) ++{ ++ ib700_debug("watchdog expired\n"); ++ ++ watchdog_perform_action(); ++ qemu_del_timer(timer); ++} ++ ++static void ib700_save(QEMUFile *f, void *vp) ++{ ++ qemu_put_timer(f, timer); ++} ++ ++static int ib700_load(QEMUFile *f, void *vp, int version) ++{ ++ if (version != 0) ++ return -EINVAL; ++ ++ qemu_get_timer(f, timer); ++ ++ return 0; ++} ++ ++/* Create and initialize a virtual IB700 during PC creation. */ ++static void ib700_pc_init(PCIBus *unused) ++{ ++ register_savevm("ib700_wdt", -1, 0, ib700_save, ib700_load, NULL); ++ ++ register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, NULL); ++ register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, NULL); ++} ++ ++static WatchdogTimerModel model = { ++ .wdt_name = "ib700", ++ .wdt_description = "iBASE 700", ++ .wdt_pc_init = ib700_pc_init, ++}; ++ ++void wdt_ib700_init(void) ++{ ++ watchdog_add_model(&model); ++ timer = qemu_new_timer(vm_clock, ib700_timer_expired, NULL); ++} +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/monitor.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/monitor.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/monitor.c +@@ -26,6 +26,7 @@ + #include "hw/pcmcia.h" + #include "hw/pc.h" + #include "hw/pci.h" ++#include "hw/watchdog.h" + #include "gdbstub.h" + #include "net.h" + #include "qemu-char.h" +@@ -531,6 +532,13 @@ static void do_gdbserver(const char *por + } + #endif + ++static void do_watchdog_action(const char *action) ++{ ++ if (select_watchdog_action(action) == -1) { ++ qemu_printf("Unknown watchdog action '%s'\n", action); ++ } ++} ++ + static void term_printc(int c) + { + term_printf("'"); +@@ -1605,6 +1613,8 @@ static const term_cmd_t term_cmds[] = { + "target", "request VM to change it's memory allocation (in MB)" }, + { "set_link", "ss", do_set_link, + "name [up|down]", "change the link status of a network adapter" }, ++ { "watchdog_action", "s", do_watchdog_action, ++ "[reset|shutdown|poweroff|pause|debug|none]", "change watchdog action" }, + { "cpu_set", "is", do_cpu_set_nr, + "cpu [online|offline]", "change cpu state" }, + { NULL, NULL, }, +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/vl.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/vl.c +@@ -30,6 +30,7 @@ + #include "hw/isa.h" + #include "hw/baum.h" + #include "hw/bt.h" ++#include "hw/watchdog.h" + #include "net.h" + #include "console.h" + #include "sysemu.h" +@@ -249,6 +250,8 @@ int no_shutdown = 0; + int cursor_hide = 1; + int graphic_rotate = 0; + int daemonize = 0; ++WatchdogTimerModel *watchdog = NULL; ++int watchdog_action = WDT_RESET; + const char *option_rom[MAX_OPTION_ROMS]; + int nb_option_roms; + int semihosting_enabled = 0; +@@ -4167,6 +4170,10 @@ static void help(int exitcode) + "-startdate select initial date of the clock\n" + "-icount [N|auto]\n" + " enable virtual instruction counter with 2^N clock ticks per instruction\n" ++ "-watchdog i6300esb|ib700\n" ++ " enable virtual hardware watchdog [default=none]\n" ++ "-watchdog-action reset|shutdown|poweroff|pause|debug|none\n" ++ " action when watchdog fires [default=reset]\n" + "-echr chr set terminal escape character instead of ctrl-a\n" + "-virtioconsole c\n" + " set virtio console\n" +@@ -4314,6 +4321,8 @@ enum { + QEMU_OPTION_localtime, + QEMU_OPTION_startdate, + QEMU_OPTION_icount, ++ QEMU_OPTION_watchdog, ++ QEMU_OPTION_watchdog_action, + QEMU_OPTION_echr, + QEMU_OPTION_virtiocon, + QEMU_OPTION_show_cursor, +@@ -4440,6 +4449,8 @@ static const QEMUOption qemu_options[] = + { "localtime", 0, QEMU_OPTION_localtime }, + { "startdate", HAS_ARG, QEMU_OPTION_startdate }, + { "icount", HAS_ARG, QEMU_OPTION_icount }, ++ { "watchdog", HAS_ARG, QEMU_OPTION_watchdog }, ++ { "watchdog-action", HAS_ARG, QEMU_OPTION_watchdog_action }, + { "echr", HAS_ARG, QEMU_OPTION_echr }, + { "virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon }, + { "show-cursor", 0, QEMU_OPTION_show_cursor }, +@@ -4941,6 +4952,8 @@ int main(int argc, char **argv, char **e + tb_size = 0; + autostart= 1; + ++ register_watchdogs(); ++ + optind = 1; + for(;;) { + if (optind >= argc) +@@ -5315,6 +5328,17 @@ int main(int argc, char **argv, char **e + serial_devices[serial_device_index] = optarg; + serial_device_index++; + break; ++ case QEMU_OPTION_watchdog: ++ i = select_watchdog(optarg); ++ if (i > 0) ++ exit (i == 1 ? 1 : 0); ++ break; ++ case QEMU_OPTION_watchdog_action: ++ if (select_watchdog_action(optarg) == -1) { ++ fprintf(stderr, "Unknown -watchdog-action parameter\n"); ++ exit(1); ++ } ++ break; + case QEMU_OPTION_virtiocon: + if (virtio_console_index >= MAX_VIRTIO_CONSOLES) { + fprintf(stderr, "qemu: too many virtio consoles\n"); diff --git a/kernel-boot-hvm.patch b/kernel-boot-hvm.patch new file mode 100644 index 0000000..01bd4f7 --- /dev/null +++ b/kernel-boot-hvm.patch @@ -0,0 +1,245 @@ +Direct kernel boot to HVM guests has regression from xen-3.3 to xen-4.0. +Foreport this feature to latest qemu-xen. Make a fake boot sector with given +kernel and initrd, which could be accessed by hvmloader. + +Signed-off-by: Chunyan Liu + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block.c +@@ -596,6 +596,16 @@ int bdrv_read(BlockDriverState *bs, int6 + + if (bdrv_check_request(bs, sector_num, nb_sectors)) + return -EIO; ++ ++ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { ++ memcpy(buf, bs->boot_sector_data, 512); ++ sector_num++; ++ nb_sectors--; ++ buf += 512; ++ if (nb_sectors == 0) ++ return 0; ++ } ++ + if (drv->bdrv_pread) { + int ret, len; + len = nb_sectors * 512; +@@ -631,6 +641,10 @@ int bdrv_write(BlockDriverState *bs, int + if (bdrv_check_request(bs, sector_num, nb_sectors)) + return -EIO; + ++ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { ++ memcpy(bs->boot_sector_data, buf, 512); ++ } ++ + if (drv->bdrv_pwrite) { + int ret, len, count = 0; + len = nb_sectors * 512; +@@ -934,6 +948,16 @@ void bdrv_guess_geometry(BlockDriverStat + } + } + ++/* force a given boot sector. */ ++void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size) ++{ ++ bs->boot_sector_enabled = 1; ++ if (size > 512) ++ size = 512; ++ memcpy(bs->boot_sector_data, data, size); ++ memset(bs->boot_sector_data + size, 0, 512 - size); ++} ++ + void bdrv_set_geometry_hint(BlockDriverState *bs, + int cyls, int heads, int secs) + { +@@ -1464,6 +1488,14 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDri + if (bdrv_check_request(bs, sector_num, nb_sectors)) + return NULL; + ++ /* XXX: we assume that nb_sectors == 0 is suppored by the async read */ ++ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { ++ memcpy(buf, bs->boot_sector_data, 512); ++ sector_num++; ++ nb_sectors--; ++ buf += 512; ++ } ++ + ret = drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque); + + if (ret) { +@@ -1489,6 +1521,10 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDr + if (bdrv_check_request(bs, sector_num, nb_sectors)) + return NULL; + ++ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { ++ memcpy(bs->boot_sector_data, buf, 512); ++ } ++ + ret = drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque); + + if (ret) { +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block_int.h +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block_int.h ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block_int.h +@@ -122,6 +122,9 @@ struct BlockDriverState { + BlockDriver *drv; /* NULL means no media */ + void *opaque; + ++ int boot_sector_enabled; ++ uint8_t boot_sector_data[512]; ++ + char filename[1024]; + char backing_file[1024]; /* if non zero, the image is a diff of + this file image */ +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/pc.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/pc.c +@@ -474,45 +474,28 @@ static void bochs_bios_init(void) + + /* Generate an initial boot sector which sets state and jump to + a specified vector */ +-static void generate_bootsect(uint8_t *option_rom, +- uint32_t gpr[8], uint16_t segs[6], uint16_t ip) ++static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) + { +- uint8_t rom[512], *p, *reloc; +- uint8_t sum; ++ uint8_t bootsect[512], *p; + int i; ++ int hda; ++ ++ hda = drive_get_index(IF_IDE, 0, 0); ++ if (hda == -1) { ++ fprintf(stderr, "A disk image must be given for 'hda' when booting " ++ "a Linux kernel\n(if you really don't want it, use /dev/zero)\n"); ++ exit(1); ++ } ++ memset(bootsect, 0, sizeof(bootsect)); + +- memset(rom, 0, sizeof(rom)); +- +- p = rom; +- /* Make sure we have an option rom signature */ +- *p++ = 0x55; +- *p++ = 0xaa; +- +- /* ROM size in sectors*/ +- *p++ = 1; +- +- /* Hook int19 */ +- +- *p++ = 0x50; /* push ax */ +- *p++ = 0x1e; /* push ds */ +- *p++ = 0x31; *p++ = 0xc0; /* xor ax, ax */ +- *p++ = 0x8e; *p++ = 0xd8; /* mov ax, ds */ +- +- *p++ = 0xc7; *p++ = 0x06; /* movvw _start,0x64 */ +- *p++ = 0x64; *p++ = 0x00; +- reloc = p; +- *p++ = 0x00; *p++ = 0x00; +- +- *p++ = 0x8c; *p++ = 0x0e; /* mov cs,0x66 */ +- *p++ = 0x66; *p++ = 0x00; +- +- *p++ = 0x1f; /* pop ds */ +- *p++ = 0x58; /* pop ax */ +- *p++ = 0xcb; /* lret */ +- +- /* Actual code */ +- *reloc = (p - rom); ++ /* Copy the MSDOS partition table if possible */ ++ bdrv_read(drives_table[hda].bdrv, 0, bootsect, 1); ++ /* Make sure we have a partition signature */ ++ bootsect[510] = 0x55; ++ bootsect[511] = 0xaa; + ++ /* Actual code */ ++ p = bootsect; + *p++ = 0xfa; /* CLI */ + *p++ = 0xfc; /* CLD */ + +@@ -542,13 +525,7 @@ static void generate_bootsect(uint8_t *o + *p++ = segs[1]; /* CS */ + *p++ = segs[1] >> 8; + +- /* sign rom */ +- sum = 0; +- for (i = 0; i < (sizeof(rom) - 1); i++) +- sum += rom[i]; +- rom[sizeof(rom) - 1] = -sum; +- +- memcpy(option_rom, rom, sizeof(rom)); ++ bdrv_set_boot_sector(drives_table[hda].bdrv, bootsect, sizeof(bootsect)); + } + + static long get_file_size(FILE *f) +@@ -565,8 +542,7 @@ static long get_file_size(FILE *f) + return size; + } + +-static void load_linux(uint8_t *option_rom, +- const char *kernel_filename, ++static void load_linux(const char *kernel_filename, + const char *initrd_filename, + const char *kernel_cmdline) + { +@@ -632,7 +608,9 @@ static void load_linux(uint8_t *option_r + + /* Special pages are placed at end of low RAM: pick an arbitrary one and + * subtract a suitably large amount of padding (64kB) to skip BIOS data. */ +- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram); ++ //xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram); ++ /* BUFIO Page beyond last_pfn, use 0x7ffc instead. Fix ME. */ ++ end_low_ram = 0x7ffc; + end_low_ram = (end_low_ram << 12) - (64*1024); + + /* highest address for loading the initrd */ +@@ -721,7 +699,7 @@ static void load_linux(uint8_t *option_r + memset(gpr, 0, sizeof gpr); + gpr[4] = cmdline_addr-real_addr-16; /* SP (-16 is paranoia) */ + +- generate_bootsect(option_rom, gpr, seg, 0); ++ generate_bootsect(gpr, seg, 0); + #endif + } + +@@ -932,14 +910,6 @@ vga_bios_error: + int size, offset; + + offset = 0; +- if (linux_boot) { +- option_rom_offset = qemu_ram_alloc(TARGET_PAGE_SIZE); +- load_linux(phys_ram_base + option_rom_offset, +- kernel_filename, initrd_filename, kernel_cmdline); +- cpu_register_physical_memory(0xd0000, TARGET_PAGE_SIZE, +- option_rom_offset | IO_MEM_ROM); +- offset = TARGET_PAGE_SIZE; +- } + + for (i = 0; i < nb_option_roms; i++) { + size = get_image_size(option_rom[i]); +@@ -973,6 +943,9 @@ vga_bios_error: + + bochs_bios_init(); + ++ if (linux_boot) ++ load_linux(kernel_filename, initrd_filename, kernel_cmdline); ++ + cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); + i8259 = i8259_init(cpu_irq[0]); + ferr_irq = i8259[13]; +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/block.h +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/block.h ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/block.h +@@ -82,6 +82,7 @@ int64_t bdrv_getlength(BlockDriverState + void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); + void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs); + int bdrv_commit(BlockDriverState *bs); ++void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); + /* async block I/O */ + typedef struct BlockDriverAIOCB BlockDriverAIOCB; + typedef void BlockDriverCompletionFunc(void *opaque, int ret); diff --git a/log-guest-console.patch b/log-guest-console.patch new file mode 100644 index 0000000..067c957 --- /dev/null +++ b/log-guest-console.patch @@ -0,0 +1,141 @@ +Add code to support logging xen-domU console, as what xenconsoled does. Log info +will be saved in /var/log/xen/console/guest-domUname.log. + +Signed-off-by: Chunyan Liu +--- + hw/xen_console.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 71 insertions(+), 0 deletions(-) + +Index: xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/xen_console.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/ioemu-qemu-xen/hw/xen_console.c ++++ xen-4.1.1-testing/tools/ioemu-qemu-xen/hw/xen_console.c +@@ -38,6 +38,8 @@ + #include "qemu-char.h" + #include "xen_backend.h" + ++static int log_guest = 0; ++ + struct buffer { + uint8_t *data; + size_t consumed; +@@ -54,8 +56,24 @@ struct XenConsole { + void *sring; + CharDriverState *chr; + int backlog; ++ int log_fd; + }; + ++static int write_all(int fd, const char* buf, size_t len) ++{ ++ while (len) { ++ ssize_t ret = write(fd, buf, len); ++ if (ret == -1 && errno == EINTR) ++ continue; ++ if (ret < 0) ++ return -1; ++ len -= ret; ++ buf += ret; ++ } ++ ++ return 0; ++} ++ + static void buffer_append(struct XenConsole *con) + { + struct buffer *buffer = &con->buffer; +@@ -83,6 +101,15 @@ static void buffer_append(struct XenCons + intf->out_cons = cons; + xen_be_send_notify(&con->xendev); + ++ if (con->log_fd != -1) { ++ int logret; ++ logret = write_all(con->log_fd, buffer->data + buffer->size - size, size); ++ if (logret < 0) { ++ xen_be_printf(&con->xendev, 1, "Write to log failed on domain %d: %d (%s)\n", ++ con->xendev.dom, errno, strerror(errno)); ++ } ++ } ++ + if (buffer->max_capacity && + buffer->size > buffer->max_capacity) { + /* Discard the middle of the data. */ +@@ -176,6 +203,36 @@ static void xencons_send(struct XenConso + } + } + ++static int create_domain_log(struct XenConsole *con) ++{ ++ char *logfile; ++ char *path, *domname; ++ int fd; ++ const char *logdir = "/var/log/xen/console"; ++ ++ path = xs_get_domain_path(xenstore, con->xendev.dom); ++ domname = xenstore_read_str(path, "name"); ++ free(path); ++ if (!domname) ++ return -1; ++ ++ if (mkdir(logdir, 0755) && errno != EEXIST) ++ { ++ xen_be_printf(&con->xendev, 1, "Directory %s does not exist and fail to create it!", logdir); ++ return -1; ++ } ++ ++ asprintf(&logfile, "%s/guest-%s.log", logdir, domname); ++ qemu_free(domname); ++ ++ fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644); ++ free(logfile); ++ if (fd == -1) ++ xen_be_printf(&con->xendev, 1, "Failed to open log %s: %d (%s)", logfile, errno, strerror(errno)); ++ ++ return fd; ++} ++ + /* -------------------------------------------------------------------- */ + + static int con_init(struct XenDevice *xendev) +@@ -183,6 +240,7 @@ static int con_init(struct XenDevice *xe + struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); + char *type, *dom, label[32]; + const char *output; ++ char *logenv = NULL; + + /* setup */ + dom = xs_get_domain_path(xenstore, con->xendev.dom); +@@ -209,6 +267,10 @@ static int con_init(struct XenDevice *xe + con->chr = qemu_chr_open(label, output, NULL); + xenstore_store_pv_console_info(con->xendev.dev, con->chr, output); + ++ logenv = getenv("XENCONSOLED_TRACE"); ++ if (logenv != NULL && strlen(logenv) == strlen("guest") && !strcmp(logenv, "guest")) { ++ log_guest = 1; ++ } + return 0; + } + +@@ -246,6 +308,9 @@ static int con_initialise(struct XenDevi + con->xendev.remote_port, + con->xendev.local_port, + con->buffer.max_capacity); ++ con->log_fd = -1; ++ if (log_guest) ++ con->log_fd = create_domain_log(con); + return 0; + } + +@@ -264,6 +329,12 @@ static void con_disconnect(struct XenDev + xc_gnttab_munmap(xendev->gnttabdev, con->sring, 1); + con->sring = NULL; + } ++ ++ if (con->log_fd != -1) { ++ close(con->log_fd); ++ con->log_fd = -1; ++ } ++ + } + + static void con_event(struct XenDevice *xendev) diff --git a/supported_module.diff b/supported_module.diff index 351729f..bc71fcc 100644 --- a/supported_module.diff +++ b/supported_module.diff @@ -2,13 +2,12 @@ Make our PV drivers "Novell supported modules" Signed-off-by: K. Y. Srinivasan -Index: xen-4.1.1-testing/unmodified_drivers/linux-2.6/Module.supported -=================================================================== --- /dev/null -+++ xen-4.1.1-testing/unmodified_drivers/linux-2.6/Module.supported -@@ -0,0 +1,5 @@ ++++ b/unmodified_drivers/linux-2.6/Module.supported +@@ -0,0 +1,6 @@ +xen-vbd +xen-platform-pci +xen-vnif +xenbus +xen-balloon ++xen-scsi diff --git a/tools-watchdog-support.patch b/tools-watchdog-support.patch new file mode 100644 index 0000000..ddd60c0 --- /dev/null +++ b/tools-watchdog-support.patch @@ -0,0 +1,149 @@ +Index: xen-4.1.1-testing/tools/python/xen/xm/create.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xm/create.py ++++ xen-4.1.1-testing/tools/python/xen/xm/create.py +@@ -535,6 +535,21 @@ gopts.var('usbdevice', val='NAME', + fn=set_value, default='', + use="Name of USB device to add?") + ++gopts.var('watchdog', val='NAME', ++ fn=set_value, default='', ++ use="Watchdog device to use. May be ib700 or i6300esb") ++ ++gopts.var('watchdog_action', val='reset|shutdown|poweroff|pause|none|dump', ++ fn=set_value, default="reset", ++ use="""Action when watchdog timer expires: ++ - reset: Default, forcefully reset the guest; ++ - shutdown: Gracefully shutdown the guest (not recommended); ++ - poweroff: Forcefully power off the guest; ++ - pause: Pause the guest; ++ - none: Do nothing; ++ - dump: Automatically dump the guest; ++ """) ++ + gopts.var('description', val='NAME', + fn=set_value, default='', + use="Description of a domain") +@@ -1092,6 +1107,7 @@ def configure_hvm(config_image, vals): + 'usb', 'usbdevice', + 'vcpus', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten', + 'vncunused', 'viridian', 'vpt_align', ++ 'watchdog', 'watchdog_action', + 'xauthority', 'xen_extended_power_mgmt', 'xen_platform_pci', + 'memory_sharing' ] + +Index: xen-4.1.1-testing/tools/python/xen/xm/xenapi_create.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xm/xenapi_create.py ++++ xen-4.1.1-testing/tools/python/xen/xm/xenapi_create.py +@@ -1113,7 +1113,9 @@ class sxp2xml: + 'xen_platform_pci', + 'tsc_mode' + 'description', +- 'nomigrate' ++ 'nomigrate', ++ 'watchdog', ++ 'watchdog_action' + ] + + platform_configs = [] +Index: xen-4.1.1-testing/tools/python/xen/xend/image.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xend/image.py ++++ xen-4.1.1-testing/tools/python/xen/xend/image.py +@@ -866,7 +866,8 @@ class HVMImageHandler(ImageHandler): + + dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', + 'localtime', 'serial', 'stdvga', 'isa', +- 'acpi', 'usb', 'usbdevice', 'gfx_passthru' ] ++ 'acpi', 'usb', 'usbdevice', 'gfx_passthru', ++ 'watchdog', 'watchdog_action' ] + + for a in dmargs: + v = vmConfig['platform'].get(a) +@@ -874,6 +875,7 @@ class HVMImageHandler(ImageHandler): + # python doesn't allow '-' in variable names + if a == 'stdvga': a = 'std-vga' + if a == 'keymap': a = 'k' ++ if a == 'watchdog_action': a = 'watchdog-action' + + # Handle booleans gracefully + if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']: +Index: xen-4.1.1-testing/tools/python/xen/xend/XendConfig.py +=================================================================== +--- xen-4.1.1-testing.orig/tools/python/xen/xend/XendConfig.py ++++ xen-4.1.1-testing/tools/python/xen/xend/XendConfig.py +@@ -191,6 +191,8 @@ XENAPI_PLATFORM_CFG_TYPES = { + 'xen_platform_pci': int, + "gfx_passthru": int, + 'oos' : int, ++ 'watchdog': str, ++ 'watchdog_action': str, + } + + # Xen API console 'other_config' keys. +Index: xen-4.1.1-testing/tools/libxl/libxl_dm.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/libxl/libxl_dm.c ++++ xen-4.1.1-testing/tools/libxl/libxl_dm.c +@@ -117,6 +117,12 @@ static char ** libxl_build_device_model_ + flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL); + } + } ++ if (info->watchdog || info->watchdog_action) { ++ flexarray_append(dm_args, "-watchdog"); ++ if (info->watchdog_action) { ++ flexarray_vappend(dm_args, "-watchdog-action", info->watchdog_action, NULL); ++ } ++ } + if (info->soundhw) { + flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL); + } +@@ -253,6 +259,12 @@ static char ** libxl_build_device_model_ + flexarray_vappend(dm_args, "-usbdevice", info->usbdevice, NULL); + } + } ++ if (info->watchdog || info->watchdog_action) { ++ flexarray_append(dm_args, "-watchdog"); ++ if (info->watchdog_action) { ++ flexarray_vappend(dm_args, "-watchdog-action", info->watchdog_action, NULL); ++ } ++ } + if (info->soundhw) { + flexarray_vappend(dm_args, "-soundhw", info->soundhw, NULL); + } +Index: xen-4.1.1-testing/tools/libxl/libxl.idl +=================================================================== +--- xen-4.1.1-testing.orig/tools/libxl/libxl.idl ++++ xen-4.1.1-testing/tools/libxl/libxl.idl +@@ -164,6 +164,8 @@ libxl_device_model_info = Struct("device + ("vcpu_avail", integer, False, "vcpus actually available"), + ("xen_platform_pci", integer, False, "enable/disable the xen platform pci device"), + ("extra", libxl_string_list, False, "extra parameters pass directly to qemu, NULL terminated"), ++ ("watchdog", string, False, "the watchdog device, ib700 or i6300esb"), ++ ("watchdog_action", string, False, "action to take when the watchdog timer expires"), + ], + comment= + """Device Model information. +Index: xen-4.1.1-testing/tools/libxl/xl_cmdimpl.c +=================================================================== +--- xen-4.1.1-testing.orig/tools/libxl/xl_cmdimpl.c ++++ xen-4.1.1-testing/tools/libxl/xl_cmdimpl.c +@@ -365,6 +365,8 @@ static void printf_info(int domid, + printf("\t\t\t(usb %d)\n", dm_info->usb); + printf("\t\t\t(usbdevice %s)\n", dm_info->usbdevice); + printf("\t\t\t(apic %d)\n", dm_info->apic); ++ printf("\t\t\t(watchdog %s)\n", dm_info->watchdog); ++ printf("\t\t\t(watchdog_action %s)\n", dm_info->watchdog_action); + printf("\t\t)\n"); + } else { + printf("\t\t(linux %d)\n", b_info->hvm); +@@ -1142,6 +1144,8 @@ skip_vfb: + xlu_cfg_replace_string (config, "soundhw", &dm_info->soundhw); + if (!xlu_cfg_get_long (config, "xen_platform_pci", &l)) + dm_info->xen_platform_pci = l; ++ xlu_cfg_replace_string (config, "watchdog", &dm_info->watchdog); ++ xlu_cfg_replace_string (config, "watchdog_action", &dm_info->watchdog_action); + + if (!xlu_cfg_get_list(config, "device_model_args", &dmargs, &nr_dmargs, 0)) + { diff --git a/x86-cpufreq-report.patch b/x86-cpufreq-report.patch index cffed3b..f88aea8 100644 --- a/x86-cpufreq-report.patch +++ b/x86-cpufreq-report.patch @@ -1,8 +1,6 @@ -Index: xen-4.1.1-testing/xen/arch/x86/platform_hypercall.c -=================================================================== ---- xen-4.1.1-testing.orig/xen/arch/x86/platform_hypercall.c -+++ xen-4.1.1-testing/xen/arch/x86/platform_hypercall.c -@@ -22,7 +22,7 @@ +--- a/xen/arch/x86/platform_hypercall.c ++++ b/xen/arch/x86/platform_hypercall.c +@@ -23,7 +23,7 @@ #include #include #include @@ -11,7 +9,7 @@ Index: xen-4.1.1-testing/xen/arch/x86/platform_hypercall.c #include #include #include -@@ -62,6 +62,7 @@ long cpu_down_helper(void *data); +@@ -63,6 +63,7 @@ long cpu_down_helper(void *data); ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { ret_t ret = 0; @@ -19,7 +17,7 @@ Index: xen-4.1.1-testing/xen/arch/x86/platform_hypercall.c struct xen_platform_op curop, *op = &curop; if ( !IS_PRIV(current->domain) ) -@@ -493,6 +494,24 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe +@@ -513,6 +514,24 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe op->u.mem_add.epfn, op->u.mem_add.pxm); break; @@ -44,11 +42,9 @@ Index: xen-4.1.1-testing/xen/arch/x86/platform_hypercall.c default: ret = -ENOSYS; break; -Index: xen-4.1.1-testing/xen/include/public/platform.h -=================================================================== ---- xen-4.1.1-testing.orig/xen/include/public/platform.h -+++ xen-4.1.1-testing/xen/include/public/platform.h -@@ -355,6 +355,14 @@ struct xenpf_mem_hotadd +--- a/xen/include/public/platform.h ++++ b/xen/include/public/platform.h +@@ -449,6 +449,14 @@ struct xenpf_mem_hotadd uint32_t flags; }; @@ -63,7 +59,7 @@ Index: xen-4.1.1-testing/xen/include/public/platform.h struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ -@@ -374,6 +382,7 @@ struct xen_platform_op { +@@ -469,6 +477,7 @@ struct xen_platform_op { struct xenpf_cpu_ol cpu_ol; struct xenpf_cpu_hotadd cpu_add; struct xenpf_mem_hotadd mem_add; diff --git a/x86-show-page-walk-early.patch b/x86-show-page-walk-early.patch index 6784654..28c24ee 100644 --- a/x86-show-page-walk-early.patch +++ b/x86-show-page-walk-early.patch @@ -1,6 +1,6 @@ --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c -@@ -160,6 +160,8 @@ static int get_superpage(unsigned long m +@@ -162,6 +162,8 @@ static int get_superpage(unsigned long m #endif static void put_superpage(unsigned long mfn); @@ -21,7 +21,7 @@ printk("%p ", _p(*stk++)); --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c -@@ -123,6 +123,8 @@ void __init paging_init(void) +@@ -121,6 +121,8 @@ void __init paging_init(void) #undef CNT #undef MFN @@ -64,7 +64,7 @@ unmap_domain_page(l1t); --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c -@@ -750,6 +750,8 @@ void __init paging_init(void) +@@ -751,6 +751,8 @@ void __init paging_init(void) #undef CNT #undef MFN diff --git a/xen-changeset.diff b/xen-changeset.diff index d950a7a..4cf1c91 100644 --- a/xen-changeset.diff +++ b/xen-changeset.diff @@ -1,13 +1,11 @@ -Index: xen-4.1.1-testing/xen/Makefile -=================================================================== ---- xen-4.1.1-testing.orig/xen/Makefile -+++ xen-4.1.1-testing/xen/Makefile +--- a/xen/Makefile ++++ b/xen/Makefile @@ -1,3 +1,4 @@ +export XEN_CHANGESET = unavailable # This is the correct place to edit the build version. # All other places this is stored (eg. compile.h) should be autogenerated. export XEN_VERSION = 4 -@@ -82,7 +83,7 @@ delete-unfresh-files: +@@ -91,7 +92,7 @@ delete-unfresh-files: @rm -f $@1 $@2 # compile.h contains dynamic build info. Rebuilt on every 'make' invocation. @@ -16,7 +14,7 @@ Index: xen-4.1.1-testing/xen/Makefile @sed -e 's/@@date@@/$(shell LC_ALL=C date)/g' \ -e 's/@@time@@/$(shell LC_ALL=C date +%T)/g' \ -e 's/@@whoami@@/$(XEN_WHOAMI)/g' \ -@@ -92,10 +93,9 @@ include/xen/compile.h: include/xen/compi +@@ -101,10 +102,9 @@ include/xen/compile.h: include/xen/compi -e 's/@@version@@/$(XEN_VERSION)/g' \ -e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \ -e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \ diff --git a/xen-warnings-unused.diff b/xen-warnings-unused.diff index 8b0d170..5c0abec 100644 --- a/xen-warnings-unused.diff +++ b/xen-warnings-unused.diff @@ -241,7 +241,7 @@ status = fread(&buf, 1, sizeof(*h), rtnl); --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c -@@ -745,7 +745,7 @@ static void __pci_disable_msi(struct msi +@@ -746,7 +746,7 @@ static void __pci_disable_msi(struct msi { struct pci_dev *dev; int pos; @@ -351,7 +351,7 @@ /* read magic: 9 first bits */ --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c -@@ -1001,7 +1001,8 @@ static void local_time_calibration(void) +@@ -1009,7 +1009,8 @@ static void local_time_calibration(void) * System timestamps, extrapolated from local and master oscillators, * taken during this calibration and the previous calibration. */ @@ -363,7 +363,7 @@ /* TSC timestamps taken during this calibration and prev calibration. */ --- a/xen/arch/x86/cpu/amd.c +++ b/xen/arch/x86/cpu/amd.c -@@ -348,7 +348,7 @@ static void __devinit init_amd(struct cp +@@ -391,7 +391,7 @@ static void __devinit init_amd(struct cp { u32 l, h; int mbytes = num_physpages >> (20-PAGE_SHIFT); @@ -482,7 +482,7 @@ union hypercall_input { --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c -@@ -4900,7 +4900,7 @@ static int ptwr_emulated_update( +@@ -4904,7 +4904,7 @@ static int ptwr_emulated_update( { unsigned long mfn; unsigned long unaligned_addr = addr; @@ -493,7 +493,7 @@ struct domain *d = v->domain; --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c -@@ -435,7 +435,8 @@ void destroy_m2p_mapping(struct mem_hota +@@ -436,7 +436,8 @@ void destroy_m2p_mapping(struct mem_hota static int setup_compat_m2p_table(struct mem_hotadd_info *info) { unsigned long i, va, smap, emap, rwva, epfn = info->epfn; @@ -633,7 +633,7 @@ --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c -@@ -375,8 +375,7 @@ int __init construct_dom0( +@@ -376,8 +376,7 @@ int __init construct_dom0( return rc; /* compatibility check */ diff --git a/xen.changes b/xen.changes index ef78797..2138db0 100644 --- a/xen.changes +++ b/xen.changes @@ -1,3 +1,80 @@ +------------------------------------------------------------------- +Wed Jun 29 09:37:05 MDT 2011 - carnold@novell.com + +- fate#309894: Xen needs to correctly understand family 15h CPU + topology +- fate#311376: EFI support in SP2 +- fate#311529: Native UEFI booting under Xen (installation) + 23074-pfn.h.patch + 23571-vtd-fault-verbosity.patch + 23574-x86-dom0-compressed-ELF.patch + 23575-x86-DMI.patch + 23610-x86-topology-info.patch + 23611-amd-fam15-topology.patch + 23613-EFI-headers.patch + 23614-x86_64-EFI-boot.patch + 23615-x86_64-EFI-runtime.patch + 23616-x86_64-EFI-MPS.patch + +------------------------------------------------------------------- +Wed Jun 29 15:01:54 CEST 2011 - jbeulich@novell.com + +- Mark xen-scsi.ko supported (bnc#582265, fate#309459). + +------------------------------------------------------------------- +Tue Jun 28 11:07:10 MDT 2011 - carnold@novell.com + +- fate#310308: Hypervisor assisted watchdog driver + ioemu-watchdog-support.patch + ioemu-watchdog-linkage.patch + ioemu-watchdog-ib700-timer.patch + tools-watchdog-support.patch + +------------------------------------------------------------------- +Mon Jun 27 09:03:17 MDT 2011 - carnold@novell.com + +- bnc#702025 - VUL-0: xen: VT-d (PCI passthrough) MSI trap + injection (CVE-2011-1898) + Fixed in Xen version 4.1.1 + +------------------------------------------------------------------- +Wed Jun 22 18:11:18 CST 2011 - cyliu@novell.com + +- fate#310956: Support Direct Kernel Boot for FV guests + kernel-boot-hvm.patch + +------------------------------------------------------------------- +Wed Jun 22 13:49:22 CST 2011 - cyliu@novell.com + +- fate#310316: Support change vnc password while vm is running + change-vnc-passwd.patch +- fate#310325: Support get domU console log from Dom0 + log-guest-console.patch + +------------------------------------------------------------------- +Wed Jun 22 11:29:47 CEST 2011 - ohering@suse.de + +- fate#311487: remove modprobe.conf files for autoloading of Xen + and Hyper-V drivers + xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch + add dmi modalias to xen-platform-pci.ko + +------------------------------------------------------------------- +Tue Jun 21 14:21:42 MDT 2011 - carnold@novell.com + +- fate#308532: [NONCODE] Remove XEN 32-bit Hypervisor + Modify ExclusiveArch in xen.spec to build only x86_64 + +------------------------------------------------------------------- +Tue Jun 21 08:03:59 MDT 2011 - carnold@novell.com + +- fate#309900 - Add Xen support for SVM Decode Assist in AMD family + 15h +- fate#309902 - Add Xen support for AMD family 12h processors +- fate#309903 - Add Xen support for AMD family 14h processors +- fate#309906 - Add Xen support for performance event counters in + AMD family 15h + ------------------------------------------------------------------- Fri Jun 17 06:37:36 MDT 2011 - carnold@novell.com diff --git a/xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch b/xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch new file mode 100644 index 0000000..30141f5 --- /dev/null +++ b/xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch @@ -0,0 +1,42 @@ +References: fate#311487 + +Provide a modalias entry in xen-plaform-pci.ko to allow early autoloading in +initrd based on /sys/class/dmi/id/modalias + +Signed-off-by: Olaf Hering + +--- + unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: xen-4.1.1-testing/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +=================================================================== +--- xen-4.1.1-testing.orig/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c ++++ xen-4.1.1-testing/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -480,6 +481,18 @@ static struct pci_device_id platform_pci + + MODULE_DEVICE_TABLE(pci, platform_pci_tbl); + ++static const struct dmi_system_id platform_dmi_tbl[] = { ++ { ++ .ident = "Xen PV-on-HVM", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Xen"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HVM domU"), ++ }, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(dmi, platform_dmi_tbl); ++ + static struct pci_driver platform_driver = { + name: DRV_NAME, + probe: platform_pci_init, diff --git a/xen.spec b/xen.spec index 0e0492d..d3af2f1 100644 --- a/xen.spec +++ b/xen.spec @@ -26,6 +26,11 @@ ExclusiveArch: %ix86 x86_64 %define xen_build_dir xen-4.1.1-testing %define with_kmp 1 %define with_stubdom 0 +%ifarch x86_64 +%define with_dom0_support 1 +%else +%define with_dom0_support 0 +%endif %define _fwdefdir /etc/sysconfig/SuSEfirewall2.d/services %if %suse_version > 1140 %define with_xend 0 @@ -67,6 +72,8 @@ BuildRequires: te_latex BuildRequires: tetex %endif %ifarch x86_64 +# EFI +#BuildRequires: libgcc46 gcc46 BuildRequires: glibc-32bit glibc-devel-32bit BuildRequires: gcc-32bit BuildRequires: gcc43-32bit @@ -80,8 +87,8 @@ BuildRequires: glibc-devel %if %{?with_kmp}0 BuildRequires: kernel-source kernel-syms module-init-tools xorg-x11 %endif -Version: 4.1.1_01 -Release: 15 +Version: 4.1.1_02 +Release: 1 License: GPLv2+ Group: System/Kernel AutoReqProv: on @@ -126,35 +133,45 @@ Source20000: xenalyze.hg.tar.bz2 Patch1: 22998-x86-get_page_from_l1e-retcode.patch Patch2: 22999-x86-mod_l1_entry-retcode.patch Patch3: 23000-x86-mod_l2_entry-retcode.patch -Patch4: 23096-x86-hpet-no-cpumask_lock.patch -Patch5: 23099-x86-rwlock-scalability.patch -Patch6: 23103-x86-pirq-guest-eoi-check.patch -Patch7: 23127-vtd-bios-settings.patch -Patch8: 23199-amd-iommu-unmapped-intr-fault.patch -Patch9: 23233-hvm-cr-access.patch -Patch10: 23234-svm-decode-assist-base.patch -Patch11: 23235-svm-decode-assist-crs.patch -Patch12: 23236-svm-decode-assist-invlpg.patch -Patch13: 23238-svm-decode-assist-insn-fetch.patch -Patch14: 23303-cpufreq-misc.patch -Patch15: 23304-amd-oprofile-strings.patch -Patch16: 23305-amd-fam15-xenoprof.patch -Patch17: 23306-amd-fam15-vpmu.patch -Patch18: 23334-amd-fam12+14-vpmu.patch -Patch19: 23383-libxc-rm-static-vars.patch -Patch20: 23437-amd-fam15-TSC-scaling.patch -Patch21: 23462-libxc-cpu-feature.patch -Patch22: 23481-x86-SMEP.patch -Patch23: 23504-x86-SMEP-hvm.patch -Patch24: 23505-x86-cpu-add-arg-check.patch -Patch25: 23508-vmx-proc-based-ctls-probe.patch -Patch26: 23510-hvm-cpuid-DRNG.patch -Patch27: 23511-amd-fam15-no-flush-for-C3.patch -Patch28: 23516-cpuid-ERMS.patch -Patch29: 23538-hvm-pio-emul-no-host-crash.patch -Patch30: 23539-hvm-cpuid-FSGSBASE.patch -Patch31: 23543-x86_64-maddr_to_virt-assertion.patch -Patch32: 23546-fucomip.patch +Patch4: 23074-pfn.h.patch +Patch5: 23096-x86-hpet-no-cpumask_lock.patch +Patch6: 23099-x86-rwlock-scalability.patch +Patch7: 23103-x86-pirq-guest-eoi-check.patch +Patch8: 23127-vtd-bios-settings.patch +Patch9: 23199-amd-iommu-unmapped-intr-fault.patch +Patch10: 23233-hvm-cr-access.patch +Patch11: 23234-svm-decode-assist-base.patch +Patch12: 23235-svm-decode-assist-crs.patch +Patch13: 23236-svm-decode-assist-invlpg.patch +Patch14: 23238-svm-decode-assist-insn-fetch.patch +Patch15: 23303-cpufreq-misc.patch +Patch16: 23304-amd-oprofile-strings.patch +Patch17: 23305-amd-fam15-xenoprof.patch +Patch18: 23306-amd-fam15-vpmu.patch +Patch19: 23334-amd-fam12+14-vpmu.patch +Patch20: 23383-libxc-rm-static-vars.patch +Patch21: 23437-amd-fam15-TSC-scaling.patch +Patch22: 23462-libxc-cpu-feature.patch +Patch23: 23481-x86-SMEP.patch +Patch24: 23504-x86-SMEP-hvm.patch +Patch25: 23505-x86-cpu-add-arg-check.patch +Patch26: 23508-vmx-proc-based-ctls-probe.patch +Patch27: 23510-hvm-cpuid-DRNG.patch +Patch28: 23511-amd-fam15-no-flush-for-C3.patch +Patch29: 23516-cpuid-ERMS.patch +Patch30: 23538-hvm-pio-emul-no-host-crash.patch +Patch31: 23539-hvm-cpuid-FSGSBASE.patch +Patch32: 23543-x86_64-maddr_to_virt-assertion.patch +Patch33: 23546-fucomip.patch +Patch34: 23571-vtd-fault-verbosity.patch +Patch35: 23574-x86-dom0-compressed-ELF.patch +Patch36: 23575-x86-DMI.patch +Patch37: 23610-x86-topology-info.patch +Patch38: 23611-amd-fam15-topology.patch +Patch39: 23613-EFI-headers.patch +Patch40: 23614-x86_64-EFI-boot.patch +Patch41: 23615-x86_64-EFI-runtime.patch +Patch42: 23616-x86_64-EFI-MPS.patch # Upstream qemu patches # Our patches Patch300: xen-config.diff @@ -209,6 +226,7 @@ Patch371: domu-usb-controller.patch Patch372: usb-list.patch Patch373: xend-devid-or-name.patch Patch374: suspend_evtchn_lock.patch +Patch375: log-guest-console.patch # Patches for snapshot support Patch400: snapshot-ioemu-save.patch Patch401: snapshot-ioemu-restore.patch @@ -246,9 +264,15 @@ Patch443: vif-bridge.mtu.patch Patch445: hotplug.losetup.patch Patch446: xend-disable-internal-logrotate.patch Patch447: xend-config-enable-dump-comment.patch +Patch448: change-vnc-passwd.patch +Patch449: kernel-boot-hvm.patch +Patch450: ioemu-watchdog-support.patch +Patch451: ioemu-watchdog-linkage.patch +Patch452: ioemu-watchdog-ib700-timer.patch +Patch453: tools-watchdog-support.patch # Jim's domain lock patch -Patch450: xend-domain-lock.patch -Patch451: xend-domain-lock-sfex.patch +Patch480: xend-domain-lock.patch +Patch481: xend-domain-lock-sfex.patch # Hypervisor and PV driver Patches Patch500: 32on64-extra-mem.patch Patch501: x86-ioapic-ack-default.patch @@ -263,6 +287,7 @@ Patch510: pv-driver-build.patch Patch511: supported_module.diff Patch512: magic_ioport_compat.patch Patch513: xen.sles11sp1.bug684297.xen_oldmem_pfn_is_ram.patch +Patch514: xen.sles11sp1.fate311487.xen_platform_pci.dmistring.patch Patch650: disable_emulated_device.diff Patch651: ioemu-disable-scsi.patch Patch652: ioemu-disable-emulated-ide-if-pv.patch @@ -405,6 +430,7 @@ Authors: -------- Ian Pratt +%if %{?with_dom0_support}0 %package tools License: GPLv2+ Summary: Xen Virtualization: Control tools for domain 0 @@ -461,6 +487,7 @@ use Xen. Authors: -------- Ian Pratt +%endif %package tools-domU License: GPLv2+ @@ -583,6 +610,7 @@ Xen, but is not available for release due to license restrictions. %endif +%if %{?with_dom0_support}0 %package doc-html License: GPLv2+ Summary: Xen Virtualization: HTML documentation @@ -621,6 +649,7 @@ xpdf/kpdf/gpdf/gv/... to read the files in Authors: -------- Ian Pratt +%endif %prep %setup -q -n %xen_build_dir -a 1 -a 20000 @@ -658,6 +687,16 @@ tar xfj %{SOURCE2} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch30 -p1 %patch31 -p1 %patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 %patch300 -p1 %patch301 -p1 %patch302 -p1 @@ -709,6 +748,7 @@ tar xfj %{SOURCE2} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch372 -p1 %patch373 -p1 #%patch374 -p1 suspend_evtchn_lock, buildservice build problem +%patch375 -p1 %patch400 -p1 %patch401 -p1 %patch402 -p1 @@ -743,8 +783,14 @@ tar xfj %{SOURCE2} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch445 -p1 %patch446 -p1 %patch447 -p1 +%patch448 -p1 +%patch449 -p1 %patch450 -p1 %patch451 -p1 +%patch452 -p1 +%patch453 -p1 +%patch480 -p1 +%patch481 -p1 %patch500 -p1 %patch501 -p1 %patch502 -p1 @@ -758,6 +804,7 @@ tar xfj %{SOURCE2} -C $RPM_BUILD_DIR/%{xen_build_dir}/tools %patch511 -p1 %patch512 -p1 %patch513 -p1 +%patch514 -p1 %patch650 -p1 %patch651 -p1 %patch652 -p1 @@ -796,10 +843,16 @@ sed -i "s/XEN_CHANGESET[\t ]*=.*\$/XEN_CHANGESET = %{changeset}/" xen/Makefi RPM_OPT_FLAGS=${RPM_OPT_FLAGS//-fstack-protector/} export CFLAGS="${RPM_OPT_FLAGS}" export RPM_OPT_FLAGS +%if %{?with_dom0_support}0 make -C xenalyze.hg CC="gcc -I../xen/include" %{?_smp_mflags} make -C tools/include/xen-foreign %{?_smp_mflags} make tools docs %{?_smp_mflags} make -C tools/debugger/gdbsx +make -C tools/xen-utils-0.1 XEN_INTREE_BUILD=yes +%else +make -C tools/include/xen-foreign %{?_smp_mflags} +make tools docs %{?_smp_mflags} +%endif %if %{?with_kmp}0 # pv driver modules export XL=/usr/src/linux @@ -816,10 +869,15 @@ for flavor in %flavors_to_build; do cd ../.. done %endif -make -C tools/xen-utils-0.1 XEN_INTREE_BUILD=yes %install export CFLAGS="$RPM_OPT_FLAGS" +%if %{?with_dom0_support}0 +# EFI +#%ifarch x86_64 +#make -C xen install CC=gcc-4.6 max_phys_cpus=%{max_cpus} debug=n crash_debug=n DESTDIR=$RPM_BUILD_ROOT EFI_VENDOR=SuSE %{?_smp_mflags} +#make -C xen clean +#%endif install_xen() { local ext="" @@ -850,7 +908,6 @@ make -C tools/include/xen-foreign %{?_smp_mflags} export XEN_PYTHON_NATIVE_INSTALL=1 make -C tools install \ DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} %{?_smp_mflags} -###cp tools/debugger/gdb/gdb-6.2.1-linux-i386-xen/gdb/gdbserver/gdbserver-xen $RPM_BUILD_ROOT/usr/bin/gdbserver-xen rm -f $RPM_BUILD_ROOT/usr/sbin/{qcow-create,img2qcow,qcow2raw} make -C tools/misc/serial-split install \ DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} %{?_smp_mflags} @@ -860,8 +917,13 @@ ln -s /usr/lib/xen/bin/qemu-dm $RPM_BUILD_ROOT/%{_libdir}/xen/bin/qemu-dm %endif cp -avL xenalyze.hg/dump-raw $RPM_BUILD_ROOT/%{_bindir}/xenalyze.dump-raw cp -avL xenalyze.hg/xenalyze $RPM_BUILD_ROOT/%{_bindir} +%else +make -C tools install DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} %{?_smp_mflags} +make -C tools/misc/serial-split install \ + DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} %{?_smp_mflags} +%endif +# PV driver modules %if %{?with_kmp}0 -# pv driver modules export INSTALL_MOD_PATH=$RPM_BUILD_ROOT export INSTALL_MOD_DIR=updates for flavor in %flavors_to_build; do @@ -871,8 +933,9 @@ done mkdir -p $RPM_BUILD_ROOT/etc/modprobe.d install -m644 %SOURCE20 $RPM_BUILD_ROOT/etc/modprobe.d/xen_pvdrivers.conf %endif +%if %{?with_dom0_support}0 +# Stubdom %if %{?with_stubdom}0 -# stubdom make stubdom %{?_smp_mflags} make -C stubdom install \ DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} \ @@ -883,7 +946,7 @@ ln -s /usr/lib/xen/bin/stubdom-dm $RPM_BUILD_ROOT/usr/lib64/xen/bin/stubdom-dm ln -s /usr/lib/xen/bin/stubdompath.sh $RPM_BUILD_ROOT/usr/lib64/xen/bin/stubdompath.sh %endif %endif -# docs +# Docs make -C docs install \ DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} \ DOCDIR=%{_defaultdocdir}/xen @@ -894,7 +957,9 @@ mkdir -p $RPM_BUILD_ROOT/%{_defaultdocdir}/xen/misc for name in vtpm.txt crashdb.txt sedf_scheduler_mini-HOWTO.txt xenpaging.txt; do install -m 644 docs/misc/$name $RPM_BUILD_ROOT/%{_defaultdocdir}/xen/misc/ done +%endif # init scripts +%if %{?with_dom0_support}0 mkdir -p $RPM_BUILD_ROOT/etc/init.d install %SOURCE6 $RPM_BUILD_ROOT/etc/init.d/xend ln -s /etc/init.d/xend $RPM_BUILD_ROOT/usr/sbin/rcxend @@ -935,6 +1000,7 @@ mkdir -p $RPM_BUILD_ROOT/var/lib/xen/xend-db/domain mkdir -p $RPM_BUILD_ROOT/var/lib/xen/xend-db/migrate mkdir -p $RPM_BUILD_ROOT/var/lib/xen/xend-db/vnet mkdir -p $RPM_BUILD_ROOT/var/log/xen +mkdir -p $RPM_BUILD_ROOT/var/log/xen/console ln -s /var/lib/xen/images $RPM_BUILD_ROOT/etc/xen/images # Bootloader install -m755 %SOURCE9 $RPM_BUILD_ROOT/usr/lib/xen/boot/ @@ -942,7 +1008,6 @@ install -m755 %SOURCE9 $RPM_BUILD_ROOT/usr/lib/xen/boot/ mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d mv $RPM_BUILD_ROOT/etc/udev/rules.d/xen-backend.rules $RPM_BUILD_ROOT/etc/udev/rules.d/40-xen.rules mv $RPM_BUILD_ROOT/etc/udev/rules.d/xend.rules $RPM_BUILD_ROOT/etc/udev/rules.d/40-xend.rules -#%find_lang xen-vm # po files are misnamed upstream # xen utils make -C tools/xen-utils-0.1 install DESTDIR=$RPM_BUILD_ROOT XEN_INTREE_BUILD=yes # Clean up unpackaged files @@ -957,18 +1022,42 @@ rm -f $RPM_BUILD_ROOT/usr/sbin/netfix rm -f $RPM_BUILD_ROOT/%{_libdir}/python%{pyver}/site-packages/*.egg-info rm -rf $RPM_BUILD_ROOT/html rm -rf $RPM_BUILD_ROOT/usr/share/doc/xen/README.* -#rm -f $RPM_BUILD_ROOT/usr/share/xen/create.dtd rm -f $RPM_BUILD_ROOT/%{_libdir}/xen/bin/qemu-dm.debug rm -f $RPM_BUILD_ROOT/%{_bindir}/qemu-img-xen rm -f $RPM_BUILD_ROOT/%{_bindir}/qemu-nbd-xen -# This is necessary because of the build of libconfig for libxl -#rm -rf $RPM_BUILD_ROOT/$RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT/%{_libdir}/debug #install firewall definitions format is described here: #/usr/share/SuSEfirewall2/services/TEMPLATE mkdir -p $RPM_BUILD_ROOT/%{_fwdefdir} install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server +%else +# 32 bit hypervisor no longer supported. Remove dom0 tools. +rm -rf $RPM_BUILD_ROOT/%{_datadir}/doc +rm -rf $RPM_BUILD_ROOT/%{_datadir}/man +rm -rf $RPM_BUILD_ROOT/%{_datadir}/xen +rm -rf $RPM_BUILD_ROOT/%{_datadir}/locale +rm -rf $RPM_BUILD_ROOT/%{_libdir}/xen +rm -rf $RPM_BUILD_ROOT/%{_libdir}/python* +rm -rf $RPM_BUILD_ROOT/usr/sbin +rm -rf $RPM_BUILD_ROOT/etc/bash_completion.d +rm -rf $RPM_BUILD_ROOT/etc/init.d +rm -rf $RPM_BUILD_ROOT/etc/logrotate.d +rm -rf $RPM_BUILD_ROOT/etc/pam.d +rm -rf $RPM_BUILD_ROOT/etc/sysconfig +rm -rf $RPM_BUILD_ROOT/etc/udev +rm -rf $RPM_BUILD_ROOT/etc/xen +rm -rf $RPM_BUILD_ROOT/var +rm -f $RPM_BUILD_ROOT/%{_bindir}/*store* +rm -f $RPM_BUILD_ROOT/%{_bindir}/*trace* +rm -f $RPM_BUILD_ROOT/%{_bindir}/xenalyze* +rm -f $RPM_BUILD_ROOT/%{_bindir}/qemu* +rm -f $RPM_BUILD_ROOT/%{_bindir}/pygrub +rm -f $RPM_BUILD_ROOT/%{_bindir}/remus +rm -f $RPM_BUILD_ROOT/%{_bindir}/tapdisk-ioemu +rm -f $RPM_BUILD_ROOT/%{_bindir}/xencons +%endif +%if %{?with_dom0_support}0 %files %defattr(-,root,root) /boot/xen-%{version}-%{release}.gz @@ -983,12 +1072,18 @@ install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server /boot/xen-syms-dbg /boot/xen-syms-dbg-%{version}-%{release} /boot/xen.gz +# EFI +#%ifarch x86_64 +#/boot/efi/efi/SuSE/xen-%{version}-%{release}.efi +#%endif +%endif %files libs %defattr(-,root,root) %{_libdir}/fs/ %{_libdir}/*.so.* +%if %{?with_dom0_support}0 %files tools %defattr(-,root,root) /usr/bin/xenalyze @@ -1052,6 +1147,7 @@ install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server %dir /var/lib/xen/xend-db/vnet %dir /var/lib/xenstored %dir /var/log/xen +%dir /var/log/xen/console %config /etc/init.d/* %config /etc/logrotate.d/xen %dir %attr(700,root,root) /etc/xen @@ -1118,12 +1214,14 @@ install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server %{_libdir}/python%{pyver}/site-packages/fsimage.so %if %{?with_stubdom}0 /usr/lib/xen/boot/ioemu-stubdom.gz -/usr/lib/xen/boot/pv-grub-x86_32.gz %ifarch x86_64 /usr/lib/xen/boot/pv-grub-x86_64.gz +%else +/usr/lib/xen/boot/pv-grub-x86_32.gz %endif %endif %config %{_fwdefdir}/xend-relocation-server +%endif %files tools-domU %defattr(-,root,root) @@ -1133,11 +1231,12 @@ install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server %files devel %defattr(-,root,root) +%{_bindir}/serial-split %{_libdir}/*.a %{_libdir}/*.so /usr/include/* -/usr/bin/serial-split +%if %{?with_dom0_support}0 %files doc-html %defattr(-,root,root) %{_defaultdocdir}/xen/html @@ -1145,7 +1244,9 @@ install -m 644 %{S:26} $RPM_BUILD_ROOT/%{_fwdefdir}/xend-relocation-server %files doc-pdf %defattr(-,root,root) %{_defaultdocdir}/xen/pdf +%endif +%if %{?with_dom0_support}0 %post tools %if %{?with_xend}0 # with_xend @@ -1205,6 +1306,7 @@ fi if [ -f /usr/bin/qemu-nbd-xen ]; then rm /usr/bin/qemu-nbd-xen fi +%endif %post libs -p /sbin/ldconfig diff --git a/xend-domain-lock-sfex.patch b/xend-domain-lock-sfex.patch index f1c4ed3..3ab5d6b 100644 --- a/xend-domain-lock-sfex.patch +++ b/xend-domain-lock-sfex.patch @@ -223,7 +223,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-4.1.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py -@@ -4499,8 +4499,14 @@ class XendDomainInfo: +@@ -4513,8 +4513,14 @@ class XendDomainInfo: # Return name of host contained in lock file. def get_lock_host(self, path): @@ -240,7 +240,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py hostname = "unknown" try: -@@ -4522,6 +4528,16 @@ class XendDomainInfo: +@@ -4536,6 +4542,16 @@ class XendDomainInfo: path = xoptions.get_xend_domain_lock_path() path = os.path.join(path, self.get_uuid()) @@ -257,7 +257,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py try: if not os.path.exists(path): mkdir.parents(path, stat.S_IRWXU) -@@ -4529,12 +4545,7 @@ class XendDomainInfo: +@@ -4543,12 +4559,7 @@ class XendDomainInfo: log.exception("%s could not be created." % path) raise XendError("%s could not be created." % path) @@ -271,7 +271,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py if status != 0: log.debug("Failed to aqcuire lock: status = %d" % status) raise XendError("The VM is locked and appears to be running on host %s." % self.get_lock_host(path)) -@@ -4551,12 +4562,18 @@ class XendDomainInfo: +@@ -4565,12 +4576,18 @@ class XendDomainInfo: path = xoptions.get_xend_domain_lock_path() path = os.path.join(path, self.get_uuid()) diff --git a/xend-domain-lock.patch b/xend-domain-lock.patch index a25a2f4..e9c8735 100644 --- a/xend-domain-lock.patch +++ b/xend-domain-lock.patch @@ -257,7 +257,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py XendTask.log_progress(0, 30, self._constructDomain) XendTask.log_progress(31, 60, self._initDomain) -@@ -2984,6 +2985,11 @@ class XendDomainInfo: +@@ -2998,6 +2999,11 @@ class XendDomainInfo: self._stateSet(DOM_STATE_HALTED) self.domid = None # Do not push into _stateSet()! @@ -269,7 +269,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py finally: self.refresh_shutdown_lock.release() -@@ -4491,6 +4497,74 @@ class XendDomainInfo: +@@ -4505,6 +4511,74 @@ class XendDomainInfo: def has_device(self, dev_class, dev_uuid): return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) diff --git a/xenpaging.autostart.patch b/xenpaging.autostart.patch index ca3f276..8860a4e 100644 --- a/xenpaging.autostart.patch +++ b/xenpaging.autostart.patch @@ -104,7 +104,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendConfig.py 'loader': str, 'display' : str, 'fda': str, -@@ -514,6 +518,14 @@ class XendConfig(dict): +@@ -516,6 +520,14 @@ class XendConfig(dict): self['platform']['nomigrate'] = 0 if self.is_hvm(): @@ -123,7 +123,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py =================================================================== --- xen-4.1.1-testing.orig/tools/python/xen/xend/XendDomainInfo.py +++ xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py -@@ -2277,6 +2277,8 @@ class XendDomainInfo: +@@ -2291,6 +2291,8 @@ class XendDomainInfo: self.info['name_label'], self.domid, self.info['uuid'], new_name, new_uuid) self._unwatchVm() @@ -132,7 +132,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() # Remove existing vm node in xenstore self._removeVm() -@@ -2948,6 +2950,9 @@ class XendDomainInfo: +@@ -2962,6 +2964,9 @@ class XendDomainInfo: self._createDevices() @@ -142,7 +142,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py self.image.cleanupTmpImages() self.info['start_time'] = time.time() -@@ -2972,6 +2977,8 @@ class XendDomainInfo: +@@ -2986,6 +2991,8 @@ class XendDomainInfo: self.refresh_shutdown_lock.acquire() try: self.unwatchShutdown() @@ -151,7 +151,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() bootloader_tidy(self) -@@ -3056,6 +3063,7 @@ class XendDomainInfo: +@@ -3070,6 +3077,7 @@ class XendDomainInfo: self.image = image.create(self, self.info) if self.image: self._createDevices(True) @@ -159,7 +159,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py self._storeDomDetails() self._registerWatches() self.refreshShutdown() -@@ -3196,6 +3204,8 @@ class XendDomainInfo: +@@ -3210,6 +3218,8 @@ class XendDomainInfo: # could also fetch a parsed note from xenstore fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0 if not fast: @@ -168,7 +168,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xend/XendDomainInfo.py self._releaseDevices() self.testDeviceComplete() self.testvifsComplete() -@@ -3211,6 +3221,8 @@ class XendDomainInfo: +@@ -3225,6 +3235,8 @@ class XendDomainInfo: self._storeDomDetails() self._createDevices() @@ -309,7 +309,7 @@ Index: xen-4.1.1-testing/tools/python/xen/xm/create.py gopts.var('device_model', val='FILE', fn=set_value, default=None, use="Path to device model program.") -@@ -1080,6 +1096,10 @@ def configure_hvm(config_image, vals): +@@ -1095,6 +1111,10 @@ def configure_hvm(config_image, vals): args = [ 'acpi', 'apic', 'boot', 'cpuid', 'cpuid_check',